33
SwitcherModel::SwitcherModel(std::vector<AbstractLauncherIcon::Ptr> const& icons)
35
* Helper comparison functor for sorting application icons.
37
bool CompareSwitcherItemsPriority(AbstractLauncherIcon::Ptr const& first,
38
AbstractLauncherIcon::Ptr const& second)
40
if (first->GetIconType() == second->GetIconType())
41
return first->SwitcherPriority() > second->SwitcherPriority();
43
if (first->GetIconType() == AbstractLauncherIcon::IconType::DESKTOP)
46
if (second->GetIconType() == AbstractLauncherIcon::IconType::DESKTOP)
49
return first->GetIconType() < second->GetIconType();
54
SwitcherModel::SwitcherModel(Applications const& icons, bool sort_by_priority)
34
55
: detail_selection(false)
35
56
, detail_selection_index(0)
36
, only_detail_on_viewport(false)
57
, only_apps_on_viewport(true)
37
58
, applications_(icons)
59
, sort_by_priority_(sort_by_priority)
42
// When using Webapps, there are more than one active icon, so let's just pick
43
// up the first one found which is the web browser.
64
for (auto it = applications_.begin(); it != applications_.end();)
66
ConnectToIconSignals(*it);
68
if (!(*it)->ShowInSwitcher(only_apps_on_viewport))
70
hidden_applications_.push_back(*it);
71
it = applications_.erase(it);
78
if (sort_by_priority_)
79
std::sort(std::begin(applications_), std::end(applications_), CompareSwitcherItemsPriority);
81
UpdateLastActiveApplication();
83
only_apps_on_viewport.changed.connect([this] (bool) {
87
detail_selection.changed.connect([this] (bool) {
92
void SwitcherModel::UpdateLastActiveApplication()
47
94
for (auto const& application : applications_)
49
application->SetOrder(++order);
51
AddChild(application.GetPointer());
52
if (application->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE) && !found)
96
if (application->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE))
54
98
last_active_application_ = application;
60
SwitcherModel::~SwitcherModel()
62
for (auto const& application : applications_)
64
RemoveChild(application.GetPointer());
104
void SwitcherModel::VerifyApplications()
106
bool anything_changed = false;
108
for (auto it = applications_.begin(); it != applications_.end();)
110
if (!(*it)->ShowInSwitcher(only_apps_on_viewport))
112
unsigned icon_index = it - applications_.begin();
113
hidden_applications_.push_back(*it);
114
it = applications_.erase(it);
115
anything_changed = true;
116
bool was_in_detail = (detail_selection && icon_index == index_);
118
if (icon_index < index_ || index_ == applications_.size())
122
UnsetDetailSelection();
130
for (auto it = hidden_applications_.begin(); it != hidden_applications_.end();)
132
if ((*it)->ShowInSwitcher(only_apps_on_viewport))
135
it = hidden_applications_.erase(it);
136
anything_changed = true;
143
if (anything_changed)
145
if (!last_active_application_ || !last_active_application_->ShowInSwitcher(only_apps_on_viewport))
146
UpdateLastActiveApplication();
152
void SwitcherModel::InsertIcon(AbstractLauncherIcon::Ptr const& application)
154
if (sort_by_priority_)
156
auto pos = std::upper_bound(applications_.begin(), applications_.end(), application, CompareSwitcherItemsPriority);
157
unsigned icon_index = pos - applications_.begin();
158
applications_.insert(pos, application);
160
if (icon_index <= index_)
165
applications_.push_back(application);
169
void SwitcherModel::ConnectToIconSignals(launcher::AbstractLauncherIcon::Ptr const& icon)
171
icon->quirks_changed.connect(sigc::hide(sigc::hide(sigc::mem_fun(this, &SwitcherModel::OnIconQuirksChanged))));
172
icon->windows_changed.connect(sigc::hide(sigc::bind(sigc::mem_fun(this, &SwitcherModel::OnIconWindowsUpdated), icon.GetPointer())));
175
void SwitcherModel::AddIcon(AbstractLauncherIcon::Ptr const& icon)
177
if (!icon || icon->GetIconType() != AbstractLauncherIcon::IconType::APPLICATION)
180
if (icon->ShowInSwitcher(only_apps_on_viewport))
182
if (icon->GetQuirk(AbstractLauncherIcon::Quirk::ACTIVE))
183
last_active_application_ = icon;
185
if (std::find(applications_.begin(), applications_.end(), icon) == applications_.end())
188
ConnectToIconSignals(icon);
192
else if (std::find(hidden_applications_.begin(), hidden_applications_.end(), icon) == hidden_applications_.end())
194
hidden_applications_.push_back(icon);
195
ConnectToIconSignals(icon);
199
void SwitcherModel::RemoveIcon(launcher::AbstractLauncherIcon::Ptr const& icon)
201
auto icon_it = std::find(applications_.begin(), applications_.end(), icon);
202
if (icon_it != applications_.end())
204
unsigned icon_index = icon_it - applications_.begin();
205
bool was_in_detail = (detail_selection && icon_index == index_);
206
applications_.erase(icon_it);
208
if (last_active_application_ == icon)
209
UpdateLastActiveApplication();
211
if (icon_index < index_ || index_ == applications_.size())
215
UnsetDetailSelection();
221
hidden_applications_.erase(std::remove(hidden_applications_.begin(), hidden_applications_.end(), icon), hidden_applications_.end());
225
void SwitcherModel::OnIconQuirksChanged()
227
auto old_selection = Selection();
228
VerifyApplications();
230
if (old_selection == last_active_application_)
231
UpdateLastActiveApplication();
233
auto const& new_selection = Selection();
235
if (old_selection != new_selection)
236
selection_changed.emit(new_selection);
239
void SwitcherModel::OnIconWindowsUpdated(AbstractLauncherIcon* icon)
241
if (detail_selection() && icon == Selection().GetPointer())
245
if (detail_selection_index() >= detail_xids_.size())
246
detail_selection_index = detail_xids_.empty() ? 0 : detail_xids_.size() - 1;
68
252
std::string SwitcherModel::GetName() const
76
260
.add("detail-selection", detail_selection)
77
.add("detail-selection-index", (int)detail_selection_index)
78
.add("detail-current-count", DetailXids().size())
79
.add("detail-windows", glib::Variant::FromVector(DetailXids()))
80
.add("only-detail-on-viewport", only_detail_on_viewport)
261
.add("detail-selection-index", detail_selection_index())
262
.add("detail-current-count", SelectionWindows().size())
263
.add("detail-windows", glib::Variant::FromVector(SelectionWindows()))
264
.add("only-apps-on-viewport", only_apps_on_viewport())
81
265
.add("selection-index", SelectionIndex())
82
266
.add("last-selection-index", LastSelectionIndex());
269
debug::Introspectable::IntrospectableList SwitcherModel::GetIntrospectableChildren()
271
debug::Introspectable::IntrospectableList children;
274
for (auto const& icon : applications_)
276
if (!icon->ShowInSwitcher(only_apps_on_viewport))
278
icon->SetOrder(++order);
279
children.push_back(icon.GetPointer());
85
286
SwitcherModel::iterator SwitcherModel::begin()
87
288
return applications_.begin();
381
void SwitcherModel::UpdateDetailXids()
383
detail_xids_.clear();
385
if (detail_selection)
386
detail_xids_ = SelectionWindows();
174
389
Window SwitcherModel::DetailSelectionWindow() const
176
auto windows = DetailXids();
177
if (!detail_selection || windows.empty())
180
if (detail_selection_index > windows.size() - 1)
183
return windows[detail_selection_index];
391
if (!detail_selection || detail_xids_.empty())
394
if (detail_selection_index > detail_xids_.size() - 1)
397
return detail_xids_[detail_selection_index];
400
void SwitcherModel::UnsetDetailSelection()
402
detail_selection = false;
403
detail_selection_index = 0;
407
void SwitcherModel::NextIndex()
409
last_index_ = index_;
410
++index_ %= applications_.size();
186
413
void SwitcherModel::Next()
416
UnsetDetailSelection();
417
selection_changed.emit(Selection());
420
void SwitcherModel::PrevIndex()
188
422
last_index_ = index_;
191
if (index_ >= applications_.size())
194
detail_selection = false;
195
detail_selection_index = 0;
197
selection_changed.emit(Selection());
423
index_ = ((index_ > 0 && index_ < applications_.size()) ? index_ : applications_.size()) - 1;
200
426
void SwitcherModel::Prev()
202
last_index_ = index_;
207
index_ = applications_.size() - 1;
209
detail_selection = false;
210
detail_selection_index = 0;
429
UnsetDetailSelection();
212
430
selection_changed.emit(Selection());