2
* Copyright (C) 2013 Canonical, Ltd.
5
* Pawel Stolowski <pawel.stolowski@canonical.com>
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; version 3.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program. If not, see <http://www.gnu.org/licenses/>.
20
#include "filtersbindingstest.h"
23
#include <UnityCore/Filter.h>
24
#include <UnityCore/MultiRangeFilter.h>
35
#include "multirangefilter.h"
36
#include "checkoptionfilter.h"
37
#include "radiooptionfilter.h"
38
#include "ratingsfilter.h"
39
#include "ratingfilteroption.h"
40
#include "genericoptionsmodel.h"
42
void FiltersBindingsTest::initTestCase()
46
GVariant* FiltersBindingsTest::createOptions(int numOfOptions)
48
auto vtype = g_variant_type_new("a(sssb)");
49
auto vb = g_variant_builder_new(vtype);
50
for (int i = 0; i<numOfOptions; i++) {
51
const std::string optId = "opt" + std::to_string(i);
52
const std::string optName = "Option " + std::to_string(i);
53
g_variant_builder_add(vb, "(sssb)", optId.c_str(), optName.c_str(), "", false);
55
return g_variant_builder_end(vb);
58
DeeModel* FiltersBindingsTest::createFilterModel()
60
const char* filter_schema[8] = {"s", "s", "s", "s", "a{sv}", "b", "b", "b"};
61
auto model = dee_sequence_model_new();
62
dee_model_set_schema_full (DEE_MODEL(model), filter_schema, 8);
66
void FiltersBindingsTest::createMultiRangeFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount)
68
createFilter(model, "filter-multirange", id, name, optionCount, true);
71
void FiltersBindingsTest::createRadioOptionFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount)
73
createFilter(model, "filter-radiooption", id, name, optionCount, true);
76
void FiltersBindingsTest::createCheckOptionFilter(DeeModel *model, const std::string &id, const std::string &name, int optionCount)
78
createFilter(model, "filter-checkoption", id, name, optionCount, true);
81
void FiltersBindingsTest::createRatingsFilter(DeeModel *model, const std::string &id, const std::string &name)
85
row[0] = g_variant_new_string(id.c_str());
86
row[1] = g_variant_new_string(name.c_str());
87
row[2] = g_variant_new_string(""); // icon hint
88
row[3] = g_variant_new_string("filter-ratings");
90
GVariant *children[2];
91
GVariant *key1 = g_variant_new_string("show-all-button");
92
GVariant *key2 = g_variant_new_string("rating");
93
children[0] = g_variant_new_dict_entry(key1, g_variant_new_variant(g_variant_new_boolean(true)));
94
children[1] = g_variant_new_dict_entry(key2, g_variant_new_variant(g_variant_new_double(0.0f)));
95
auto fhints = g_variant_new_array(G_VARIANT_TYPE("{sv}"), children, 2);
98
row[5] = g_variant_new_boolean(true); // visible
99
row[6] = g_variant_new_boolean(false); // collapsed
100
row[7] = g_variant_new_boolean(false); // filtering
102
dee_model_append_row(model, row);
105
void FiltersBindingsTest::createFilter(DeeModel *model, const std::string &renderer, const std::string &id, const std::string &name, int optionCount, bool showAll)
109
row[0] = g_variant_new_string(id.c_str());
110
row[1] = g_variant_new_string(name.c_str());
111
row[2] = g_variant_new_string(""); // icon hint
112
row[3] = g_variant_new_string(renderer.c_str()); // renderer
114
GVariant *children[2];
115
GVariant *key1 = g_variant_new_string("show-all-button");
116
GVariant *key2 = g_variant_new_string("options");
117
children[0] = g_variant_new_dict_entry(key1, g_variant_new_variant(g_variant_new_boolean(showAll)));
118
children[1] = g_variant_new_dict_entry(key2, g_variant_new_variant(createOptions(optionCount)));
119
auto fhints = g_variant_new_array(G_VARIANT_TYPE("{sv}"), children, 2);
122
row[5] = g_variant_new_boolean(true); // visible
123
row[6] = g_variant_new_boolean(false); // collapsed
124
row[7] = g_variant_new_boolean(false); // filtering
126
dee_model_append_row(model, row);
129
void FiltersBindingsTest::testMultiRangeFilter()
131
auto model = createFilterModel();
133
createMultiRangeFilter(model, "f1", "Filter1", 1);
134
createMultiRangeFilter(model, "f2", "Filter2", 2);
135
createMultiRangeFilter(model, "f3", "Filter3", 3);
137
// create filter out of 1st row
138
auto iter = dee_model_get_first_iter(DEE_MODEL(model));
140
auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
141
QVERIFY(core_filter != nullptr);
142
auto bind_filter = Filter::newFromUnityFilter(core_filter);
143
auto multi_filter = dynamic_cast<MultiRangeFilter*>(bind_filter);
144
QVERIFY(multi_filter != nullptr);
145
auto options = multi_filter->options();
146
QCOMPARE(options->rowCount(), 2);
148
auto idx = options->index(1);
149
QVariant id_var = options->data(idx, GenericOptionsModel::RoleId);
150
QVariant name_var = options->data(idx, GenericOptionsModel::RoleName);
151
QVariant icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
152
QVariant active_var = options->data(idx, GenericOptionsModel::RoleActive);
154
QCOMPARE(id_var.toString(), QString("opt0"));
155
QCOMPARE(name_var.toString(), QString("Option 0"));
156
QCOMPARE(icon_var.toString(), QString(""));
157
QCOMPARE(active_var.toBool(), false);
162
// create filter out of 2nd row
163
iter = dee_model_next(DEE_MODEL(model), iter);
165
auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
166
QVERIFY(core_filter != nullptr);
167
auto bind_filter = Filter::newFromUnityFilter(core_filter);
168
auto multi_filter = dynamic_cast<MultiRangeFilter*>(bind_filter);
169
QVERIFY(multi_filter != nullptr);
170
auto options = multi_filter->options();
171
QCOMPARE(options->rowCount(), 3);
173
auto idx = options->index(1);
174
QVariant id_var = options->data(idx, GenericOptionsModel::RoleId);
175
QVariant name_var = options->data(idx, GenericOptionsModel::RoleName);
176
QVariant icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
177
QVariant active_var = options->data(idx, GenericOptionsModel::RoleActive);
179
QCOMPARE(id_var.toString(), QString("opt0"));
180
QCOMPARE(name_var.toString(), QString("Option 0"));
181
QCOMPARE(icon_var.toString(), QString(""));
182
QCOMPARE(active_var.toBool(), false);
184
AbstractFilterOption* opt1 = options->getRawOption(1);
185
QCOMPARE(opt1->id(), QString("opt0"));
187
AbstractFilterOption* opt2 = options->getRawOption(2);
188
QCOMPARE(opt2->id(), QString("opt1"));
193
// create filter out of 3nd row
194
iter = dee_model_next(DEE_MODEL(model), iter);
196
auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
197
QVERIFY(core_filter != nullptr);
198
auto bind_filter = Filter::newFromUnityFilter(core_filter);
199
auto multi_filter = dynamic_cast<MultiRangeFilter*>(bind_filter);
200
QVERIFY(multi_filter != nullptr);
201
auto options = multi_filter->options();
202
QCOMPARE(options->rowCount(), 4);
204
AbstractFilterOption* showAll = options->getRawOption(0);
205
QVERIFY(showAll->id().startsWith("show_all::"));
207
AbstractFilterOption* opt0 = options->getRawOption(1);
208
QCOMPARE(opt0->id(), QString("opt0"));
210
AbstractFilterOption* opt1 = options->getRawOption(2);
211
QCOMPARE(opt1->id(), QString("opt1"));
213
AbstractFilterOption* opt2 = options->getRawOption(3);
214
QCOMPARE(opt2->id(), QString("opt2"));
216
// verify filter options are bound to correct underlying unity options
217
auto core_multi_filter = std::dynamic_pointer_cast<unity::dash::MultiRangeFilter>(core_filter);
218
QCOMPARE(QString::fromStdString(core_multi_filter->options()[0]->id()), QString("opt0"));
219
QCOMPARE(QString::fromStdString(core_multi_filter->options()[1]->id()), QString("opt1"));
220
QCOMPARE(QString::fromStdString(core_multi_filter->options()[2]->id()), QString("opt2"));
222
QSignalSpy opt0spy(opt0, SIGNAL(activeChanged(bool)));
223
QSignalSpy opt1spy(opt1, SIGNAL(activeChanged(bool)));
224
QSignalSpy opt2spy(opt2, SIGNAL(activeChanged(bool)));
226
// test active property changes
227
QCOMPARE(opt0->active(), false);
229
opt0->setActive(true); // activate 1st option
230
QCOMPARE(opt0spy.count(), 1);
231
QCOMPARE(opt1spy.count(), 0);
232
QCOMPARE(opt2spy.count(), 0);
233
QCOMPARE(opt0->active(), true);
234
QCOMPARE(opt1->active(), false);
235
QCOMPARE(opt2->active(), false);
237
opt1->setActive(true);
238
QCOMPARE(opt0spy.count(), 2);
239
QCOMPARE(opt1spy.count(), 1);
240
QCOMPARE(opt2spy.count(), 0);
241
QCOMPARE(opt0->active(), false); //1st combined option gets deactivated
242
QCOMPARE(opt1->active(), true);
243
QCOMPARE(opt2->active(), false);
245
opt1->setActive(false); // and de-activate it
246
QCOMPARE(opt0spy.count(), 2);
247
QCOMPARE(opt1spy.count(), 2);
248
QCOMPARE(opt2spy.count(), 0);
249
QCOMPARE(opt0->active(), false);
250
QCOMPARE(opt1->active(), false);
251
QCOMPARE(opt2->active(), false);
253
opt2->setActive(true); // activate another combined option
254
QCOMPARE(opt0spy.count(), 2);
255
QCOMPARE(opt1spy.count(), 2);
256
QCOMPARE(opt2spy.count(), 1);
257
QCOMPARE(opt0->active(), false);
258
QCOMPARE(opt1->active(), false);
259
QCOMPARE(opt2->active(), true);
265
void FiltersBindingsTest::testCheckOptionFilter()
267
auto model = createFilterModel();
269
createCheckOptionFilter(model, "f1", "Filter1", 3);
271
// create filter out of 1st row
272
auto iter = dee_model_get_first_iter(DEE_MODEL(model));
274
auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
275
QVERIFY(core_filter != nullptr);
276
auto bind_filter = Filter::newFromUnityFilter(core_filter);
277
auto check_filter = dynamic_cast<CheckOptionFilter*>(bind_filter);
278
QVERIFY(check_filter != nullptr);
279
auto options = check_filter->options();
280
QCOMPARE(options->rowCount(), 4);
282
QCOMPARE(check_filter->id(), QString("f1"));
283
QCOMPARE(check_filter->name(), QString("Filter1"));
284
QCOMPARE(check_filter->iconHint(), QString(""));
285
QCOMPARE(check_filter->rendererName(), QString("filter-checkoption"));
286
QCOMPARE(check_filter->visible(), true);
287
QCOMPARE(check_filter->collapsed(), false);
288
QCOMPARE(check_filter->filtering(), false);
290
auto idx = options->index(1);
291
QVariant id_var = options->data(idx, GenericOptionsModel::RoleId);
292
QVariant name_var = options->data(idx, GenericOptionsModel::RoleName);
293
QVariant icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
294
QVariant active_var = options->data(idx, GenericOptionsModel::RoleActive);
296
QCOMPARE(id_var.toString(), QString("opt0"));
297
QCOMPARE(name_var.toString(), QString("Option 0"));
298
QCOMPARE(icon_var.toString(), QString(""));
299
QCOMPARE(active_var.toBool(), false);
301
idx = options->index(2);
302
id_var = options->data(idx, GenericOptionsModel::RoleId);
303
name_var = options->data(idx, GenericOptionsModel::RoleName);
304
icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
305
active_var = options->data(idx, GenericOptionsModel::RoleActive);
307
QCOMPARE(id_var.toString(), QString("opt1"));
308
QCOMPARE(name_var.toString(), QString("Option 1"));
309
QCOMPARE(icon_var.toString(), QString(""));
310
QCOMPARE(active_var.toBool(), false);
312
AbstractFilterOption* showAll = options->getRawOption(0);
313
AbstractFilterOption* opt0 = options->getRawOption(1);
314
AbstractFilterOption* opt1 = options->getRawOption(2);
315
AbstractFilterOption* opt2 = options->getRawOption(3);
317
QSignalSpy showAllSpy(showAll, SIGNAL(activeChanged(bool)));
318
QSignalSpy opt0spy(opt0, SIGNAL(activeChanged(bool)));
319
QSignalSpy opt1spy(opt1, SIGNAL(activeChanged(bool)));
320
QSignalSpy opt2spy(opt2, SIGNAL(activeChanged(bool)));
321
QSignalSpy dataChangedSpy(options, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
323
// test active property changes
324
QCOMPARE(showAll->active(), false);
325
QCOMPARE(opt0->active(), false);
326
QCOMPARE(opt1->active(), false);
327
QCOMPARE(opt2->active(), false);
329
opt0->setActive(true);
330
QCOMPARE(showAllSpy.count(), 0);
331
QCOMPARE(opt0spy.count(), 1);
332
QCOMPARE(opt1spy.count(), 0);
333
QCOMPARE(opt2spy.count(), 0);
334
QCOMPARE(showAll->active(), false);
335
QCOMPARE(opt0->active(), true);
336
QCOMPARE(opt1->active(), false);
337
QCOMPARE(opt2->active(), false);
339
opt1->setActive(true);
340
QCOMPARE(showAllSpy.count(), 0);
341
QCOMPARE(opt0spy.count(), 2);
342
QCOMPARE(opt1spy.count(), 1);
343
QCOMPARE(opt2spy.count(), 0);
344
QCOMPARE(showAll->active(), false);
345
QCOMPARE(opt0->active(), false);
346
QCOMPARE(opt1->active(), true);
347
QCOMPARE(opt2->active(), false);
349
QCOMPARE(dataChangedSpy.count(), 3);
351
showAll->setActive(true);
352
QCOMPARE(showAllSpy.count(), 1);
353
QCOMPARE(opt0spy.count(), 2);
354
QCOMPARE(opt1spy.count(), 2);
355
QCOMPARE(opt2spy.count(), 0);
356
QCOMPARE(showAll->active(), true);
357
QCOMPARE(opt0->active(), false);
358
QCOMPARE(opt1->active(), false);
359
QCOMPARE(opt2->active(), false);
365
void FiltersBindingsTest::testRadioOptionFilter()
367
auto model = createFilterModel();
369
createRadioOptionFilter(model, "f1", "Filter1", 3);
371
// create filter out of 1st row
372
auto iter = dee_model_get_first_iter(DEE_MODEL(model));
374
auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
375
QVERIFY(core_filter != nullptr);
376
auto bind_filter = Filter::newFromUnityFilter(core_filter);
377
auto radio_filter = dynamic_cast<RadioOptionFilter*>(bind_filter);
378
QVERIFY(radio_filter != nullptr);
379
auto options = radio_filter->options();
380
QCOMPARE(options->rowCount(), 4);
382
auto idx = options->index(0);
383
QVariant id_var = options->data(idx, GenericOptionsModel::RoleId);
384
QVariant name_var = options->data(idx, GenericOptionsModel::RoleName);
385
QVariant icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
386
QVariant active_var = options->data(idx, GenericOptionsModel::RoleActive);
388
QVERIFY(id_var.toString().startsWith("show_all::"));
389
QVERIFY(name_var.toString().size() > 0);
390
QCOMPARE(icon_var.toString(), QString(""));
391
QCOMPARE(active_var.toBool(), false);
393
idx = options->index(1);
394
id_var = options->data(idx, GenericOptionsModel::RoleId);
395
name_var = options->data(idx, GenericOptionsModel::RoleName);
396
icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
397
active_var = options->data(idx, GenericOptionsModel::RoleActive);
399
QCOMPARE(id_var.toString(), QString("opt0"));
400
QCOMPARE(name_var.toString(), QString("Option 0"));
401
QCOMPARE(icon_var.toString(), QString(""));
402
QCOMPARE(active_var.toBool(), false);
404
idx = options->index(2);
405
id_var = options->data(idx, GenericOptionsModel::RoleId);
406
name_var = options->data(idx, GenericOptionsModel::RoleName);
407
icon_var = options->data(idx, GenericOptionsModel::RoleIconHint);
408
active_var = options->data(idx, GenericOptionsModel::RoleActive);
410
QCOMPARE(id_var.toString(), QString("opt1"));
411
QCOMPARE(name_var.toString(), QString("Option 1"));
412
QCOMPARE(icon_var.toString(), QString(""));
413
QCOMPARE(active_var.toBool(), false);
415
AbstractFilterOption* opt0 = options->getRawOption(1);
416
AbstractFilterOption* opt1 = options->getRawOption(2);
417
AbstractFilterOption* opt2 = options->getRawOption(3);
419
QSignalSpy opt0spy(opt0, SIGNAL(activeChanged(bool)));
420
QSignalSpy opt1spy(opt1, SIGNAL(activeChanged(bool)));
421
QSignalSpy opt2spy(opt2, SIGNAL(activeChanged(bool)));
422
QSignalSpy dataChangedSpy(options, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
424
// test active property changes
425
QCOMPARE(opt0->active(), false);
426
QCOMPARE(opt1->active(), false);
427
QCOMPARE(opt2->active(), false);
429
opt0->setActive(true);
430
QCOMPARE(opt0spy.count(), 1);
431
QCOMPARE(opt1spy.count(), 0);
432
QCOMPARE(opt2spy.count(), 0);
433
QCOMPARE(opt0->active(), true);
434
QCOMPARE(opt1->active(), false);
435
QCOMPARE(opt2->active(), false);
437
opt1->setActive(true);
438
QCOMPARE(opt0spy.count(), 2);
439
QCOMPARE(opt1spy.count(), 1);
440
QCOMPARE(opt2spy.count(), 0);
441
QCOMPARE(opt0->active(), false);
442
QCOMPARE(opt1->active(), true);
443
QCOMPARE(opt2->active(), false);
445
QCOMPARE(dataChangedSpy.count(), 3);
451
void FiltersBindingsTest::testRatingsFilter()
453
auto model = createFilterModel();
455
createRatingsFilter(model, "f1", "Filter1");
457
// create filter out of 1st row
458
auto iter = dee_model_get_first_iter(DEE_MODEL(model));
460
auto core_filter = unity::dash::Filter::FilterFromIter(model, iter);
461
QVERIFY(core_filter != nullptr);
462
auto bind_filter = Filter::newFromUnityFilter(core_filter);
463
auto rating_filter = dynamic_cast<RatingsFilter*>(bind_filter);
464
QVERIFY(rating_filter != nullptr);
465
auto options = rating_filter->options();
466
QCOMPARE(options->rowCount(), 6);
468
RatingFilterOption* opt[5];
469
for (int i = 0; i<5; i++) {
470
opt[i] = dynamic_cast<RatingFilterOption *>(options->getRawOption(i+1));
473
QSignalSpy opt0spy(opt[0], SIGNAL(activeChanged(bool)));
474
QSignalSpy opt4spy(opt[4], SIGNAL(activeChanged(bool)));
475
QSignalSpy dataChangedSpy(options, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
477
QVERIFY(qAbs(opt[0]->value() - 0.2f) <= 0.0001f);
478
QVERIFY(qAbs(opt[1]->value() - 0.4f) <= 0.0001f);
479
QVERIFY(qAbs(opt[2]->value() - 0.6f) <= 0.0001f);
480
QVERIFY(qAbs(opt[3]->value() - 0.8f) <= 0.0001f);
481
QVERIFY(qAbs(opt[4]->value() - 1.0f) <= 0.0001f);
483
QVERIFY(rating_filter->rating() <= 0.0001f); // rating equals zero
485
// all options initially inactive
486
for (int i=0; i<5; i++) {
487
QCOMPARE(opt[i]->active(), false);
490
// verify activation for all options
491
for (int i=0; i<5; i++) {
492
opt[i]->setActive(true);
493
QCOMPARE(opt[i]->active(), true);
494
QVERIFY(rating_filter->rating() - ((i+1)*0.2f) <= 0.0001f);
496
// verify that all other options are inactive
497
for (int j=0; j<5; j++) {
499
QCOMPARE(opt[j]->active(), false);
504
QCOMPARE(opt0spy.count(), 2);
505
QCOMPARE(opt4spy.count(), 1);
507
opt[4]->setActive(false);
508
QVERIFY(rating_filter->rating() <= 0.0001f); // rating equals zero
509
QCOMPARE(opt4spy.count(), 2);
511
QCOMPARE(dataChangedSpy.count(), 10);
515
QTEST_MAIN(FiltersBindingsTest)