Merge lp:~3v1n0/unity/keep-priority-launcher-model into lp:unity

Proposed by Marco Trevisan (Treviño)
Status: Merged
Approved by: Timo Jyrinki
Approved revision: no longer in the source branch.
Merged at revision: 2660
Proposed branch: lp:~3v1n0/unity/keep-priority-launcher-model
Merge into: lp:unity
Diff against target: 1314 lines (+513/-454)
7 files modified
launcher/Launcher.cpp (+2/-1)
launcher/LauncherController.cpp (+1/-6)
launcher/LauncherModel.cpp (+191/-202)
launcher/LauncherModel.h (+19/-20)
launcher/MockLauncherIcon.h (+9/-9)
tests/test_launcher.cpp (+0/-4)
tests/test_launcher_model.cpp (+291/-212)
To merge this branch: bzr merge lp:~3v1n0/unity/keep-priority-launcher-model
Reviewer Review Type Date Requested Status
Andrea Azzarone (community) Approve
jenkins continuous-integration Pending
Review via email: mp+122699@code.launchpad.net

Commit message

LauncherModel: rewrite the Reordering functions to keep the icon priority deltas

The priority of the icons added to the model was reset every time the model
was reordered; we should otherwise keep the priority deltas between icons
so that we can safely set them without be worried that a reorder would completely
reset them.
Also add IconIndex method to get the positio of a given icon.

Description of the change

The unity LauncherModel used the IconPriority value to sort icons, however it was resetting this value every time the model was reordered, and was not possible to keep the priority deltas between the icons.
I've rewritten the model functions to make them change the priority to a relative value, instead of absolute ones.

This work is preliminary to the work needed for bug #761155

Unit tests added and updated.

To post a comment you must log in.
Revision history for this message
Andrea Azzarone (azzar1) wrote :

LGTM... Discussed and reviewed on IRC.

review: Approve
Revision history for this message
Unity Merger (unity-merger) wrote :

The Jenkins job https://jenkins.qa.ubuntu.com/job/automerge-unity/1181/console reported an error when processing this lp:~3v1n0/unity/keep-priority-launcher-model branch.
Not merging it.

Revision history for this message
Unity Merger (unity-merger) wrote :

The Jenkins job https://jenkins.qa.ubuntu.com/job/automerge-unity/1203/console reported an error when processing this lp:~3v1n0/unity/keep-priority-launcher-model branch.
Not merging it.

Revision history for this message
Unity Merger (unity-merger) wrote :

The Jenkins job https://jenkins.qa.ubuntu.com/job/automerge-unity/1209/console reported an error when processing this lp:~3v1n0/unity/keep-priority-launcher-model branch.
Not merging it.

Revision history for this message
Unity Merger (unity-merger) wrote :

The Jenkins job https://jenkins.qa.ubuntu.com/job/automerge-unity/1212/console reported an error when processing this lp:~3v1n0/unity/keep-priority-launcher-model branch.
Not merging it.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'launcher/Launcher.cpp'
2--- launcher/Launcher.cpp 2012-09-03 08:47:49 +0000
3+++ launcher/Launcher.cpp 2012-09-04 16:43:33 +0000
4@@ -1981,7 +1981,8 @@
5
6 // FIXME: nux doesn't give nux::GetEventButton (button_flags) there, relying
7 // on an internal Launcher property then
8- if (drag_icon && _last_button_press == 1 && _model->IconHasSister(drag_icon))
9+ bool can_drag = (_model->IconHasSister(drag_icon) || drag_icon->GetIconType() == AbstractLauncherIcon::IconType::DEVICE);
10+ if (drag_icon && _last_button_press == 1 && can_drag)
11 {
12 SetActionState(ACTION_DRAG_ICON);
13 StartIconDrag(drag_icon);
14
15=== modified file 'launcher/LauncherController.cpp'
16--- launcher/LauncherController.cpp 2012-08-30 21:09:02 +0000
17+++ launcher/LauncherController.cpp 2012-09-04 16:43:33 +0000
18@@ -688,10 +688,6 @@
19 GList* apps, *l;
20 BamfApplication* app;
21
22- // Sufficiently large number such that we ensure proper sorting
23- // (avoids case where first item gets tacked onto end rather than start)
24- int priority = 100;
25-
26 FavoriteList const& favs = FavoriteStore::Instance().GetFavorites();
27
28 for (FavoriteList::const_iterator i = favs.begin(), end = favs.end();
29@@ -701,9 +697,8 @@
30
31 if (fav)
32 {
33- fav->SetSortPriority(priority);
34+ fav->SetSortPriority(sort_priority_++);
35 RegisterIcon(fav);
36- priority++;
37 }
38 }
39
40
41=== modified file 'launcher/LauncherModel.cpp'
42--- launcher/LauncherModel.cpp 2012-08-31 19:35:46 +0000
43+++ launcher/LauncherModel.cpp 2012-09-04 16:43:33 +0000
44@@ -1,6 +1,6 @@
45 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
46 /*
47- * Copyright (C) 2010 Canonical Ltd
48+ * Copyright (C) 2010-2012 Canonical Ltd
49 *
50 * This program is free software: you can redistribute it and/or modify
51 * it under the terms of the GNU General Public License version 3 as
52@@ -15,6 +15,7 @@
53 * along with this program. If not, see <http://www.gnu.org/licenses/>.
54 *
55 * Authored by: Jason Smith <jason.smith@canonical.com>
56+ * Marco Trevisan <marco.trevisan@canonical.com>
57 */
58
59 #include "LauncherModel.h"
60@@ -30,8 +31,7 @@
61
62 LauncherModel::LauncherModel()
63 : selection_(0)
64-{
65-}
66+{}
67
68 std::string LauncherModel::GetName() const
69 {
70@@ -54,12 +54,12 @@
71 return introspection_results_;
72 }
73
74-bool LauncherModel::IconShouldShelf(AbstractLauncherIcon::Ptr icon) const
75+bool LauncherModel::IconShouldShelf(AbstractLauncherIcon::Ptr const& icon) const
76 {
77 return icon->GetIconType() == AbstractLauncherIcon::IconType::TRASH;
78 }
79
80-bool LauncherModel::CompareIcons(AbstractLauncherIcon::Ptr first, AbstractLauncherIcon::Ptr second)
81+bool LauncherModel::CompareIcons(AbstractLauncherIcon::Ptr const& first, AbstractLauncherIcon::Ptr const& second)
82 {
83 if (first->GetIconType() < second->GetIconType())
84 return true;
85@@ -69,36 +69,43 @@
86 return first->SortPriority() < second->SortPriority();
87 }
88
89-bool
90-LauncherModel::Populate()
91+void LauncherModel::PopulatePart(iterator begin, iterator end)
92+{
93+ AbstractLauncherIcon::Ptr prev_icon;
94+ for (auto it = begin; it != end; ++it)
95+ {
96+ auto const& icon = *it;
97+ _inner.push_back(icon);
98+
99+ if (prev_icon)
100+ {
101+ // Ensuring that the current icon has higher priority than previous one
102+ if (icon->SortPriority() < prev_icon->SortPriority())
103+ {
104+ int new_priority = prev_icon->SortPriority() + 1;
105+ icon->SetSortPriority(new_priority);
106+ }
107+ }
108+
109+ prev_icon = icon;
110+ }
111+}
112+
113+bool LauncherModel::Populate()
114 {
115 Base copy = _inner;
116-
117 _inner.clear();
118-
119- iterator it, it2;
120-
121- int i = 0;
122- for (it = main_begin(); it != main_end(); ++it)
123- {
124- _inner.push_back(*it);
125- (*it)->SetSortPriority(i);
126- ++i;
127- }
128-
129- for (it = shelf_begin(); it != shelf_end(); ++it)
130- {
131- _inner.push_back(*it);
132- (*it)->SetSortPriority(i);
133- ++i;
134- }
135+ PopulatePart(main_begin(), main_end());
136+ PopulatePart(shelf_begin(), shelf_end());
137
138 return copy.size() == _inner.size() && !std::equal(begin(), end(), copy.begin());
139 }
140
141-void
142-LauncherModel::AddIcon(AbstractLauncherIcon::Ptr icon)
143+void LauncherModel::AddIcon(AbstractLauncherIcon::Ptr const& icon)
144 {
145+ if (!icon || std::find(begin(), end(), icon) != end())
146+ return;
147+
148 if (IconShouldShelf(icon))
149 _inner_shelf.push_back(icon);
150 else
151@@ -113,8 +120,7 @@
152 icon->on_icon_removed_connection = icon->remove.connect(sigc::mem_fun(this, &LauncherModel::OnIconRemove));
153 }
154
155-void
156-LauncherModel::RemoveIcon(AbstractLauncherIcon::Ptr icon)
157+void LauncherModel::RemoveIcon(AbstractLauncherIcon::Ptr const& icon)
158 {
159 size_t size;
160
161@@ -130,23 +136,20 @@
162 }
163 }
164
165-void
166-LauncherModel::OnIconRemove(AbstractLauncherIcon::Ptr icon)
167+void LauncherModel::OnIconRemove(AbstractLauncherIcon::Ptr const& icon)
168 {
169- timeouts_.AddTimeout(1000, [&, icon] {
170+ timeouts_.AddTimeout(1000, [this, icon] {
171 RemoveIcon(icon);
172 return false;
173 });
174 }
175
176-void
177-LauncherModel::Save()
178+void LauncherModel::Save()
179 {
180 saved.emit();
181 }
182
183-void
184-LauncherModel::Sort()
185+void LauncherModel::Sort()
186 {
187 std::stable_sort(_inner_shelf.begin(), _inner_shelf.end(), &LauncherModel::CompareIcons);
188 std::stable_sort(_inner_main.begin(), _inner_main.end(), &LauncherModel::CompareIcons);
189@@ -155,15 +158,14 @@
190 order_changed.emit();
191 }
192
193-bool
194-LauncherModel::IconHasSister(AbstractLauncherIcon::Ptr icon) const
195+bool LauncherModel::IconHasSister(AbstractLauncherIcon::Ptr const& icon) const
196 {
197+ if (!icon)
198+ return false;
199+
200 const_iterator it;
201 const_iterator end;
202
203- if (icon && icon->GetIconType() == AbstractLauncherIcon::IconType::DEVICE)
204- return true;
205-
206 if (IconShouldShelf(icon))
207 {
208 it = _inner_shelf.begin();
209@@ -177,144 +179,125 @@
210
211 for (; it != end; ++it)
212 {
213- AbstractLauncherIcon::Ptr iter_icon = *it;
214- if ((iter_icon != icon)
215- && iter_icon->GetIconType() == icon->GetIconType())
216+ AbstractLauncherIcon::Ptr const& iter_icon = *it;
217+
218+ if (iter_icon != icon && iter_icon->GetIconType() == icon->GetIconType())
219 return true;
220 }
221
222 return false;
223 }
224
225-void
226-LauncherModel::ReorderAfter(AbstractLauncherIcon::Ptr icon, AbstractLauncherIcon::Ptr other)
227-{
228- if (icon == other || icon.IsNull() || other.IsNull())
229- return;
230-
231- if (icon->GetIconType() != other->GetIconType())
232- return;
233-
234- int i = 0;
235- for (LauncherModel::iterator it = begin(); it != end(); ++it)
236- {
237- if ((*it) == icon)
238- continue;
239-
240- if ((*it) == other)
241- {
242- (*it)->SetSortPriority(i);
243- ++i;
244-
245- icon->SetSortPriority(i);
246- ++i;
247- }
248- else
249- {
250- (*it)->SetSortPriority(i);
251- ++i;
252- }
253- }
254-
255- Sort();
256-}
257-
258-void
259-LauncherModel::ReorderBefore(AbstractLauncherIcon::Ptr icon, AbstractLauncherIcon::Ptr other, bool save)
260-{
261- if (icon == other || icon.IsNull() || other.IsNull())
262- return;
263-
264- if (icon->GetIconType() != other->GetIconType())
265- return;
266-
267- int i = 0;
268- int j = 0;
269- for (auto icon_it : _inner)
270- {
271- if (icon_it == icon)
272- {
273- j++;
274- continue;
275- }
276-
277- if (icon_it == other)
278- {
279- icon->SetSortPriority(i);
280- if (i != j && save)
281- icon_it->SaveCenter();
282- i++;
283-
284- icon_it->SetSortPriority(i);
285- if (i != j && save)
286- icon_it->SaveCenter();
287- i++;
288- }
289- else
290- {
291- icon_it->SetSortPriority(i);
292- if (i != j && save)
293- icon_it->SaveCenter();
294- i++;
295- }
296- j++;
297- }
298-
299- Sort();
300-}
301-
302-void
303-LauncherModel::ReorderSmart(AbstractLauncherIcon::Ptr icon, AbstractLauncherIcon::Ptr other, bool save)
304-{
305- if (icon == other || icon.IsNull() || other.IsNull())
306- return;
307-
308- if (icon->GetIconType() != other->GetIconType())
309- return;
310-
311- int i = 0;
312- int j = 0;
313- bool skipped = false;
314- for (auto icon_it : _inner)
315- {
316- if (icon_it == icon)
317- {
318- skipped = true;
319- j++;
320- continue;
321- }
322-
323- if (icon_it == other)
324- {
325- if (!skipped)
326- {
327- icon->SetSortPriority(i);
328- if (i != j && save)
329- icon_it->SaveCenter();
330- i++;
331- }
332-
333- icon_it->SetSortPriority(i);
334- if (i != j && save)
335- icon_it->SaveCenter();
336- i++;
337-
338- if (skipped)
339- {
340- icon->SetSortPriority(i);
341- if (i != j && save)
342- icon_it->SaveCenter();
343- i++;
344- }
345- }
346- else
347- {
348- icon_it->SetSortPriority(i);
349- if (i != j && save)
350- icon_it->SaveCenter();
351- i++;
352- }
353- j++;
354+void LauncherModel::ReorderAfter(AbstractLauncherIcon::Ptr const& icon, AbstractLauncherIcon::Ptr const& other)
355+{
356+ if (icon == other || icon.IsNull() || other.IsNull())
357+ return;
358+
359+ if (icon->GetIconType() != other->GetIconType())
360+ return;
361+
362+ icon->SetSortPriority(other->SortPriority() + 1);
363+
364+ for (auto it = std::next(std::find(begin(), end(), other)); it != end(); ++it)
365+ {
366+ // Increasing the priority of the icons next to the other one
367+ auto const& icon_it = *it;
368+ int new_priority = icon_it->SortPriority() + 1;
369+ icon_it->SetSortPriority(new_priority);
370+ }
371+
372+ Sort();
373+}
374+
375+void LauncherModel::ReorderBefore(AbstractLauncherIcon::Ptr const& icon, AbstractLauncherIcon::Ptr const& other, bool animate)
376+{
377+ if (icon == other || icon.IsNull() || other.IsNull())
378+ return;
379+
380+ if (icon->GetIconType() != other->GetIconType())
381+ return;
382+
383+ bool found_target = false;
384+ bool center = false;
385+
386+ for (auto const& icon_it : _inner)
387+ {
388+ if (icon_it == icon)
389+ {
390+ center = !center;
391+ continue;
392+ }
393+
394+ int new_priority = icon_it->SortPriority() + (found_target ? 1 : -1);
395+ icon_it->SetSortPriority(new_priority);
396+
397+ if (icon_it == other)
398+ {
399+ if (animate && center)
400+ icon_it->SaveCenter();
401+
402+ center = !center;
403+ new_priority = new_priority - 1;
404+ icon->SetSortPriority(new_priority);
405+
406+ if (animate && center)
407+ icon_it->SaveCenter();
408+
409+ found_target = true;
410+ }
411+ else
412+ {
413+ if (animate && center)
414+ icon_it->SaveCenter();
415+ }
416+ }
417+
418+ Sort();
419+}
420+
421+void LauncherModel::ReorderSmart(AbstractLauncherIcon::Ptr const& icon, AbstractLauncherIcon::Ptr const& other, bool animate)
422+{
423+ if (icon == other || icon.IsNull() || other.IsNull())
424+ return;
425+
426+ if (icon->GetIconType() != other->GetIconType())
427+ return;
428+
429+ bool found_icon = false;
430+ bool found_target = false;
431+ bool center = false;
432+
433+ for (auto const& icon_it : _inner)
434+ {
435+ if (icon_it == icon)
436+ {
437+ found_icon = true;
438+ center = !center;
439+ continue;
440+ }
441+
442+ int new_priority = icon_it->SortPriority() + (found_target ? 1 : -1);
443+ icon_it->SetSortPriority(new_priority);
444+
445+ if (icon_it == other)
446+ {
447+ if (animate && center)
448+ icon_it->SaveCenter();
449+
450+ center = !center;
451+ new_priority = new_priority + (found_icon ? 1 : -1);
452+ icon->SetSortPriority(new_priority);
453+
454+ if (animate && center)
455+ icon_it->SaveCenter();
456+
457+ found_target = true;
458+ }
459+ else
460+ {
461+ if (animate && center)
462+ icon_it->SaveCenter();
463+ }
464 }
465
466 Sort();
467@@ -357,7 +340,7 @@
468 if (temp >= Size())
469 temp = 0;
470
471- if (_inner[temp]->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE))
472+ if (_inner[temp]->IsVisible())
473 {
474 selection_ = temp;
475 selection_changed.emit(Selection());
476@@ -377,7 +360,7 @@
477 if (temp < 0)
478 temp = Size() - 1;
479
480- if (_inner[temp]->GetQuirk(AbstractLauncherIcon::Quirk::VISIBLE))
481+ if (_inner[temp]->IsVisible())
482 {
483 selection_ = temp;
484 selection_changed.emit(Selection());
485@@ -387,7 +370,7 @@
486 }
487 }
488
489-AbstractLauncherIcon::Ptr LauncherModel::GetClosestIcon(AbstractLauncherIcon::Ptr icon, bool& is_before) const
490+AbstractLauncherIcon::Ptr LauncherModel::GetClosestIcon(AbstractLauncherIcon::Ptr const& icon, bool& is_before) const
491 {
492 AbstractLauncherIcon::Ptr prev, next;
493 bool found_target = false;
494@@ -423,22 +406,38 @@
495 return is_before ? prev : next;
496 }
497
498+int LauncherModel::IconIndex(AbstractLauncherIcon::Ptr const& target) const
499+{
500+ int pos = 0;
501+ bool found = false;
502+
503+ for (auto const& icon : _inner)
504+ {
505+ if (icon == target)
506+ {
507+ found = true;
508+ break;
509+ }
510+
511+ ++pos;
512+ }
513+
514+ return found ? pos : -1;
515+}
516+
517 /* iterators */
518
519-LauncherModel::iterator
520-LauncherModel::begin()
521+LauncherModel::iterator LauncherModel::begin()
522 {
523 return _inner.begin();
524 }
525
526-LauncherModel::iterator
527-LauncherModel::end()
528+LauncherModel::iterator LauncherModel::end()
529 {
530 return _inner.end();
531 }
532
533-LauncherModel::iterator
534-LauncherModel::at(int index)
535+LauncherModel::iterator LauncherModel::at(int index)
536 {
537 LauncherModel::iterator it;
538 int i;
539@@ -453,62 +452,52 @@
540 return (LauncherModel::iterator)NULL;
541 }
542
543-LauncherModel::reverse_iterator
544-LauncherModel::rbegin()
545+LauncherModel::reverse_iterator LauncherModel::rbegin()
546 {
547 return _inner.rbegin();
548 }
549
550-LauncherModel::reverse_iterator
551-LauncherModel::rend()
552+LauncherModel::reverse_iterator LauncherModel::rend()
553 {
554 return _inner.rend();
555 }
556
557-LauncherModel::iterator
558-LauncherModel::main_begin()
559+LauncherModel::iterator LauncherModel::main_begin()
560 {
561 return _inner_main.begin();
562 }
563
564-LauncherModel::iterator
565-LauncherModel::main_end()
566+LauncherModel::iterator LauncherModel::main_end()
567 {
568 return _inner_main.end();
569 }
570
571-LauncherModel::reverse_iterator
572-LauncherModel::main_rbegin()
573+LauncherModel::reverse_iterator LauncherModel::main_rbegin()
574 {
575 return _inner_main.rbegin();
576 }
577
578-LauncherModel::reverse_iterator
579-LauncherModel::main_rend()
580+LauncherModel::reverse_iterator LauncherModel::main_rend()
581 {
582 return _inner_main.rend();
583 }
584
585-LauncherModel::iterator
586-LauncherModel::shelf_begin()
587+LauncherModel::iterator LauncherModel::shelf_begin()
588 {
589 return _inner_shelf.begin();
590 }
591
592-LauncherModel::iterator
593-LauncherModel::shelf_end()
594+LauncherModel::iterator LauncherModel::shelf_end()
595 {
596 return _inner_shelf.end();
597 }
598
599-LauncherModel::reverse_iterator
600-LauncherModel::shelf_rbegin()
601+LauncherModel::reverse_iterator LauncherModel::shelf_rbegin()
602 {
603 return _inner_shelf.rbegin();
604 }
605
606-LauncherModel::reverse_iterator
607-LauncherModel::shelf_rend()
608+LauncherModel::reverse_iterator LauncherModel::shelf_rend()
609 {
610 return _inner_shelf.rend();
611 }
612
613=== modified file 'launcher/LauncherModel.h'
614--- launcher/LauncherModel.h 2012-08-31 19:35:46 +0000
615+++ launcher/LauncherModel.h 2012-09-04 16:43:33 +0000
616@@ -1,6 +1,6 @@
617 // -*- Mode: C++; indent-tabs-mode: nil; tab-width: 2 -*-
618 /*
619- * Copyright (C) 2010 Canonical Ltd
620+ * Copyright (C) 2010-2012 Canonical Ltd
621 *
622 * This program is free software: you can redistribute it and/or modify
623 * it under the terms of the GNU General Public License version 3 as
624@@ -15,6 +15,7 @@
625 * along with this program. If not, see <http://www.gnu.org/licenses/>.
626 *
627 * Authored by: Jason Smith <jason.smith@canonical.com>
628+ * Marco Trevisan <marco.trevisan@canonical.com>
629 */
630
631 #ifndef LAUNCHERMODEL_H
632@@ -41,20 +42,18 @@
633
634 LauncherModel();
635
636- void AddIcon(AbstractLauncherIcon::Ptr icon);
637- void RemoveIcon(AbstractLauncherIcon::Ptr icon);
638+ void AddIcon(AbstractLauncherIcon::Ptr const& icon);
639+ void RemoveIcon(AbstractLauncherIcon::Ptr const& icon);
640 void Save();
641 void Sort();
642 int Size() const;
643
644- void OnIconRemove(AbstractLauncherIcon::Ptr icon);
645-
646- bool IconHasSister(AbstractLauncherIcon::Ptr icon) const;
647-
648- void ReorderAfter(AbstractLauncherIcon::Ptr icon, AbstractLauncherIcon::Ptr other);
649- void ReorderBefore(AbstractLauncherIcon::Ptr icon, AbstractLauncherIcon::Ptr other, bool save);
650-
651- void ReorderSmart(AbstractLauncherIcon::Ptr icon, AbstractLauncherIcon::Ptr other, bool save);
652+ bool IconHasSister(AbstractLauncherIcon::Ptr const& icon) const;
653+ int IconIndex(AbstractLauncherIcon::Ptr const& icon) const;
654+
655+ void ReorderAfter(AbstractLauncherIcon::Ptr const& icon, AbstractLauncherIcon::Ptr const& other);
656+ void ReorderBefore(AbstractLauncherIcon::Ptr const& icon, AbstractLauncherIcon::Ptr const& other, bool animate);
657+ void ReorderSmart(AbstractLauncherIcon::Ptr const& icon, AbstractLauncherIcon::Ptr const& other, bool animate);
658
659 AbstractLauncherIcon::Ptr Selection() const;
660 int SelectionIndex() const;
661@@ -62,7 +61,7 @@
662 void SelectNext();
663 void SelectPrevious();
664
665- AbstractLauncherIcon::Ptr GetClosestIcon(AbstractLauncherIcon::Ptr icon, bool& is_before) const;
666+ AbstractLauncherIcon::Ptr GetClosestIcon(AbstractLauncherIcon::Ptr const& icon, bool& is_before) const;
667
668 iterator begin();
669 iterator end();
670@@ -80,17 +79,17 @@
671 reverse_iterator shelf_rbegin();
672 reverse_iterator shelf_rend();
673
674- sigc::signal<void, AbstractLauncherIcon::Ptr> icon_added;
675- sigc::signal<void, AbstractLauncherIcon::Ptr> icon_removed;
676+ sigc::signal<void, AbstractLauncherIcon::Ptr const&> icon_added;
677+ sigc::signal<void, AbstractLauncherIcon::Ptr const&> icon_removed;
678+ sigc::signal<void, AbstractLauncherIcon::Ptr const&> selection_changed;
679 sigc::signal<void> order_changed;
680 sigc::signal<void> saved;
681- sigc::signal<void, AbstractLauncherIcon::Ptr> selection_changed;
682
683- IntrospectableList GetIntrospectableChildren();
684 protected:
685 // Introspectable methods
686 std::string GetName() const;
687 void AddProperties(GVariantBuilder* builder);
688+ IntrospectableList GetIntrospectableChildren();
689
690 private:
691 Base _inner;
692@@ -101,10 +100,10 @@
693 glib::SourceManager timeouts_;
694
695 bool Populate();
696-
697- bool IconShouldShelf(AbstractLauncherIcon::Ptr icon) const;
698-
699- static bool CompareIcons(AbstractLauncherIcon::Ptr first, AbstractLauncherIcon::Ptr second);
700+ void PopulatePart(iterator begin, iterator end);
701+ void OnIconRemove(AbstractLauncherIcon::Ptr const& icon);
702+ bool IconShouldShelf(AbstractLauncherIcon::Ptr const& icon) const;
703+ static bool CompareIcons(AbstractLauncherIcon::Ptr const& first, AbstractLauncherIcon::Ptr const& second);
704
705 /* Template Methods */
706 public:
707
708=== modified file 'launcher/MockLauncherIcon.h'
709--- launcher/MockLauncherIcon.h 2012-08-31 18:00:29 +0000
710+++ launcher/MockLauncherIcon.h 2012-09-04 16:43:33 +0000
711@@ -44,12 +44,12 @@
712 {
713 NUX_DECLARE_OBJECT_TYPE(MockLauncherIcon, AbstractLauncherIcon);
714 public:
715- MockLauncherIcon()
716- : icon_(0)
717+ MockLauncherIcon(IconType type = IconType::APPLICATION)
718+ : type_(type)
719+ , sort_priority_(0)
720+ , icon_(0)
721 {
722 tooltip_text = "Mock Icon";
723- sort_priority_ = 0;
724- type_ = IconType::APPLICATION;
725
726 for (unsigned i = 0; i < unsigned(Quirk::LAST); ++i)
727 {
728@@ -58,7 +58,7 @@
729 }
730
731 std::string GetName() const { return "MockLauncherIcon"; }
732-
733+
734 void AddProperties(GVariantBuilder* builder) {}
735
736 void HideTooltip() {}
737@@ -293,9 +293,9 @@
738 bool IsVisible() const { return false; }
739
740 void AboutToRemove() {}
741-
742+
743 void Stick(bool save = true) {}
744-
745+
746 void UnStick() {}
747
748 private:
749@@ -346,9 +346,9 @@
750 return result;
751 }
752
753+ IconType type_;
754+ int sort_priority_;
755 nux::BaseTexture* icon_;
756- int sort_priority_;
757- IconType type_;
758 bool quirks_[unsigned(Quirk::LAST)];
759 timespec quirk_times_[unsigned(Quirk::LAST)];
760 std::map<int, nux::Point3> center_;
761
762=== modified file 'tests/test_launcher.cpp'
763--- tests/test_launcher.cpp 2012-09-01 14:09:20 +0000
764+++ tests/test_launcher.cpp 2012-09-04 16:43:33 +0000
765@@ -210,10 +210,6 @@
766 MockMockLauncherIcon::Ptr icon2(new MockMockLauncherIcon);
767 MockMockLauncherIcon::Ptr icon3(new MockMockLauncherIcon);
768
769- icon1->SetSortPriority(0);
770- icon2->SetSortPriority(1);
771- icon3->SetSortPriority(2);
772-
773 model_->AddIcon(icon1);
774 model_->AddIcon(icon2);
775 model_->AddIcon(icon3);
776
777=== modified file 'tests/test_launcher_model.cpp'
778--- tests/test_launcher_model.cpp 2012-08-31 19:35:46 +0000
779+++ tests/test_launcher_model.cpp 2012-09-04 16:43:33 +0000
780@@ -1,5 +1,5 @@
781 /*
782- * Copyright 2011 Canonical Ltd.
783+ * Copyright 2011-2012 Canonical Ltd.
784 *
785 * This program is free software: you can redistribute it and/or modify it
786 * under the terms of the GNU General Public License version 3, as published
787@@ -15,7 +15,7 @@
788 * <http://www.gnu.org/licenses/>
789 *
790 * Authored by: Jason Smith <jason.smith@canonical.com>
791- *
792+ * Marco Trevisan <marco.trevisan@canonical.com>
793 */
794
795 #include <gtest/gtest.h>
796@@ -32,229 +32,308 @@
797 namespace
798 {
799
800-class EventListener
801+class TestLauncherModel : public testing::Test
802 {
803- public:
804- EventListener()
805- {
806- icon_added = false;
807- icon_removed = false;
808- }
809-
810- void OnIconAdded (AbstractLauncherIcon::Ptr icon)
811- {
812- icon_added = true;
813- }
814-
815- void OnIconRemoved (AbstractLauncherIcon::Ptr icon)
816- {
817- icon_removed = true;
818- }
819-
820- bool icon_added;
821- bool icon_removed;
822+public:
823+ TestLauncherModel()
824+ : icon1(new MockLauncherIcon())
825+ , icon2(new MockLauncherIcon())
826+ , icon3(new MockLauncherIcon())
827+ , icon4(new MockLauncherIcon())
828+ {}
829+
830+ AbstractLauncherIcon::Ptr icon1;
831+ AbstractLauncherIcon::Ptr icon2;
832+ AbstractLauncherIcon::Ptr icon3;
833+ AbstractLauncherIcon::Ptr icon4;
834+
835+ LauncherModel model;
836 };
837-//bool seen_result;
838-
839-TEST(TestLauncherModel, TestConstructor)
840-{
841- LauncherModel::Ptr model(new LauncherModel());
842- EXPECT_EQ(model->Size(), 0);
843-}
844-
845-TEST(TestLauncherModel, TestAdd)
846-{
847- AbstractLauncherIcon::Ptr first(new MockLauncherIcon());
848- LauncherModel::Ptr model(new LauncherModel());
849-
850- EXPECT_EQ(model->Size(), 0);
851- model->AddIcon(first);
852- EXPECT_EQ(model->Size(), 1);
853-}
854-
855-TEST(TestLauncherModel, TestRemove)
856-{
857- AbstractLauncherIcon::Ptr first(new MockLauncherIcon());
858- LauncherModel::Ptr model(new LauncherModel());
859-
860- EXPECT_EQ(model->Size(), 0);
861- model->AddIcon(first);
862- EXPECT_EQ(model->Size(), 1);
863- model->RemoveIcon(first);
864- EXPECT_EQ(model->Size(), 0);
865-}
866-
867-TEST(TestLauncherModel, TestAddSignal)
868-{
869- AbstractLauncherIcon::Ptr first(new MockLauncherIcon());
870- LauncherModel::Ptr model(new LauncherModel());
871-
872- EventListener *listener = new EventListener();
873-
874- model->icon_added.connect(sigc::mem_fun(listener, &EventListener::OnIconAdded));
875- model->AddIcon(first);
876- EXPECT_EQ(listener->icon_added, true);
877-
878- delete listener;
879-}
880-
881-TEST(TestLauncherModel, TestRemoveSignal)
882-{
883- AbstractLauncherIcon::Ptr first(new MockLauncherIcon());
884- LauncherModel::Ptr model(new LauncherModel());
885-
886- EventListener *listener = new EventListener();
887-
888- model->icon_removed.connect(sigc::mem_fun(listener, &EventListener::OnIconRemoved));
889- model->AddIcon(first);
890- EXPECT_EQ(listener->icon_removed, false);
891- model->RemoveIcon(first);
892- EXPECT_EQ(listener->icon_removed, true);
893-
894- delete listener;
895-}
896-
897-TEST(TestLauncherModel, TestSort)
898-{
899- AbstractLauncherIcon::Ptr first(new MockLauncherIcon());
900- AbstractLauncherIcon::Ptr second(new MockLauncherIcon());
901- AbstractLauncherIcon::Ptr third(new MockLauncherIcon());
902- AbstractLauncherIcon::Ptr fourth(new MockLauncherIcon());
903-
904- LauncherModel::Ptr model(new LauncherModel());
905-
906- third->SetSortPriority(0);
907- model->AddIcon(third);
908-
909- first->SetSortPriority(-1);
910- model->AddIcon(first);
911-
912- fourth->SetSortPriority(2);
913- model->AddIcon(fourth);
914-
915- second->SetSortPriority(0);
916- model->AddIcon(second);
917-
918- LauncherModel::iterator it;
919- it = model->begin();
920-
921- EXPECT_EQ(first, *it);
922- it++;
923- EXPECT_EQ(second, *it);
924- it++;
925- EXPECT_EQ(third, *it);
926- it++;
927- EXPECT_EQ(fourth, *it);
928-}
929-
930-TEST(TestLauncherModel, TestReorderBefore)
931-{
932- AbstractLauncherIcon::Ptr first(new MockLauncherIcon());
933- AbstractLauncherIcon::Ptr second(new MockLauncherIcon());
934- AbstractLauncherIcon::Ptr third(new MockLauncherIcon());
935- AbstractLauncherIcon::Ptr fourth(new MockLauncherIcon());
936-
937- LauncherModel::Ptr model(new LauncherModel());
938-
939- first->SetSortPriority(0);
940- second->SetSortPriority(1);
941- third->SetSortPriority(2);
942- fourth->SetSortPriority(3);
943-
944- model->AddIcon(first);
945- model->AddIcon(second);
946- model->AddIcon(third);
947- model->AddIcon(fourth);
948-
949- model->ReorderBefore(third, second, false);
950-
951- LauncherModel::iterator it;
952- it = model->begin();
953-
954- EXPECT_EQ(first, *it);
955- it++;
956- EXPECT_EQ(third, *it);
957- it++;
958- EXPECT_EQ(second, *it);
959- it++;
960- EXPECT_EQ(fourth, *it);
961-}
962-
963-TEST(TestLauncherModel, TestReorderSmart)
964-{
965- AbstractLauncherIcon::Ptr first(new MockLauncherIcon());
966- AbstractLauncherIcon::Ptr second(new MockLauncherIcon());
967- AbstractLauncherIcon::Ptr third(new MockLauncherIcon());
968- AbstractLauncherIcon::Ptr fourth(new MockLauncherIcon());
969-
970- LauncherModel::Ptr model(new LauncherModel());
971-
972- first->SetSortPriority(0);
973- second->SetSortPriority(1);
974- third->SetSortPriority(2);
975- fourth->SetSortPriority(3);
976-
977- model->AddIcon(first);
978- model->AddIcon(second);
979- model->AddIcon(third);
980- model->AddIcon(fourth);
981-
982- model->ReorderSmart(third, second, false);
983-
984- LauncherModel::iterator it;
985- it = model->begin();
986-
987- EXPECT_EQ(first, *it);
988- it++;
989- EXPECT_EQ(third, *it);
990- it++;
991- EXPECT_EQ(second, *it);
992- it++;
993- EXPECT_EQ(fourth, *it);
994-}
995-
996-TEST(TestLauncherModel, TestGetClosestIcon)
997-{
998- LauncherModel::Ptr model(new LauncherModel());
999- AbstractLauncherIcon::Ptr first(new MockLauncherIcon());
1000- AbstractLauncherIcon::Ptr second(new MockLauncherIcon());
1001- AbstractLauncherIcon::Ptr third(new MockLauncherIcon());
1002- AbstractLauncherIcon::Ptr fourth(new MockLauncherIcon());
1003-
1004- first->SetSortPriority(0);
1005- second->SetSortPriority(1);
1006- third->SetSortPriority(2);
1007- fourth->SetSortPriority(3);
1008-
1009- model->AddIcon(first);
1010- model->AddIcon(second);
1011- model->AddIcon(third);
1012- model->AddIcon(fourth);
1013+
1014+TEST_F(TestLauncherModel, Constructor)
1015+{
1016+ EXPECT_EQ(model.Size(), 0);
1017+}
1018+
1019+TEST_F(TestLauncherModel, Add)
1020+{
1021+ model.AddIcon(icon1);
1022+ EXPECT_EQ(model.Size(), 1);
1023+
1024+ model.AddIcon(icon1);
1025+ EXPECT_EQ(model.Size(), 1);
1026+
1027+ model.AddIcon(AbstractLauncherIcon::Ptr());
1028+ EXPECT_EQ(model.Size(), 1);
1029+}
1030+
1031+TEST_F(TestLauncherModel, Remove)
1032+{
1033+ model.AddIcon(icon1);
1034+ EXPECT_EQ(model.Size(), 1);
1035+
1036+ model.RemoveIcon(icon1);
1037+ EXPECT_EQ(model.Size(), 0);
1038+}
1039+
1040+TEST_F(TestLauncherModel, AddSignal)
1041+{
1042+ bool icon_added = false;
1043+ model.icon_added.connect([&icon_added] (AbstractLauncherIcon::Ptr) { icon_added = true; });
1044+
1045+ model.AddIcon(icon1);
1046+ EXPECT_TRUE(icon_added);
1047+
1048+ icon_added = false;
1049+ model.AddIcon(icon1);
1050+ EXPECT_FALSE(icon_added);
1051+
1052+ icon_added = false;
1053+ model.AddIcon(AbstractLauncherIcon::Ptr());
1054+ EXPECT_FALSE(icon_added);
1055+}
1056+
1057+TEST_F(TestLauncherModel, RemoveSignal)
1058+{
1059+ bool icon_removed = false;
1060+ model.icon_removed.connect([&icon_removed] (AbstractLauncherIcon::Ptr) { icon_removed = true; });
1061+
1062+ model.AddIcon(icon1);
1063+ EXPECT_FALSE(icon_removed);
1064+ model.RemoveIcon(icon1);
1065+ EXPECT_TRUE(icon_removed);
1066+}
1067+
1068+TEST_F(TestLauncherModel, Sort)
1069+{
1070+ icon2->SetSortPriority(0);
1071+ model.AddIcon(icon2);
1072+
1073+ icon1->SetSortPriority(-1);
1074+ model.AddIcon(icon1);
1075+
1076+ icon4->SetSortPriority(2);
1077+ model.AddIcon(icon4);
1078+
1079+ icon3->SetSortPriority(0);
1080+ model.AddIcon(icon3);
1081+
1082+ LauncherModel::iterator it;
1083+ it = model.begin();
1084+
1085+ EXPECT_EQ(icon1, *it);
1086+ it++;
1087+ EXPECT_EQ(icon2, *it);
1088+ it++;
1089+ EXPECT_EQ(icon3, *it);
1090+ it++;
1091+ EXPECT_EQ(icon4, *it);
1092+}
1093+
1094+TEST_F(TestLauncherModel, ModelKeepsPriorityDeltas)
1095+{
1096+ icon2->SetSortPriority(0);
1097+ icon1->SetSortPriority(-1);
1098+ icon4->SetSortPriority(2);
1099+ icon3->SetSortPriority(0);
1100+
1101+ model.AddIcon(icon2);
1102+ model.AddIcon(icon1);
1103+ model.AddIcon(icon4);
1104+ model.AddIcon(icon3);
1105+
1106+ auto it = model.begin();
1107+ EXPECT_EQ(icon1, *it);
1108+ it++;
1109+ EXPECT_EQ(icon2, *it);
1110+ it++;
1111+ EXPECT_EQ(icon3, *it);
1112+ it++;
1113+ EXPECT_EQ(icon4, *it);
1114+
1115+ EXPECT_GT(icon2->SortPriority(), icon1->SortPriority());
1116+ EXPECT_EQ(icon2->SortPriority(), icon3->SortPriority());
1117+ EXPECT_LT(icon3->SortPriority(), icon4->SortPriority());
1118+}
1119+
1120+TEST_F(TestLauncherModel, ReorderBefore)
1121+{
1122+ icon1->SetSortPriority(0);
1123+ icon2->SetSortPriority(1);
1124+ icon3->SetSortPriority(2);
1125+ icon4->SetSortPriority(3);
1126+
1127+ model.AddIcon(icon1);
1128+ model.AddIcon(icon2);
1129+ model.AddIcon(icon3);
1130+ model.AddIcon(icon4);
1131+
1132+ model.ReorderBefore(icon3, icon2, false);
1133+
1134+ LauncherModel::iterator it;
1135+ it = model.begin();
1136+
1137+ EXPECT_EQ(icon1, *it);
1138+ it++;
1139+ EXPECT_EQ(icon3, *it);
1140+ it++;
1141+ EXPECT_EQ(icon2, *it);
1142+ it++;
1143+ EXPECT_EQ(icon4, *it);
1144+}
1145+
1146+TEST_F(TestLauncherModel, ReorderAfter)
1147+{
1148+ model.AddIcon(icon1);
1149+ model.AddIcon(icon3);
1150+ model.AddIcon(icon2);
1151+ model.AddIcon(icon4);
1152+
1153+ model.ReorderAfter(icon3, icon2);
1154+
1155+ LauncherModel::iterator it;
1156+ it = model.begin();
1157+
1158+ EXPECT_EQ(icon1, *it);
1159+ it++;
1160+ EXPECT_EQ(icon2, *it);
1161+ it++;
1162+ EXPECT_EQ(icon3, *it);
1163+ it++;
1164+ EXPECT_EQ(icon4, *it);
1165+}
1166+
1167+TEST_F(TestLauncherModel, ReorderSmart)
1168+{
1169+ icon1->SetSortPriority(0);
1170+ icon2->SetSortPriority(1);
1171+ icon3->SetSortPriority(2);
1172+ icon4->SetSortPriority(3);
1173+
1174+ model.AddIcon(icon1);
1175+ model.AddIcon(icon2);
1176+ model.AddIcon(icon3);
1177+ model.AddIcon(icon4);
1178+
1179+ model.ReorderSmart(icon3, icon2, false);
1180+
1181+ LauncherModel::iterator it;
1182+ it = model.begin();
1183+
1184+ EXPECT_EQ(icon1, *it);
1185+ it++;
1186+ EXPECT_EQ(icon3, *it);
1187+ it++;
1188+ EXPECT_EQ(icon2, *it);
1189+ it++;
1190+ EXPECT_EQ(icon4, *it);
1191+}
1192+
1193+TEST_F(TestLauncherModel, OrderByType)
1194+{
1195+ AbstractLauncherIcon::Ptr icon1(new MockLauncherIcon(AbstractLauncherIcon::IconType::HOME));
1196+ AbstractLauncherIcon::Ptr icon2(new MockLauncherIcon(AbstractLauncherIcon::IconType::APPLICATION));
1197+ AbstractLauncherIcon::Ptr icon3(new MockLauncherIcon(AbstractLauncherIcon::IconType::EXPO));
1198+ AbstractLauncherIcon::Ptr icon4(new MockLauncherIcon(AbstractLauncherIcon::IconType::DEVICE));
1199+ AbstractLauncherIcon::Ptr icon5(new MockLauncherIcon(AbstractLauncherIcon::IconType::TRASH));
1200+
1201+ model.AddIcon(icon3);
1202+ model.AddIcon(icon4);
1203+ model.AddIcon(icon2);
1204+ model.AddIcon(icon1);
1205+ model.AddIcon(icon5);
1206+
1207+ auto it = model.begin();
1208+ EXPECT_EQ(icon1, *it);
1209+ it++;
1210+ EXPECT_EQ(icon2, *it);
1211+ it++;
1212+ EXPECT_EQ(icon3, *it);
1213+ it++;
1214+ EXPECT_EQ(icon4, *it);
1215+ it++;
1216+ EXPECT_EQ(icon5, *it);
1217+ it++;
1218+ EXPECT_EQ(it, model.end());
1219+
1220+ auto it_main = model.main_begin();
1221+ EXPECT_EQ(icon1, *it_main);
1222+ it_main++;
1223+ EXPECT_EQ(icon2, *it_main);
1224+ it_main++;
1225+ EXPECT_EQ(icon3, *it_main);
1226+ it_main++;
1227+ EXPECT_EQ(icon4, *it_main);
1228+ it_main++;
1229+ EXPECT_EQ(it_main, model.main_end());
1230+
1231+ auto it_shelf = model.shelf_begin();
1232+ EXPECT_EQ(icon5, *it_shelf);
1233+ it_shelf++;
1234+ EXPECT_EQ(it_shelf, model.shelf_end());
1235+}
1236+
1237+TEST_F(TestLauncherModel, GetClosestIcon)
1238+{
1239+ model.AddIcon(icon1);
1240+ model.AddIcon(icon2);
1241+ model.AddIcon(icon3);
1242+ model.AddIcon(icon4);
1243
1244 bool before;
1245- EXPECT_EQ(model->GetClosestIcon(first, before), second);
1246+ EXPECT_EQ(model.GetClosestIcon(icon1, before), icon2);
1247 EXPECT_FALSE(before);
1248
1249- EXPECT_EQ(model->GetClosestIcon(second, before), first);
1250- EXPECT_TRUE(before);
1251-
1252- EXPECT_EQ(model->GetClosestIcon(third, before), second);
1253- EXPECT_TRUE(before);
1254-
1255- EXPECT_EQ(model->GetClosestIcon(fourth, before), third);
1256+ EXPECT_EQ(model.GetClosestIcon(icon2, before), icon1);
1257+ EXPECT_TRUE(before);
1258+
1259+ EXPECT_EQ(model.GetClosestIcon(icon3, before), icon2);
1260+ EXPECT_TRUE(before);
1261+
1262+ EXPECT_EQ(model.GetClosestIcon(icon4, before), icon3);
1263 EXPECT_TRUE(before);
1264 }
1265
1266-TEST(TestLauncherModel, TestGetClosestIconWithOneIcon)
1267+TEST_F(TestLauncherModel, GetClosestIconWithOneIcon)
1268 {
1269- LauncherModel::Ptr model(new LauncherModel());
1270- AbstractLauncherIcon::Ptr first(new MockLauncherIcon());
1271-
1272- model->AddIcon(first);
1273+ model.AddIcon(icon1);
1274
1275 bool before;
1276- EXPECT_EQ(model->GetClosestIcon(first, before), nullptr);
1277+ EXPECT_EQ(model.GetClosestIcon(icon1, before), nullptr);
1278 EXPECT_TRUE(before);
1279 }
1280
1281+TEST_F(TestLauncherModel, IconIndex)
1282+{
1283+ model.AddIcon(icon1);
1284+ model.AddIcon(icon2);
1285+ model.AddIcon(icon3);
1286+ model.AddIcon(icon4);
1287+
1288+ EXPECT_EQ(model.IconIndex(icon1), 0);
1289+ EXPECT_EQ(model.IconIndex(icon2), 1);
1290+ EXPECT_EQ(model.IconIndex(icon3), 2);
1291+ EXPECT_EQ(model.IconIndex(icon4), 3);
1292+
1293+ AbstractLauncherIcon::Ptr icon5(new MockLauncherIcon());
1294+ EXPECT_EQ(model.IconIndex(icon5), -1);
1295+}
1296+
1297+TEST_F(TestLauncherModel, IconHasSister)
1298+{
1299+ model.AddIcon(icon1);
1300+ EXPECT_FALSE(model.IconHasSister(icon1));
1301+
1302+ model.AddIcon(icon2);
1303+ model.AddIcon(icon3);
1304+ model.AddIcon(icon4);
1305+
1306+ EXPECT_TRUE(model.IconHasSister(icon1));
1307+ EXPECT_TRUE(model.IconHasSister(icon2));
1308+ EXPECT_TRUE(model.IconHasSister(icon3));
1309+ EXPECT_TRUE(model.IconHasSister(icon4));
1310+
1311+ EXPECT_FALSE(AbstractLauncherIcon::Ptr());
1312+}
1313+
1314 }