@@ -0,0 +1,214 @@
1+/*
2+* Copyright (C) 2011, 2013 Canonical, Ltd.
3+*
4+* This program is free software; you can redistribute it and/or modify
5+* it under the terms of the GNU General Public License as published by
6+* the Free Software Foundation; version 3.
7+*
8+* This program is distributed in the hope that it will be useful,
9+* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+* GNU General Public License for more details.
12+*
13+* You should have received a copy of the GNU General Public License
14+* along with this program. If not, see <http://www.gnu.org/licenses/>.
15+*/
16+
17+#include "filtersbindingstest.h"
18+
19+// libunity-core
20+#include <UnityCore/Filter.h>
21+#include <UnityCore/MultiRangeFilter.h>
22+
23+// Qt
24+#include <QTest>
25+#include <QSignalSpy>
26+
27+// libunity
28+#include <unity.h>
29+
30+#include <dee.h>
31+
32+// local
33+#include "filter.h"
34+#include "multirangefilter.h"
35+#include "combinedfilteroption.h"
36+
37+void FiltersBindingsTest::initTestCase()
38+{
39+}
40+
41+GVariant *createOptions(int numOfOptions)
42+{
43+ auto vtype = g_variant_type_new("a(sssb)");
44+ auto vb = g_variant_builder_new(vtype);
45+ for (int i = 0; i<numOfOptions; i++) {
46+ const std::string optId = "opt" + std::to_string(i);
47+ const std::string optName = "Option " + std::to_string(i);
48+ g_variant_builder_add(vb, "(sssb)", optId.c_str(), optName.c_str(), "", false);
49+ }
50+ return g_variant_builder_end(vb);
51+}
52+
53+DeeModel* createFilterModel()
54+{
55+ const char* filter_schema[8] = {"s", "s", "s", "s", "a{sv}", "b", "b", "b"};
56+ auto model = dee_sequence_model_new();
57+ dee_model_set_schema_full (DEE_MODEL(model), filter_schema, 8);
58+ return model;
59+}
60+
61+void createMultiRangeFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount)
62+{
63+ GVariant* row[8];
64+
65+ row[0] = g_variant_new_string(id.c_str());
66+ row[1] = g_variant_new_string(name.c_str());
67+ row[2] = g_variant_new_string(""); // icon hint
68+ row[3] = g_variant_new_string("filter-multirange"); // renderer
69+
70+ GVariant *children[2];
71+ GVariant *key1 = g_variant_new_string("show-all-button");
72+ GVariant *key2 = g_variant_new_string("options");
73+ children[0] = g_variant_new_dict_entry(key1, g_variant_new_variant(g_variant_new_boolean(false)));
74+ children[1] = g_variant_new_dict_entry(key2, g_variant_new_variant(createOptions(optionCount)));
75+ auto fhints = g_variant_new_array(G_VARIANT_TYPE("{sv}"), children, 2);
76+
77+ row[4] = fhints;
78+ row[5] = g_variant_new_boolean(true); // visible
79+ row[6] = g_variant_new_boolean(false); // collapsed
80+ row[7] = g_variant_new_boolean(false); // filtering
81+
82+ dee_model_append_row(model, row);
83+}
84+
85+void FiltersBindingsTest::testMultiRangeFilter()
86+{
87+ auto model = createFilterModel();
88+
89+ createMultiRangeFilter(model, "f1", "Filter1", 1);
90+ createMultiRangeFilter(model, "f2", "Filter2", 2);
91+ createMultiRangeFilter(model, "f3", "Filter3", 3);
92+
93+ // create filter out of 1st row
94+ auto iter = dee_model_get_first_iter(DEE_MODEL(model));
95+ {
96+ auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
97+ QVERIFY(core_filter != nullptr);
98+ auto bind_filter = Filter::newFromUnityFilter(core_filter);
99+ auto multi_filter = dynamic_cast<MultiRangeFilter*>(bind_filter);
100+ QVERIFY(multi_filter != nullptr);
101+ auto options = multi_filter->options();
102+ QCOMPARE(options->rowCount(), 1);
103+
104+ QVariant optvar = options->data(options->index(0));
105+ CombinedFilterOption* opt1 = optvar.value<CombinedFilterOption*>();
106+ QCOMPARE(opt1->id(), QString("opt0"));
107+
108+ delete multi_filter;
109+ }
110+
111+ // create filter out of 2nd row
112+ iter = dee_model_next(DEE_MODEL(model), iter);
113+ {
114+ auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
115+ QVERIFY(core_filter != nullptr);
116+ auto bind_filter = Filter::newFromUnityFilter(core_filter);
117+ auto multi_filter = dynamic_cast<MultiRangeFilter*>(bind_filter);
118+ QVERIFY(multi_filter != nullptr);
119+ auto options = multi_filter->options();
120+ QCOMPARE(options->rowCount(), 2);
121+
122+ QVariant optvar = options->data(options->index(0));
123+ CombinedFilterOption* opt1 = optvar.value<CombinedFilterOption*>();
124+ QCOMPARE(opt1->id(), QString("opt0-opt1"));
125+
126+ optvar = options->data(options->index(1));
127+ CombinedFilterOption* opt2 = optvar.value<CombinedFilterOption*>();
128+ QCOMPARE(opt2->id(), QString("opt1"));
129+
130+ delete multi_filter;
131+ }
132+
133+ // create filter out of 3nd row
134+ iter = dee_model_next(DEE_MODEL(model), iter);
135+ {
136+ auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
137+ QVERIFY(core_filter != nullptr);
138+ auto bind_filter = Filter::newFromUnityFilter(core_filter);
139+ auto multi_filter = dynamic_cast<MultiRangeFilter*>(bind_filter);
140+ QVERIFY(multi_filter != nullptr);
141+ auto options = multi_filter->options();
142+ QCOMPARE(options->rowCount(), 3);
143+
144+ QVariant optvar = options->data(options->index(0));
145+ CombinedFilterOption* opt0 = optvar.value<CombinedFilterOption*>();
146+ QCOMPARE(opt0->id(), QString("opt0-opt1"));
147+
148+ optvar = options->data(options->index(1));
149+ CombinedFilterOption* opt1 = optvar.value<CombinedFilterOption*>();
150+ QCOMPARE(opt1->id(), QString("opt1-opt2"));
151+
152+ optvar = options->data(options->index(2));
153+ CombinedFilterOption* opt2 = optvar.value<CombinedFilterOption*>();
154+ QCOMPARE(opt2->id(), QString("opt2"));
155+
156+ // verify combined filter options are bound to correct underlying unity options
157+ auto core_multi_filter = std::dynamic_pointer_cast<unity::dash::MultiRangeFilter>(core_filter);
158+ QCOMPARE(QString::fromStdString(core_multi_filter->options()[0]->id()), QString("opt0"));
159+ QCOMPARE(QString::fromStdString(core_multi_filter->options()[1]->id()), QString("opt1"));
160+ QCOMPARE(QString::fromStdString(core_multi_filter->options()[2]->id()), QString("opt2"));
161+
162+ QSignalSpy opt0spy(opt0, SIGNAL(activeChanged(bool)));
163+ QSignalSpy opt1spy(opt1, SIGNAL(activeChanged(bool)));
164+ QSignalSpy opt2spy(opt2, SIGNAL(activeChanged(bool)));
165+
166+ // test active property changes
167+ QCOMPARE(opt0->active(), false);
168+
169+ opt0->setActive(true); // activate 1st combined option
170+ QCOMPARE(opt0spy.count(), 1);
171+ QCOMPARE(opt1spy.count(), 0);
172+ QCOMPARE(opt2spy.count(), 0);
173+ QCOMPARE(opt0->active(), true);
174+ QCOMPARE(opt1->active(), false);
175+ QCOMPARE(core_multi_filter->options()[0]->active(), true);
176+ QCOMPARE(core_multi_filter->options()[1]->active(), true);
177+ QCOMPARE(core_multi_filter->options()[2]->active(), false);
178+
179+ opt1->setActive(true); // activate another combined option
180+ QCOMPARE(opt0spy.count(), 2);
181+ QCOMPARE(opt1spy.count(), 1);
182+ QCOMPARE(opt2spy.count(), 0);
183+ QCOMPARE(opt0->active(), false); //1st combined option gets deactivated
184+ QCOMPARE(opt1->active(), true);
185+ QCOMPARE(core_multi_filter->options()[0]->active(), false);
186+ QCOMPARE(core_multi_filter->options()[1]->active(), true); // shared option, stays active
187+ QCOMPARE(core_multi_filter->options()[2]->active(), true);
188+
189+ opt1->setActive(false); // and de-activate it
190+ QCOMPARE(opt0spy.count(), 2);
191+ QCOMPARE(opt1spy.count(), 2);
192+ QCOMPARE(opt2spy.count(), 0);
193+ QCOMPARE(opt0->active(), false);
194+ QCOMPARE(opt1->active(), false);
195+ QCOMPARE(core_multi_filter->options()[0]->active(), false);
196+ QCOMPARE(core_multi_filter->options()[1]->active(), false);
197+ QCOMPARE(core_multi_filter->options()[2]->active(), false);
198+
199+ opt2->setActive(true); // activate another combined option
200+ QCOMPARE(opt0spy.count(), 2);
201+ QCOMPARE(opt1spy.count(), 2);
202+ QCOMPARE(opt2spy.count(), 1);
203+ QCOMPARE(opt0->active(), false);
204+ QCOMPARE(opt1->active(), false);
205+ QCOMPARE(opt2->active(), true);
206+ QCOMPARE(core_multi_filter->options()[0]->active(), false);
207+ QCOMPARE(core_multi_filter->options()[1]->active(), false);
208+ QCOMPARE(core_multi_filter->options()[2]->active(), true);
209+
210+ delete multi_filter;
211+ }
212+}
213+
214+QTEST_MAIN(FiltersBindingsTest)