1
/*****************************************************************
3
Copyright 2008 Christian Mollekopf <chrigi_1@hotmail.com>
5
Permission is hereby granted, free of charge, to any person obtaining a copy
6
of this software and associated documentation files (the "Software"), to deal
7
in the Software without restriction, including without limitation the rights
8
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
copies of the Software, and to permit persons to whom the Software is
10
furnished to do so, subject to the following conditions:
12
The above copyright notice and this permission notice shall be included in
13
all copies or substantial portions of the Software.
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
******************************************************************/
24
#include "groupmanager.h"
34
#include "abstractsortingstrategy.h"
38
#include "taskgroup.h"
39
#include "taskmanager.h"
40
#include "strategies/alphasortingstrategy.h"
41
#include "strategies/desktopsortingstrategy.h"
42
#include "strategies/programgroupingstrategy.h"
43
#include "strategies/manualgroupingstrategy.h"
44
#include "strategies/kustodiangroupingstrategy.h"
45
#include "strategies/manualsortingstrategy.h"
46
#include "launcheritem.h"
51
class GroupManagerPrivate
54
GroupManagerPrivate(GroupManager *manager)
56
sortingStrategy(GroupManager::NoSorting),
57
groupingStrategy(GroupManager::NoGrouping),
58
lastGroupingStrategy(GroupManager::NoGrouping),
59
abstractGroupingStrategy(0),
60
abstractSortingStrategy(0),
63
showOnlyCurrentDesktop(false),
64
showOnlyCurrentActivity(false),
65
showOnlyCurrentScreen(false),
66
showOnlyMinimized(false),
67
onlyGroupWhenFull(false),
68
changingGroupingStrategy(false),
69
readingLauncherConfig(false)
73
/** reload all tasks from TaskManager */
75
void actuallyReloadTasks();
78
* Keep track of changes in Taskmanager
80
void currentDesktopChanged(int);
81
void currentActivityChanged(QString);
82
void taskChanged(TaskPtr, ::TaskManager::TaskChanges);
83
void checkScreenChange();
84
void taskDestroyed(QObject *item);
85
void startupItemDestroyed(AbstractGroupableItem *);
87
void actuallyCheckIfFull();
88
bool addTask(TaskPtr);
89
void removeTask(TaskPtr);
90
void addStartup(StartupPtr);
91
void removeStartup(StartupPtr);
92
void launcherVisibilityChange();
93
void checkLauncherVisibility(LauncherItem *launcher);
94
void saveLauncher(LauncherItem *launcher);
95
void saveLauncher(LauncherItem *launcher, KConfigGroup &group);
96
void unsaveLauncher(LauncherItem *launcher);
97
KConfigGroup launcherConfig(const KConfigGroup &config = KConfigGroup());
99
TaskGroup *currentRootGroup();
102
QHash<StartupPtr, TaskItem*> startupList;
103
GroupManager::TaskSortingStrategy sortingStrategy;
104
GroupManager::TaskGroupingStrategy groupingStrategy;
105
GroupManager::TaskGroupingStrategy lastGroupingStrategy;
106
AbstractGroupingStrategy *abstractGroupingStrategy;
107
AbstractSortingStrategy *abstractSortingStrategy;
111
QTimer checkIfFullTimer;
112
QSet<Task *> geometryTasks;
113
int groupIsFullLimit;
116
QHash<QString, QHash<int, TaskGroup*> > rootGroups; //container for groups
117
QHash<KUrl, LauncherItem *> launchers;
119
QString currentActivity;
121
bool showOnlyCurrentDesktop : 1;
122
bool showOnlyCurrentActivity : 1;
123
bool showOnlyCurrentScreen : 1;
124
bool showOnlyMinimized : 1;
125
bool onlyGroupWhenFull : 1;
126
bool changingGroupingStrategy : 1;
127
bool readingLauncherConfig : 1;
131
GroupManager::GroupManager(QObject *parent)
133
d(new GroupManagerPrivate(this))
135
connect(TaskManager::self(), SIGNAL(taskAdded(TaskPtr)), this, SLOT(addTask(TaskPtr)));
136
connect(TaskManager::self(), SIGNAL(taskRemoved(TaskPtr)), this, SLOT(removeTask(TaskPtr)));
137
connect(TaskManager::self(), SIGNAL(startupAdded(StartupPtr)), this, SLOT(addStartup(StartupPtr)));
138
connect(TaskManager::self(), SIGNAL(startupRemoved(StartupPtr)), this, SLOT(removeStartup(StartupPtr)));
140
d->currentDesktop = TaskManager::self()->currentDesktop();
141
d->currentActivity = TaskManager::self()->currentActivity();
143
d->rootGroups[d->currentActivity][d->currentDesktop] = new TaskGroup(this, "RootGroup", Qt::transparent);
145
d->reloadTimer.setSingleShot(true);
146
d->reloadTimer.setInterval(0);
147
connect(&d->reloadTimer, SIGNAL(timeout()), this, SLOT(actuallyReloadTasks()));
149
d->screenTimer.setSingleShot(true);
150
d->screenTimer.setInterval(100);
151
connect(&d->screenTimer, SIGNAL(timeout()), this, SLOT(checkScreenChange()));
153
d->checkIfFullTimer.setSingleShot(true);
154
d->checkIfFullTimer.setInterval(0);
155
connect(&d->checkIfFullTimer, SIGNAL(timeout()), this, SLOT(actuallyCheckIfFull()));
158
GroupManager::~GroupManager()
160
TaskManager::self()->setTrackGeometry(false, d->configToken);
161
delete d->abstractSortingStrategy;
162
delete d->abstractGroupingStrategy;
166
TaskGroup *GroupManagerPrivate::currentRootGroup()
168
return rootGroups[currentActivity][currentDesktop];
171
void GroupManagerPrivate::reloadTasks()
176
void GroupManagerPrivate::actuallyReloadTasks()
178
//kDebug() << "number of tasks available " << TaskManager::self()->tasks().size();
179
QHash<WId, TaskPtr> taskList = TaskManager::self()->tasks();
180
QMutableHashIterator<WId, TaskPtr> it(taskList);
182
while (it.hasNext()) {
185
if (addTask(it.value())) {
186
//kDebug() << "task added " << it.value()->visibleName();
191
// Remove what remains
193
while (it.hasNext()) {
195
removeTask(it.value());
201
void GroupManagerPrivate::addStartup(StartupPtr task)
204
if (!startupList.contains(task)) {
205
TaskItem *item = new TaskItem(q, task);
206
startupList.insert(task, item);
207
currentRootGroup()->add(item);
208
QObject::connect(item, SIGNAL(destroyed(AbstractGroupableItem*)),
209
q, SLOT(startupItemDestroyed(AbstractGroupableItem*)));
213
void GroupManagerPrivate::removeStartup(StartupPtr task)
216
if (!startupList.contains(task)) {
217
kDebug() << "invalid startup task";
221
AbstractGroupableItem *item = startupList.take(task);
222
if (item->parentGroup()) {
223
item->parentGroup()->remove(item);
227
bool GroupManagerPrivate::addTask(TaskPtr task)
230
/* kDebug() << task->visibleName()
231
<< task->visibleNameWithState()
234
<< task->classClass(); */
236
if (!task->showInTaskbar()) {
237
//kDebug() << "Do not show in taskbar";
241
if (showOnlyCurrentScreen && !task->isOnScreen(currentScreen)) {
242
//kDebug() << "Not on this screen and showOnlyCurrentScreen";
246
// Should the Task be displayed ? We always display if attention is demaded
247
if (!task->demandsAttention()) {
248
// As the Task doesn't demand attention
249
// go through all filters whether the task should be displayed or not
250
if (showOnlyCurrentDesktop && !task->isOnCurrentDesktop()) {
251
/* kDebug() << "Not on this desktop and showOnlyCurrentDesktop"
252
<< KWindowSystem::currentDesktop() << task->desktop(); */
256
if (showOnlyCurrentActivity && !task->isOnCurrentActivity()) {
257
/* kDebug() << "Not on this desktop and showOnlyCurrentActivity"
258
<< KWindowSystem::currentActivity() << task->desktop(); */
262
if (showOnlyMinimized && !task->isMinimized()) {
263
//kDebug() << "Not minimized and only showing minimized";
267
NET::WindowType type = task->info().windowType(NET::NormalMask | NET::DialogMask |
268
NET::OverrideMask | NET::UtilityMask);
269
if (type == NET::Utility) {
270
//kDebug() << "skipping utility window" << task->name();
274
//TODO: should we check for transiency? if so the following code can detect it.
276
QHash <TaskPtr, TaskItem*>::iterator it = d->itemList.begin();
278
while (it != d->itemList.end()) {
279
TaskItem *item = it.value();
280
if (item->task()->hasTransient(task->window())) {
281
kDebug() << "TRANSIENT TRANSIENT TRANSIENT!";
289
//Ok the Task should be displayed
290
TaskItem *item = qobject_cast<TaskItem*>(currentRootGroup()->getMemberByWId(task->window()));
292
// first search for an existing startuptask for this task
293
QHash<StartupPtr, TaskItem *>::iterator it = startupList.begin();
294
QHash<StartupPtr, TaskItem *>::iterator itEnd = startupList.end();
295
while (it != itEnd) {
296
if (it.key()->matchesWindow(task->window())) {
297
//kDebug() << "startup task found";
299
startupList.erase(it);
300
QObject::disconnect(item, 0, q, 0);
301
item->setTaskPointer(task);
308
item = new TaskItem(q, task);
311
QObject::connect(task.data(), SIGNAL(destroyed(QObject*)),
312
q, SLOT(taskDestroyed(QObject*)));
314
foreach (LauncherItem *launcher, launchers) {
315
launcher->associateItemIfMatches(item);
319
//Find a fitting group for the task with GroupingStrategies
320
if (abstractGroupingStrategy && !task->demandsAttention()) { //do not group attention tasks
321
abstractGroupingStrategy->handleItem(item);
323
currentRootGroup()->add(item);
326
geometryTasks.insert(task.data());
332
void GroupManagerPrivate::removeTask(TaskPtr task)
334
//kDebug() << "remove: " << task->visibleName();
335
geometryTasks.remove(task.data());
337
AbstractGroupableItem *item = currentRootGroup()->getMemberByWId(task->window());
339
// this can happen if the window hasn't been caught previously,
340
// of it it is an ignored type such as a NET::Utility type window
341
//kDebug() << "invalid item";
345
if (item->parentGroup()) {
346
item->parentGroup()->remove(item);
349
//the item must exist as long as the TaskPtr does because of activate calls so don't delete the item here, it will delete itself.
352
void GroupManagerPrivate::taskDestroyed(QObject *item)
354
Task *task = static_cast<Task*>(item);
356
geometryTasks.remove(task);
360
void GroupManagerPrivate::startupItemDestroyed(AbstractGroupableItem *item)
362
TaskItem *taskItem = static_cast<TaskItem*>(item);
363
startupList.remove(startupList.key(taskItem));
364
geometryTasks.remove(taskItem->task().data());
367
bool GroupManager::manualGroupingRequest(AbstractGroupableItem* item, TaskGroup* groupItem)
369
if (d->abstractGroupingStrategy) {
370
return d->abstractGroupingStrategy->manualGroupingRequest(item, groupItem);
375
bool GroupManager::manualGroupingRequest(ItemList items)
377
if (d->abstractGroupingStrategy) {
378
return d->abstractGroupingStrategy->manualGroupingRequest(items);
383
bool GroupManager::manualSortingRequest(AbstractGroupableItem* taskItem, int newIndex)
385
if (d->abstractSortingStrategy) {
386
return d->abstractSortingStrategy->manualSortingRequest(taskItem, newIndex);
392
GroupPtr GroupManager::rootGroup() const
394
return d->currentRootGroup();
397
void GroupManagerPrivate::currentActivityChanged(QString newActivity)
399
if (!showOnlyCurrentActivity || currentActivity == newActivity) {
403
if (!rootGroups.contains(newActivity) || !rootGroups.value(newActivity).contains(currentDesktop)) {
404
kDebug() << "created new desk group";
405
rootGroups[newActivity][currentDesktop] = new TaskGroup(q, "RootGroup", Qt::transparent);
406
if (abstractSortingStrategy) {
407
abstractSortingStrategy->handleGroup(rootGroups[newActivity][currentDesktop]);
411
if (onlyGroupWhenFull) {
412
QObject::disconnect(currentRootGroup(), SIGNAL(itemAdded(AbstractGroupableItem *)), q, SLOT(checkIfFull()));
413
QObject::disconnect(currentRootGroup(), SIGNAL(itemRemoved(AbstractGroupableItem *)), q, SLOT(checkIfFull()));
416
currentActivity = newActivity;
418
foreach (LauncherItem *item, launchers) {
419
rootGroups[currentActivity][currentDesktop]->add(item);
422
if (onlyGroupWhenFull) {
423
QObject::connect(currentRootGroup(), SIGNAL(itemAdded(AbstractGroupableItem *)), q, SLOT(checkIfFull()));
424
QObject::connect(currentRootGroup(), SIGNAL(itemRemoved(AbstractGroupableItem *)), q, SLOT(checkIfFull()));
430
void GroupManagerPrivate::currentDesktopChanged(int newDesktop)
433
if (!showOnlyCurrentDesktop) {
437
if (currentDesktop == newDesktop) {
441
if (!rootGroups[currentActivity].contains(newDesktop)) {
442
kDebug() << "created new desk group";
443
rootGroups[currentActivity][newDesktop] = new TaskGroup(q, "RootGroup", Qt::transparent);
444
if (abstractSortingStrategy) {
445
abstractSortingStrategy->handleGroup(rootGroups[currentActivity][newDesktop]);
449
if (onlyGroupWhenFull) {
450
QObject::disconnect(currentRootGroup(), SIGNAL(itemAdded(AbstractGroupableItem *)), q, SLOT(checkIfFull()));
451
QObject::disconnect(currentRootGroup(), SIGNAL(itemRemoved(AbstractGroupableItem *)), q, SLOT(checkIfFull()));
454
currentDesktop = newDesktop;
456
foreach (LauncherItem *item, launchers) {
457
rootGroups[currentActivity][currentDesktop]->add(item);
460
if (onlyGroupWhenFull) {
461
QObject::connect(currentRootGroup(), SIGNAL(itemAdded(AbstractGroupableItem *)), q, SLOT(checkIfFull()));
462
QObject::connect(currentRootGroup(), SIGNAL(itemRemoved(AbstractGroupableItem *)), q, SLOT(checkIfFull()));
469
void GroupManagerPrivate::taskChanged(TaskPtr task, ::TaskManager::TaskChanges changes)
472
bool takeAction = false;
475
if (showOnlyCurrentDesktop && changes & ::TaskManager::DesktopChanged) {
477
show = task->isOnCurrentDesktop();
478
//kDebug() << task->visibleName() << "on" << TaskManager::self()->currentDesktop();
481
if (showOnlyCurrentActivity && changes & ::TaskManager::ActivitiesChanged) {
483
show = task->isOnCurrentActivity();
484
//kDebug() << task->visibleName() << "on" << TaskManager::self()->currentDesktop();
487
if (showOnlyMinimized && changes & ::TaskManager::StateChanged) {
488
//TODO: wouldn't it be nice to get notification of JUST minimization?
490
show = task->isMinimized();
493
if (showOnlyCurrentScreen && changes & ::TaskManager::GeometryChanged) {
494
geometryTasks.insert(task.data());
496
if (!screenTimer.isActive()) {
501
if (changes & ::TaskManager::AttentionChanged) {
502
// we show tasks anyway if they demand attention
503
// so whenever our state changes ... try to re-adjust it
512
show = show && (!showOnlyCurrentScreen || task->isOnScreen(currentScreen));
515
//kDebug() << "add(task);";
518
//kDebug() << "remove(task);";
523
void GroupManager::setScreen(int screen)
525
//kDebug() << "new Screen: " << screen;
526
d->currentScreen = screen;
531
void GroupManagerPrivate::checkScreenChange()
534
foreach (Task *task, geometryTasks) {
535
if (task->isOnScreen(currentScreen)) {
536
addTask(TaskPtr(task));
538
removeTask(TaskPtr(task));
543
void GroupManager::reconnect()
546
disconnect(TaskManager::self(), SIGNAL(desktopChanged(int)),
547
this, SLOT(currentDesktopChanged(int)));
548
disconnect(TaskManager::self(), SIGNAL(activityChanged(QString)),
549
this, SLOT(currentActivityChanged(QString)));
550
disconnect(TaskManager::self(), SIGNAL(windowChanged(TaskPtr,::TaskManager::TaskChanges)),
551
this, SLOT(taskChanged(TaskPtr,::TaskManager::TaskChanges)));
553
if (d->showOnlyCurrentDesktop || d->showOnlyMinimized || d->showOnlyCurrentScreen || d->showOnlyCurrentActivity) {
554
// listen to the relevant task manager signals
555
if (d->showOnlyCurrentDesktop) {
556
connect(TaskManager::self(), SIGNAL(desktopChanged(int)),
557
this, SLOT(currentDesktopChanged(int)));
559
if (d->showOnlyCurrentActivity) {
560
connect(TaskManager::self(), SIGNAL(activityChanged(QString)),
561
this, SLOT(currentActivityChanged(QString)));
564
connect(TaskManager::self(), SIGNAL(windowChanged(TaskPtr,::TaskManager::TaskChanges)),
565
this, SLOT(taskChanged(TaskPtr,::TaskManager::TaskChanges)));
568
TaskManager::self()->setTrackGeometry(d->showOnlyCurrentScreen, d->configToken);
570
if (!d->showOnlyCurrentScreen) {
571
d->geometryTasks.clear();
577
KConfigGroup GroupManager::config() const
579
return KConfigGroup();
582
bool GroupManager::addLauncher(const KUrl &url, QIcon icon, QString name, QString genericName)
588
LauncherItem *launcher = d->launchers.value(url); // Do not insert launchers twice
590
launcher = new LauncherItem(d->currentRootGroup(), url);
592
if (!launcher->isValid()) {
597
if (!icon.isNull()) {
598
launcher->setIcon(icon);
601
if (!name.isEmpty()) {
602
launcher->setName(name);
605
if (!genericName.isEmpty()) {
606
launcher->setGenericName(genericName);
609
QStack<TaskGroup *> groups;
610
groups.push(d->currentRootGroup());
611
while (!groups.isEmpty()) {
612
TaskGroup *group = groups.pop();
614
foreach (AbstractGroupableItem *item, group->members()) {
615
if (item->itemType() == GroupItemType) {
616
groups.push(static_cast<TaskGroup *>(item));
618
launcher->associateItemIfMatches(item);
623
d->launchers.insert(url, launcher);
624
connect(launcher, SIGNAL(show(bool)), this, SLOT(launcherVisibilityChange()));
625
d->checkLauncherVisibility(launcher);
626
d->saveLauncher(launcher);
632
void GroupManager::removeLauncher(const KUrl &url)
634
LauncherItem *launcher = d->launchers.value(url);
639
d->launchers.remove(url);
641
typedef QHash<int,TaskGroup*> Metagroup;
642
foreach (Metagroup metagroup, d->rootGroups) {
643
foreach (TaskGroup *rootGroup, metagroup) {
644
rootGroup->remove(launcher);
648
d->unsaveLauncher(launcher);
649
launcher->deleteLater();
652
void GroupManagerPrivate::launcherVisibilityChange()
654
checkLauncherVisibility(qobject_cast<LauncherItem *>(q->sender()));
657
void GroupManagerPrivate::checkLauncherVisibility(LauncherItem *launcher)
663
typedef QHash<int, TaskGroup *> Metagroup;
664
foreach (Metagroup metagroup, rootGroups) {
665
foreach (TaskGroup *rootGroup, metagroup) {
666
if (launcher->shouldShow()) {
667
rootGroup->add(launcher);
669
rootGroup->remove(launcher);
675
bool GroupManager::launcherExists(const KUrl &url) const
677
return d->launchers.value(url);
680
void GroupManager::readLauncherConfig(const KConfigGroup &cg)
682
KConfigGroup conf = d->launcherConfig(cg);
683
if (!conf.isValid()) {
687
// prevents re-writing the results out
688
d->readingLauncherConfig = true;
690
foreach (const QString &key, conf.keyList()) {
691
QStringList item = conf.readEntry(key, QStringList());
692
if (item.length() >= 4) {
693
KUrl url(item.at(0));
695
if (!item.at(1).isEmpty()) {
696
icon = KIcon(item.at(1));
697
} else if (item.length() >= 5) {
699
QByteArray bytes = QByteArray::fromBase64(item.at(4).toAscii());
700
pixmap.loadFromData(bytes);
701
icon.addPixmap(pixmap);
703
QString name(item.at(2));
704
QString genericName(item.at(3));
706
if (addLauncher(url, icon, name, genericName)) {
712
d->readingLauncherConfig = false;
714
// a bit paranoiac, perhaps, but we check the removals first and then
715
// remove the launchers after that scan because Qt's iterators operate
716
// on a copy of the list and/or don't like multiple iterators messing
717
// with the same list. we might get away with just calling removeLauncher
718
// immediately without the removals KUrl::List, but this is known safe
719
// and not a performance bottleneck
721
foreach (LauncherItem *launcher, d->launchers) {
722
if (!urls.contains(launcher->launcherUrl())) {
723
removals << launcher->launcherUrl();
727
foreach (const KUrl &url, removals) {
732
void GroupManager::exportLauncherConfig(const KConfigGroup &cg)
734
KConfigGroup conf = d->launcherConfig(cg);
735
if (!conf.isValid()) {
739
foreach (LauncherItem *launcher, d->launchers) {
740
d->saveLauncher(launcher, conf);
744
KConfigGroup GroupManagerPrivate::launcherConfig(const KConfigGroup &config)
746
KConfigGroup cg = config.isValid() ? config : q->config();
751
return KConfigGroup(&cg, "Launchers");
754
void GroupManagerPrivate::saveLauncher(LauncherItem *launcher)
756
if (readingLauncherConfig) {
760
KConfigGroup cg = launcherConfig();
765
saveLauncher(launcher, cg);
766
emit q->configChanged();
769
void GroupManagerPrivate::saveLauncher(LauncherItem *launcher, KConfigGroup &cg)
771
QVariantList launcherProperties;
772
launcherProperties.append(launcher->launcherUrl().url());
773
launcherProperties.append(launcher->icon().name());
774
launcherProperties.append(launcher->name());
775
launcherProperties.append(launcher->genericName());
777
if (launcher->icon().name().isEmpty()) {
778
QPixmap pixmap = launcher->icon().pixmap(QSize(64,64));
780
QBuffer buffer(&bytes);
781
buffer.open(QIODevice::WriteOnly);
782
pixmap.save(&buffer, "PNG");
783
launcherProperties.append(bytes.toBase64());
786
cg.writeEntry(launcher->name(), launcherProperties);
789
void GroupManagerPrivate::unsaveLauncher(LauncherItem *launcher)
791
KConfigGroup cg = launcherConfig();
796
cg.deleteEntry(launcher->name());
797
emit q->configChanged();
800
bool GroupManager::onlyGroupWhenFull() const
802
return d->onlyGroupWhenFull;
805
void GroupManager::setOnlyGroupWhenFull(bool onlyGroupWhenFull)
807
//kDebug() << onlyGroupWhenFull;
808
if (d->onlyGroupWhenFull == onlyGroupWhenFull) {
812
d->onlyGroupWhenFull = onlyGroupWhenFull;
814
disconnect(d->currentRootGroup(), SIGNAL(itemAdded(AbstractGroupableItem *)), this, SLOT(checkIfFull()));
815
disconnect(d->currentRootGroup(), SIGNAL(itemRemoved(AbstractGroupableItem *)), this, SLOT(checkIfFull()));
817
if (onlyGroupWhenFull) {
818
connect(d->currentRootGroup(), SIGNAL(itemAdded(AbstractGroupableItem *)), this, SLOT(checkIfFull()));
819
connect(d->currentRootGroup(), SIGNAL(itemRemoved(AbstractGroupableItem *)), this, SLOT(checkIfFull()));
824
void GroupManager::setFullLimit(int limit)
827
d->groupIsFullLimit = limit;
828
if (d->onlyGroupWhenFull) {
833
void GroupManagerPrivate::checkIfFull()
835
// Start a timer so that if we have been triggered by a layouting
836
// we give time for it to finish up instead of starting a new one
838
checkIfFullTimer.start();
841
void GroupManagerPrivate::actuallyCheckIfFull()
844
if (!onlyGroupWhenFull ||
845
groupingStrategy != GroupManager::ProgramGrouping ||
846
changingGroupingStrategy) {
850
if (currentRootGroup()->totalSize() >= groupIsFullLimit) {
851
if (!abstractGroupingStrategy) {
852
geometryTasks.clear();
853
q->setGroupingStrategy(GroupManager::ProgramGrouping);
855
} else if (abstractGroupingStrategy) {
856
geometryTasks.clear();
857
q->setGroupingStrategy(GroupManager::NoGrouping);
858
//let the visualization think we still use the programGrouping
859
groupingStrategy = GroupManager::ProgramGrouping;
863
bool GroupManager::showOnlyCurrentScreen() const
865
return d->showOnlyCurrentScreen;
868
void GroupManager::setShowOnlyCurrentScreen(bool showOnlyCurrentScreen)
870
d->showOnlyCurrentScreen = showOnlyCurrentScreen;
874
bool GroupManager::showOnlyCurrentDesktop() const
876
return d->showOnlyCurrentDesktop;
879
void GroupManager::setShowOnlyCurrentDesktop(bool showOnlyCurrentDesktop)
881
d->showOnlyCurrentDesktop = showOnlyCurrentDesktop;
885
bool GroupManager::showOnlyCurrentActivity() const
887
return d->showOnlyCurrentActivity;
890
void GroupManager::setShowOnlyCurrentActivity(bool showOnlyCurrentActivity)
892
d->showOnlyCurrentActivity = showOnlyCurrentActivity;
896
bool GroupManager::showOnlyMinimized() const
898
return d->showOnlyMinimized;
901
void GroupManager::setShowOnlyMinimized(bool showOnlyMinimized)
903
d->showOnlyMinimized = showOnlyMinimized;
907
GroupManager::TaskSortingStrategy GroupManager::sortingStrategy() const
909
return d->sortingStrategy;
912
AbstractSortingStrategy* GroupManager::taskSorter() const
914
return d->abstractSortingStrategy;
917
void GroupManager::setSortingStrategy(TaskSortingStrategy sortOrder)
919
//kDebug() << sortOrder;
921
if (d->abstractSortingStrategy) {
922
if (d->abstractSortingStrategy->type() == sortOrder) {
926
d->abstractSortingStrategy->deleteLater();
927
d->abstractSortingStrategy = 0;
932
d->abstractSortingStrategy = new ManualSortingStrategy(this);
936
d->abstractSortingStrategy = new AlphaSortingStrategy(this);
940
d->abstractSortingStrategy = new DesktopSortingStrategy(this);
943
case NoSorting: //manual and no grouping result both in non automatic grouping
947
kDebug() << "Invalid Strategy";
949
if (d->abstractSortingStrategy) {
950
typedef QHash<int,TaskGroup*> Metagroup;
951
foreach (Metagroup metagroup, d->rootGroups) {
952
foreach (TaskGroup *group, metagroup) {
953
d->abstractSortingStrategy->handleGroup(group);
958
d->sortingStrategy = sortOrder;
962
GroupManager::TaskGroupingStrategy GroupManager::groupingStrategy() const
964
return d->groupingStrategy;
967
AbstractGroupingStrategy* GroupManager::taskGrouper() const
969
return d->abstractGroupingStrategy;
973
void GroupManager::setGroupingStrategy(TaskGroupingStrategy strategy)
975
if (d->changingGroupingStrategy ||
976
(d->abstractGroupingStrategy && d->abstractGroupingStrategy->type() == strategy)) {
980
d->changingGroupingStrategy = true;
982
//kDebug() << strategy << kBacktrace();
983
if (d->onlyGroupWhenFull) {
984
disconnect(d->currentRootGroup(), SIGNAL(itemAdded(AbstractGroupableItem *)), this, SLOT(checkIfFull()));
985
disconnect(d->currentRootGroup(), SIGNAL(itemRemoved(AbstractGroupableItem *)), this, SLOT(checkIfFull()));
988
if (d->abstractGroupingStrategy) {
989
disconnect(d->abstractGroupingStrategy, 0, this, 0);
990
d->abstractGroupingStrategy->destroy();
991
d->abstractGroupingStrategy = 0;
996
d->abstractGroupingStrategy = new ManualGroupingStrategy(this);
999
case ProgramGrouping:
1000
d->abstractGroupingStrategy = new ProgramGroupingStrategy(this);
1003
case KustodianGrouping:
1004
d->abstractGroupingStrategy = new KustodianGroupingStrategy(this);
1011
kDebug() << "Strategy not implemented";
1014
d->groupingStrategy = strategy;
1016
d->actuallyReloadTasks();
1018
if (d->onlyGroupWhenFull) {
1019
connect(d->currentRootGroup(), SIGNAL(itemAdded(AbstractGroupableItem *)), this, SLOT(checkIfFull()));
1020
connect(d->currentRootGroup(), SIGNAL(itemRemoved(AbstractGroupableItem *)), this, SLOT(checkIfFull()));
1023
d->changingGroupingStrategy = false;
1026
} // TaskManager namespace
1028
#include "groupmanager.moc"