summaryrefslogtreecommitdiff
diff options
authorMichal Hruby <michal.mhr@gmail.com>2012-08-11 23:29:24 +0200
committerMichal Hruby <michal.mhr@gmail.com>2012-08-11 23:29:24 +0200
commit4b92db359532b713e1f605beecc21faed3b3a47a (patch)
tree5042c81cfa1eaa49706788119d54755206d19211
parent0c9f0ef0dda3d34abf3de49d98a620614b37d8c1 (diff)
parenta9f5b8d6d2db9a6c30f4385696a62ae1b906a2a7 (diff)
Merge Gord's result-iterator branch
(bzr r2547.3.1)
-rw-r--r--UnityCore/CMakeLists.txt2
-rw-r--r--UnityCore/Model-inl.h6
-rw-r--r--UnityCore/Model.h1
-rw-r--r--UnityCore/ResultIterator.cpp150
-rw-r--r--UnityCore/ResultIterator.h103
-rw-r--r--UnityCore/Results.cpp10
-rw-r--r--UnityCore/Results.h4
-rw-r--r--tests/test_results.cpp90
-rw-r--r--tests/test_service_model.c2
9 files changed, 358 insertions, 10 deletions
diff --git a/UnityCore/CMakeLists.txt b/UnityCore/CMakeLists.txt
index 0ae006c41..bfc526410 100644
--- a/UnityCore/CMakeLists.txt
+++ b/UnityCore/CMakeLists.txt
@@ -43,6 +43,7 @@ set (CORE_HEADERS
RadioOptionFilter.h
RatingsFilter.h
Result.h
+ ResultIterator.h
Results.h
SeriesPreview.h
Track.h
@@ -80,6 +81,7 @@ set (CORE_SOURCES
RatingsFilter.cpp
RadioOptionFilter.cpp
Result.cpp
+ ResultIterator.cpp
Results.cpp
SeriesPreview.cpp
Track.cpp
diff --git a/UnityCore/Model-inl.h b/UnityCore/Model-inl.h
index ee5b93895..bb97b821f 100644
--- a/UnityCore/Model-inl.h
+++ b/UnityCore/Model-inl.h
@@ -163,6 +163,12 @@ const RowAdaptor Model<RowAdaptor>::RowAtIndex(std::size_t index)
}
template<class RowAdaptor>
+DeeModelTag* Model<RowAdaptor>::GetTag()
+{
+ return renderer_tag_;
+}
+
+template<class RowAdaptor>
std::size_t Model<RowAdaptor>::get_count()
{
if (model_)
diff --git a/UnityCore/Model.h b/UnityCore/Model.h
index 8eb4d14b2..1c14067a7 100644
--- a/UnityCore/Model.h
+++ b/UnityCore/Model.h
@@ -57,6 +57,7 @@ public:
virtual ~Model();
const RowAdaptor RowAtIndex(std::size_t index);
+ DeeModelTag* GetTag();
nux::Property<std::string> swarm_name;
nux::ROProperty<std::size_t> count;
diff --git a/UnityCore/ResultIterator.cpp b/UnityCore/ResultIterator.cpp
new file mode 100644
index 000000000..9a7387f7a
--- /dev/null
+++ b/UnityCore/ResultIterator.cpp
@@ -0,0 +1,150 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Gordon Allott <gord.allott@canonical.com>
+ */
+
+#include "ResultIterator.h"
+#include <NuxCore/Logger.h>
+namespace unity
+{
+namespace dash
+{
+
+namespace
+{
+ nux::logging::Logger logger("unity.dash.resultiterator");
+}
+
+ResultIterator::ResultIterator(glib::Object<DeeModel> model)
+ : model_(model, glib::AddRef())
+ , iter_(dee_model_get_first_iter(model))
+ , tag_(NULL)
+ , iter_result_(model_, iter_, tag_)
+ , cache_invalidated_(false)
+{
+}
+
+ResultIterator::ResultIterator(glib::Object<DeeModel> model, DeeModelIter* iter, DeeModelTag* tag)
+ : model_(model, glib::AddRef())
+ , iter_(iter)
+ , tag_(tag)
+ , iter_result_(model_, iter_, tag_)
+ , cache_invalidated_(false)
+{
+}
+
+ResultIterator ResultIterator::operator[](int value)
+{
+ return ResultIterator(model_, dee_model_get_iter_at_row(model_, value), tag_);
+}
+
+ResultIterator& ResultIterator::operator=(ResultIterator const& rhs)
+{
+ model_ = rhs.model_;
+ iter_ = rhs.iter_;
+ tag_ = rhs.tag_;
+ iter_result_ = Result(model_, iter_, tag_);
+ cache_invalidated_ = false;
+
+ return *this;
+}
+
+ResultIterator& ResultIterator::operator++()
+{
+ iter_ = dee_model_next(model_, iter_);
+ cache_invalidated_ = true;
+ return *this;
+}
+
+ResultIterator& ResultIterator::operator+=(int count)
+{
+ if (dee_model_is_last(model_, iter_))
+ return *this;
+
+ for (int index = 0; index < count; index++)
+ iter_ = dee_model_next(model_, iter_);
+
+ cache_invalidated_ = true;
+ return *this;
+}
+
+ResultIterator ResultIterator::operator++(int)
+{
+ ResultIterator tmp(*this);
+ operator++();
+ return tmp;
+}
+
+ResultIterator ResultIterator::operator+(int count) const
+{
+ ResultIterator tmp(*this);
+ tmp += count;
+ return tmp;
+}
+
+ResultIterator& ResultIterator::operator--()
+{
+ iter_ = dee_model_prev(model_, iter_);
+ cache_invalidated_ = true;
+ return *this;
+}
+
+ResultIterator& ResultIterator::operator-=(int count)
+{
+ if (dee_model_is_first(model_, iter_))
+ return *this;
+
+ for (int index = 0; index < count; index++)
+ iter_ = dee_model_prev(model_, iter_);
+
+ cache_invalidated_ = true;
+ return *this;
+}
+
+ResultIterator ResultIterator::operator--(int)
+{
+ ResultIterator tmp(*this);
+ operator--();
+ return tmp;
+}
+
+ResultIterator ResultIterator::operator-(int count) const
+{
+ ResultIterator tmp(*this);
+ tmp -= count;
+ return tmp;
+}
+
+Result const& ResultIterator::operator*()
+{
+ if (cache_invalidated_)
+ iter_result_ = Result(model_, iter_, tag_);
+ return iter_result_;
+}
+
+bool const ResultIterator::IsLast()
+{
+ return (dee_model_is_last(model_, iter_));
+}
+
+bool const ResultIterator::IsFirst()
+{
+ return (dee_model_is_first(model_, iter_));
+}
+
+}
+}
diff --git a/UnityCore/ResultIterator.h b/UnityCore/ResultIterator.h
new file mode 100644
index 000000000..a68aafb8f
--- /dev/null
+++ b/UnityCore/ResultIterator.h
@@ -0,0 +1,103 @@
+// -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Gordon Allott <gord.allott@canonical.com>
+ */
+#ifndef UNITY_RESULT_ITERATOR_H
+#define UNITY_RESULT_ITERATOR_H
+
+#include <dee.h>
+#include <iterator>
+#include "Result.h"
+#include "GLibWrapper.h"
+
+namespace unity
+{
+namespace dash
+{
+
+// Provides an iterator that will iterate a DeeModel from a Results object
+// based on the category you give it
+
+class ResultIterator : public std::iterator<std::random_access_iterator_tag, Result>
+{
+public:
+ ResultIterator(glib::Object<DeeModel> model);
+ ResultIterator(glib::Object<DeeModel> model, DeeModelIter* iter_, DeeModelTag* tag);
+ ResultIterator(ResultIterator const& copy) : model_(copy.model_), iter_(copy.iter_), tag_(copy.tag_), iter_result_(copy.iter_result_), cache_invalidated_(false){};
+
+ ResultIterator& operator=(ResultIterator const& rhs);
+
+ //Iterator methods
+ ResultIterator& operator++();
+ ResultIterator operator++(int);
+ ResultIterator& operator+=(int value);
+ ResultIterator operator+(int value) const;
+
+ ResultIterator& operator--();
+ ResultIterator operator--(int);
+ ResultIterator& operator-=(int value);
+ ResultIterator operator-(int value) const;
+
+ ResultIterator operator[](int value);
+ friend inline bool const operator<(const ResultIterator& lhs, const ResultIterator& rhs)
+ {
+ return (dee_model_get_position(lhs.model_, lhs.iter_) < dee_model_get_position(rhs.model_, rhs.iter_));
+ }
+
+ friend inline bool const operator>(const ResultIterator& lhs, const ResultIterator& rhs)
+ {
+ return (dee_model_get_position(lhs.model_, lhs.iter_) > dee_model_get_position(rhs.model_, rhs.iter_));
+ }
+
+ friend inline bool const operator<=(const ResultIterator& lhs, const ResultIterator& rhs)
+ {
+ return (dee_model_get_position(lhs.model_, lhs.iter_) <= dee_model_get_position(rhs.model_, rhs.iter_));
+ }
+
+ friend inline bool const operator>=(const ResultIterator& lhs, const ResultIterator& rhs)
+ {
+ return (dee_model_get_position(lhs.model_, lhs.iter_) >= dee_model_get_position(rhs.model_, rhs.iter_));
+ }
+
+ friend inline bool const operator==(const ResultIterator& lhs, const ResultIterator& rhs)
+ {
+ return (lhs.iter_ == rhs.iter_);
+ }
+
+ friend inline bool operator!=(const ResultIterator& lhs, const ResultIterator& rhs)
+ {
+ return !(lhs == rhs);
+ }
+ Result const& operator*();
+
+ /* convenience methods */
+ bool const IsLast();
+ bool const IsFirst();
+
+private:
+ glib::Object<DeeModel> model_;
+ DeeModelIter* iter_;
+ DeeModelTag* tag_;
+ Result iter_result_;
+ bool cache_invalidated_;
+};
+
+}
+
+}
+
+#endif
diff --git a/UnityCore/Results.cpp b/UnityCore/Results.cpp
index b38c8e77e..8d3d9a654 100644
--- a/UnityCore/Results.cpp
+++ b/UnityCore/Results.cpp
@@ -39,6 +39,16 @@ Results::Results(ModelType model_type)
row_removed.connect(sigc::mem_fun(this, &Results::OnRowRemoved));
}
+ResultIterator Results::begin()
+{
+ return ResultIterator(model(), dee_model_get_first_iter(model()), GetTag());
+}
+
+ResultIterator Results::end()
+{
+ return ResultIterator(model(), dee_model_get_last_iter(model()), GetTag());
+}
+
void Results::OnRowAdded(Result& result)
{
result_added.emit(result);
diff --git a/UnityCore/Results.h b/UnityCore/Results.h
index ca98b9b95..d9d8c6108 100644
--- a/UnityCore/Results.h
+++ b/UnityCore/Results.h
@@ -24,6 +24,7 @@
#include "Model.h"
#include "Result.h"
+#include "ResultIterator.h"
namespace unity
{
@@ -38,6 +39,9 @@ public:
Results();
Results(ModelType model_type);
+ ResultIterator begin();
+ ResultIterator end();
+
sigc::signal<void, Result const&> result_added;
sigc::signal<void, Result const&> result_changed;
sigc::signal<void, Result const&> result_removed;
diff --git a/tests/test_results.cpp b/tests/test_results.cpp
index 730430333..e4b4d5165 100644
--- a/tests/test_results.cpp
+++ b/tests/test_results.cpp
@@ -3,11 +3,13 @@
#include <UnityCore/GLibWrapper.h>
#include <UnityCore/Results.h>
+#include <UnityCore/ResultIterator.h>
#include "test_utils.h"
using namespace std;
using namespace unity::dash;
+using namespace unity;
namespace
{
@@ -35,27 +37,97 @@ TEST(TestResults, TestSynchronization)
EXPECT_EQ(model.count, n_rows);
}
+TEST(TestResults, TestFilterValid)
+{
+ Results model;
+ DeeFilter filter;
+
+ model.swarm_name = swarm_name;
+ WaitForSynchronize(model);
+
+ dee_filter_new_for_any_column(2, g_variant_new_uint32(1), &filter);
+ glib::Object<DeeModel> filter_model(dee_filter_model_new(model.model(), &filter));
+
+ unsigned int i = 0;
+ for (ResultIterator iter(filter_model); !iter.IsLast(); ++iter)
+ {
+ EXPECT_EQ((*iter).category_index(), 1);
+ i++;
+ }
+
+ EXPECT_EQ(i, 50);
+}
+
TEST(TestResults, TestRowsValid)
{
Results model;
model.swarm_name = swarm_name;
WaitForSynchronize(model);
+
+ ResultIterator iter(model.model);
+ unsigned int i = 0;
+ for (Result result : model)
+ {
+ //Result adaptor = *iter;
+ unity::glib::String tmp(g_strdup_printf("Result%d", i));
+ string value = tmp.Str();
+ EXPECT_EQ(result.uri(), value);
+ EXPECT_EQ(result.icon_hint(), value);
+ EXPECT_EQ(result.category_index(), (i / 50));
+ EXPECT_EQ(result.mimetype(), value);
+ EXPECT_EQ(result.name(), value);
+ EXPECT_EQ(result.comment(), value);
+ EXPECT_EQ(result.dnd_uri(), value);
+ i++;
+ }
- for (unsigned int i = 0; i < n_rows; i++)
+ //test reading a subset
+ i = 20;
+ for (auto iter = model.begin() + i; iter != model.end(); ++iter)
{
- Result adaptor = model.RowAtIndex(i);
+ Result result = (*iter);
+ unity::glib::String tmp(g_strdup_printf("Result%d", i));
+ string value = tmp.Str();
+ EXPECT_EQ(result.uri(), value);
+ i++;
+ }
+ // test post incrementor
+ i = 20;
+ for (auto iter = model.begin() + i; iter != model.end(); iter++)
+ {
+ Result result = (*iter);
unity::glib::String tmp(g_strdup_printf("Result%d", i));
string value = tmp.Str();
- EXPECT_EQ(adaptor.uri, value);
- EXPECT_EQ(adaptor.icon_hint, value);
- EXPECT_EQ(adaptor.category_index, i);
- EXPECT_EQ(adaptor.mimetype, value);
- EXPECT_EQ(adaptor.name, value);
- EXPECT_EQ(adaptor.comment, value);
- EXPECT_EQ(adaptor.dnd_uri, value);
+ EXPECT_EQ(result.uri(), value);
+ i++;
}
+
+ // test equality
+ EXPECT_TRUE(model.begin() == model.begin());
+ EXPECT_TRUE(model.begin() != model.end());
+
+ EXPECT_FALSE(model.begin().IsLast());
+ EXPECT_FALSE(model.end().IsFirst());
+ EXPECT_TRUE(model.begin().IsFirst());
+ EXPECT_TRUE(model.end().IsLast());
+
+ EXPECT_TRUE(model.begin() < model.end());
+ EXPECT_FALSE(model.end() < model.begin());
+ EXPECT_TRUE(model.end() > model.begin());
+ EXPECT_FALSE(model.begin() > model.end());
+ EXPECT_TRUE(model.begin() <= model.end());
+ EXPECT_FALSE(model.end() <= model.begin());
+ EXPECT_TRUE(model.end() >= model.begin());
+ EXPECT_FALSE(model.begin() >= model.end());
+
+
+ EXPECT_TRUE(model.begin() + 20 > model.begin());
+ EXPECT_TRUE(model.begin() + 20 > model.begin() + 19);
+ EXPECT_TRUE(model.end() - 20 < model.end());
+ EXPECT_TRUE(model.end() - 20 < model.end() - 19);
+
}
// We're testing the model's ability to store and retrieve random pointers
diff --git a/tests/test_service_model.c b/tests/test_service_model.c
index 8acdda48f..95f07f615 100644
--- a/tests/test_service_model.c
+++ b/tests/test_service_model.c
@@ -58,7 +58,7 @@ service_model_create_results(ServiceModel* self)
dee_model_append(self->results_model_,
name,
name,
- (guint)i,
+ (guint)(i/50), // new category every 50 results
name,
name,
name,