• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

libtaskmanager

groupmanager.cpp

Go to the documentation of this file.
00001 /*****************************************************************
00002 
00003 Copyright 2008 Christian Mollekopf <chrigi_1@hotmail.com>
00004 
00005 Permission is hereby granted, free of charge, to any person obtaining a copy
00006 of this software and associated documentation files (the "Software"), to deal
00007 in the Software without restriction, including without limitation the rights
00008 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00009 copies of the Software, and to permit persons to whom the Software is
00010 furnished to do so, subject to the following conditions:
00011 
00012 The above copyright notice and this permission notice shall be included in
00013 all copies or substantial portions of the Software.
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
00018 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00019 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00020 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00021 
00022 ******************************************************************/
00023 
00024 #include "groupmanager.h"
00025 
00026 #include <QList>
00027 #include <KDebug>
00028 #include <QTimer>
00029 #include <QUuid>
00030 
00031 #include "abstractsortingstrategy.h"
00032 #include "startup.h"
00033 #include "task.h"
00034 #include "taskitem.h"
00035 #include "taskgroup.h"
00036 #include "taskmanager.h"
00037 #include "strategies/alphasortingstrategy.h"
00038 #include "strategies/desktopsortingstrategy.h"
00039 #include "strategies/programgroupingstrategy.h"
00040 #include "strategies/manualgroupingstrategy.h"
00041 #include "strategies/manualsortingstrategy.h"
00042 
00043 namespace TaskManager
00044 {
00045 
00046 class GroupManagerPrivate
00047 {
00048 public:
00049     GroupManagerPrivate(GroupManager *manager)
00050         : q(manager),
00051           rootGroup(0),
00052           sortingStrategy(GroupManager::NoSorting),
00053           groupingStrategy(GroupManager::NoGrouping),
00054           lastGroupingStrategy(GroupManager::NoGrouping),
00055           abstractGroupingStrategy(0),
00056           abstractSortingStrategy(0),
00057           currentScreen(-1),
00058           groupIsFullLimit(0),
00059           showOnlyCurrentDesktop(false),
00060           showOnlyCurrentScreen(false),
00061           showOnlyMinimized(false),
00062           onlyGroupWhenFull(false),
00063           changingGroupingStragegy(false)
00064     {
00065     }
00066 
00068     void reloadTasks();
00069 
00073     void currentDesktopChanged(int);
00074     void taskChanged(TaskPtr, ::TaskManager::TaskChanges);
00075 
00076     void checkScreenChange();
00077 
00078     void itemDestroyed();
00079     void checkIfFull();
00080 
00081     GroupManager *q;
00082     QHash<TaskPtr, TaskItem*> itemList; //holds all tasks of the Taskmanager
00083     QHash<StartupPtr, TaskItem*> startupList;
00084     TaskGroup *rootGroup; //the current layout
00085     GroupManager::TaskSortingStrategy sortingStrategy;
00086     GroupManager::TaskGroupingStrategy groupingStrategy;
00087     GroupManager::TaskGroupingStrategy lastGroupingStrategy;
00088     AbstractGroupingStrategy *abstractGroupingStrategy;
00089     AbstractSortingStrategy *abstractSortingStrategy;
00090     int currentScreen;
00091     QTimer screenTimer;
00092     QList<TaskPtr> geometryTasks;
00093     int groupIsFullLimit;
00094     bool showOnlyCurrentDesktop : 1;
00095     bool showOnlyCurrentScreen : 1;
00096     bool showOnlyMinimized : 1;
00097     bool onlyGroupWhenFull : 1;
00098     bool changingGroupingStragegy : 1;
00099     QUuid configToken;
00100 };
00101 
00102 
00103 
00104 
00105 GroupManager::GroupManager(QObject *parent)
00106     : QObject(parent),
00107       d(new GroupManagerPrivate(this))
00108 {
00109     connect(TaskManager::self(), SIGNAL(taskAdded(TaskPtr)), this, SLOT(add(TaskPtr)));
00110     connect(TaskManager::self(), SIGNAL(taskRemoved(TaskPtr)), this, SLOT(remove(TaskPtr)));
00111     connect(TaskManager::self(), SIGNAL(startupAdded(StartupPtr)), this, SLOT(add(StartupPtr)));
00112     connect(TaskManager::self(), SIGNAL(startupRemoved(StartupPtr)), this, SLOT(remove(StartupPtr)));
00113     d->rootGroup = new TaskGroup(this, "RootGroup", Qt::transparent);
00114     //reloadTasks();
00115     d->screenTimer.setSingleShot(true);
00116     d->screenTimer.setInterval(100);
00117     connect(&d->screenTimer, SIGNAL(timeout()), this, SLOT(checkScreenChange()));
00118 }
00119 
00120 GroupManager::~GroupManager()
00121 {
00122     TaskManager::TaskManager::self()->setTrackGeometry(false, d->configToken);
00123     delete d->abstractSortingStrategy;
00124     delete d->abstractGroupingStrategy;
00125     delete d->rootGroup;
00126     delete d;
00127 }
00128 
00129 void GroupManagerPrivate::reloadTasks()
00130 {
00131     //kDebug() << "number of tasks available " << TaskManager::self()->tasks().size();
00132 
00133     QList <TaskPtr> taskList = TaskManager::self()->tasks().values();
00134     foreach (const TaskPtr& task, taskList) { //Add all existing tasks
00135         if (!q->add(task)) {
00136             q->remove(task); //remove what isn't needed anymore
00137         }
00138         taskList.removeAll(task);
00139     }
00140 
00141     foreach (const TaskPtr& task, taskList) { //Remove the remaining
00142         q->remove(task);
00143     }
00144 
00145     emit q->reload();
00146 }
00147 
00148 void GroupManager::add(StartupPtr task)
00149 {
00150     //kDebug();
00151     TaskItem *item;
00152     if (!d->startupList.contains(task)) {
00153         item = new TaskItem(this, task);
00154         d->startupList.insert(task, item); 
00155         d->rootGroup->add(item);
00156     }
00157 }
00158 
00159 void GroupManager::remove(StartupPtr task)
00160 {
00161     //kDebug() << "startup";
00162     if (!d->startupList.contains(task)) {
00163         kDebug() << "invalid startup task";
00164         return;
00165     }
00166 
00167     AbstractItemPtr item = d->startupList.take(task);
00168     if (item->parentGroup()) {
00169         item->parentGroup()->remove(item);
00170     }
00171 
00172     emit itemRemoved(item);
00173 }
00174 
00175 bool GroupManager::add(TaskPtr task)
00176 {
00177     /* kDebug() << task->visibleName()
00178              << task->visibleNameWithState()
00179              << task->name()
00180              << task->className()
00181              << task->classClass(); */
00182 
00183     if (!task->showInTaskbar()) {
00184         //kDebug() << "Do not show in taskbar";
00185         return false;
00186     }
00187 
00188     if (showOnlyCurrentScreen() && !task->isOnScreen(d->currentScreen)) {
00189         //kDebug() << "Not on this screen and showOnlyCurrentScreen";
00190         return false;
00191     }
00192 
00193     // Should the Task be displayed ? We always display if attention is demaded
00194     if (!task->demandsAttention()) {
00195         // As the Task doesn't demand attention
00196         // go through all filters whether the task should be displayed or not
00197         if (showOnlyCurrentDesktop() && !task->isOnCurrentDesktop()) {
00198             /* kDebug() << "Not on this desktop and showOnlyCurrentDesktop"
00199                      << KWindowSystem::currentDesktop() << task->desktop(); */
00200             return false;
00201         }
00202 
00203         if (showOnlyMinimized() && !task->isMinimized()) {
00204             //kDebug() << "Not minimized and only showing minimized";
00205             return false;
00206         }
00207 
00208         NET::WindowType type = task->info().windowType(NET::NormalMask | NET::DialogMask |
00209                                                     NET::OverrideMask | NET::UtilityMask);
00210         if (type == NET::Utility) {
00211             //kDebug() << "skipping utility window" << task->name();
00212             return false;
00213         }
00214 
00215             //TODO: should we check for transiency? if so the following code can detect it.
00216         /*
00217             QHash <TaskPtr, TaskItem*>::iterator it = d->itemList.begin();
00218 
00219             while (it != d->itemList.end()) {
00220                 TaskItem *item = it.value();
00221                 if (item->task()->hasTransient(task->window())) {
00222                     kDebug() << "TRANSIENT TRANSIENT TRANSIENT!";
00223                     return flase;
00224                 }
00225                 ++it;
00226             }
00227         */
00228     }
00229 
00230     //Ok the Task should be displayed
00231     TaskItem *item = 0;
00232     if (!d->itemList.contains(task)) {
00233         //Lookout for existing startuptask of this task
00234         QMutableHashIterator<StartupPtr, TaskItem*> it(d->startupList);
00235         while (it.hasNext()) {
00236             it.next();
00237             if (it.key()->matchesWindow(task->window())) {
00238                 //kDebug() << "startup task";
00239                 item = it.value();
00240                 item->setTaskPointer(task);
00241                 it.remove();
00242                 break;
00243             }
00244         }
00245 
00246         if (!item) {
00247             item = new TaskItem(this, task);
00248         }
00249 
00250         connect(item, SIGNAL(destroyed()), this, SLOT(itemDestroyed()));
00251         d->itemList.insert(task, item); 
00252     } else {
00253         item = d->itemList.value(task); //we add it again so the group is evaluated again
00254     }
00255 
00256     //Find a fitting group for the task with GroupingStrategies
00257     if (d->abstractGroupingStrategy && !task->demandsAttention()) { //do not group attetion tasks
00258         d->abstractGroupingStrategy->handleItem(item);
00259     } else {
00260         d->rootGroup->add(item);
00261     }
00262 
00263     return true;
00264 }
00265 
00266 
00267 void GroupManager::remove(TaskPtr task)
00268 {
00269     //kDebug() << "remove: " << task->visibleName();
00270     if (!d->geometryTasks.isEmpty()) {
00271         d->geometryTasks.removeAll(task);
00272     }
00273 
00274     TaskItem *item = d->itemList.value(task);
00275     if (!item) {
00276         // this can happen if the window hasn't been caught previously, 
00277         // of it its an ignored type such as a NET::Utility type window
00278         //kDebug() << "invalid item";
00279         return;
00280     }
00281 
00282     if (item->parentGroup()) {
00283         item->parentGroup()->remove(item);
00284     }
00285 
00286     emit itemRemoved(item);
00287     //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. We keep it in the itemlist because it may return
00288 }
00289 
00290 void GroupManagerPrivate::itemDestroyed()
00291 {
00292     TaskItem *taskItem = qobject_cast<TaskItem*>(q->sender());
00293     TaskItem *item = itemList.take(itemList.key(taskItem));
00294     if (!item) {
00295         kDebug() << "invalid item";
00296         return;
00297     }
00298     QObject::disconnect(item, 0, q, 0);
00299 }
00300 
00301 
00302 bool GroupManager::manualGroupingRequest(AbstractGroupableItem* item, TaskGroup* groupItem)
00303 {
00304     //kDebug();
00305     if (d->abstractGroupingStrategy) {
00306         return d->abstractGroupingStrategy->addItemToGroup(item, groupItem);
00307     //    kDebug() << d->abstractGroupingStrategy->type() << ManualGrouping;
00308         /*if (d->abstractGroupingStrategy->type() == ManualGrouping) {
00309    //         kDebug();
00310             return (qobject_cast<ManualGroupingStrategy*>(d->abstractGroupingStrategy))->addItemToGroup(item,groupItem);
00311         }*/
00312     }
00313     return false;
00314 }
00315 
00316 bool GroupManager::manualGroupingRequest(ItemList items)
00317 {
00318     // kDebug();
00319     if (d->abstractGroupingStrategy) {
00320      //   kDebug() << d->abstractGroupingStrategy->type() << ManualGrouping;
00321         if (d->abstractGroupingStrategy->type() == ManualGrouping) {
00322       //      kDebug();
00323             return (qobject_cast<ManualGroupingStrategy*>(d->abstractGroupingStrategy))->groupItems(items);
00324         }
00325     }
00326     return false;
00327 }
00328 
00329 bool GroupManager::manualSortingRequest(AbstractGroupableItem* taskItem, int newIndex)
00330 {
00331     //kDebug();
00332     if (d->abstractSortingStrategy) {
00333         if (d->abstractSortingStrategy->type() == ManualSorting) {
00334             return (qobject_cast<ManualSortingStrategy*>(d->abstractSortingStrategy))->moveItem(taskItem, newIndex);
00335         }
00336     }
00337     return false;
00338 }
00339 
00340 
00341 GroupPtr GroupManager::rootGroup() const
00342 {
00343     return d->rootGroup;
00344 }
00345 
00346 
00347 void GroupManagerPrivate::currentDesktopChanged(int newDesktop)
00348 {
00349     //kDebug();
00350     if (!showOnlyCurrentDesktop) {
00351         return;
00352     }
00353 
00354     if (abstractSortingStrategy) {
00355         abstractSortingStrategy->desktopChanged(newDesktop);
00356     }
00357 
00358     if (abstractGroupingStrategy) {
00359         abstractGroupingStrategy->desktopChanged(newDesktop);
00360     }
00361 
00362     reloadTasks();
00363 }
00364 
00365 
00366 void GroupManagerPrivate::taskChanged(TaskPtr task, ::TaskManager::TaskChanges changes)
00367 {
00368     //kDebug();
00369     bool takeAction = false;
00370     bool show = true;
00371 
00372     if (showOnlyCurrentDesktop && changes & ::TaskManager::DesktopChanged) {
00373         takeAction = true;
00374         show = task->isOnCurrentDesktop();
00375         //kDebug() << task->visibleName() << "on" << TaskManager::self()->currentDesktop();
00376     }
00377 
00378     if (showOnlyMinimized && changes & ::TaskManager::StateChanged) {
00379         //TODO: wouldn't it be nice to get notification of JUST minimization?
00380         takeAction = true;
00381         show = task->isMinimized();
00382     }
00383 
00384     if (changes & ::TaskManager::GeometryChanged) {
00385         if (!geometryTasks.contains(task)) {
00386             geometryTasks.append(task);
00387         }
00388 
00389         if (!screenTimer.isActive()) {
00390             screenTimer.start();
00391         }
00392     }
00393 
00394     //show tasks anyway if they demand attention
00395     if (changes & ::TaskManager::StateChanged && task->demandsAttention()) {
00396         takeAction = true;
00397         show = true;
00398     }
00399 
00400     if (!takeAction) {
00401         return;
00402     }
00403 
00404     if (show) {
00405         //kDebug() << "add(task);";
00406         q->add(task);
00407     } else {
00408         //kDebug() << "remove(task);";
00409         q->remove(task);
00410     }
00411 }
00412 
00413 void GroupManager::setScreen(int screen)
00414 {
00415     //kDebug() << "new Screen: " << screen;
00416     d->currentScreen = screen;
00417 }
00418 
00419 
00420 void GroupManagerPrivate::checkScreenChange()
00421 {
00422     //kDebug();
00423     foreach (const TaskPtr &task, geometryTasks) {
00424         if (task->isOnScreen(currentScreen)) {
00425             q->add(task);
00426         } else {
00427             q->remove(task);
00428         }
00429     }
00430 
00431     geometryTasks.clear();
00432 }
00433 
00434 
00435 void GroupManager::reconnect()
00436 {
00437     //kDebug();
00438     disconnect(TaskManager::self(), SIGNAL(desktopChanged(int)),
00439                this, SLOT(currentDesktopChanged(int)));
00440     disconnect(TaskManager::self(), SIGNAL(windowChanged(TaskPtr,::TaskManager::TaskChanges)),
00441                this, SLOT(taskChanged(TaskPtr,::TaskManager::TaskChanges)));
00442 
00443     if (d->showOnlyCurrentDesktop || d->showOnlyMinimized || d->showOnlyCurrentScreen) {
00444         // listen to the relevant task manager signals
00445         if (d->showOnlyCurrentDesktop) {
00446             connect(TaskManager::TaskManager::self(), SIGNAL(desktopChanged(int)),
00447                     this, SLOT(currentDesktopChanged(int)));
00448         }
00449 
00450         connect(TaskManager::self(), SIGNAL(windowChanged(TaskPtr,::TaskManager::TaskChanges)),
00451                 this, SLOT(taskChanged(TaskPtr,::TaskManager::TaskChanges)));
00452     }
00453 
00454     TaskManager::TaskManager::self()->setTrackGeometry(d->showOnlyCurrentScreen, d->configToken);
00455 
00456     if (!d->showOnlyCurrentScreen) {
00457         d->geometryTasks.clear();
00458     }
00459 
00460     d->reloadTasks();
00461 }
00462 
00463 
00464 bool GroupManager::onlyGroupWhenFull() const
00465 {
00466     return d->onlyGroupWhenFull;
00467 }
00468 
00469 void GroupManager::setOnlyGroupWhenFull(bool state)
00470 {
00471     //kDebug() << state;
00472     if (d->onlyGroupWhenFull == state) {
00473         return;
00474     }
00475 
00476     d->onlyGroupWhenFull = state;
00477 
00478     if (state) {
00479         connect(d->rootGroup, SIGNAL(itemAdded(AbstractItemPtr)), this, SLOT(checkIfFull()));
00480         connect(d->rootGroup, SIGNAL(itemRemoved(AbstractItemPtr)), this, SLOT(checkIfFull()));
00481         d->checkIfFull();
00482     } else {
00483         disconnect(d->rootGroup, SIGNAL(itemAdded(AbstractItemPtr)), this, SLOT(checkIfFull()));
00484         disconnect(d->rootGroup, SIGNAL(itemRemoved(AbstractItemPtr)), this, SLOT(checkIfFull()));
00485     }
00486 }
00487 
00488 void GroupManager::setFullLimit(int limit)
00489 {
00490     //kDebug() << limit;
00491     d->groupIsFullLimit = limit;
00492     if (d->onlyGroupWhenFull) {
00493         d->checkIfFull();
00494     }
00495 }
00496 
00497 void GroupManagerPrivate::checkIfFull()
00498 {
00499     //kDebug();
00500     if (!onlyGroupWhenFull || groupingStrategy != GroupManager::ProgramGrouping) {
00501         return;
00502     }
00503 
00504     if (itemList.size() >= groupIsFullLimit) {
00505         if (!abstractGroupingStrategy) {
00506             q->setGroupingStrategy(GroupManager::ProgramGrouping);
00507         }
00508     } else if (abstractGroupingStrategy) {
00509         q->setGroupingStrategy(GroupManager::NoGrouping);
00510         //let the visualization thing we still use the programGrouping
00511         groupingStrategy = GroupManager::ProgramGrouping;
00512     }
00513 }
00514 
00515 bool GroupManager::showOnlyCurrentScreen() const
00516 {
00517     return d->showOnlyCurrentScreen;
00518 }
00519 
00520 void GroupManager::setShowOnlyCurrentScreen(bool showOnlyCurrentScreen)
00521 {
00522     d->showOnlyCurrentScreen = showOnlyCurrentScreen;
00523 }
00524 
00525 bool GroupManager::showOnlyCurrentDesktop() const
00526 {
00527     return d->showOnlyCurrentDesktop;
00528 }
00529 
00530 void GroupManager::setShowOnlyCurrentDesktop(bool showOnlyCurrentDesktop)
00531 {
00532     d->showOnlyCurrentDesktop = showOnlyCurrentDesktop;
00533 }
00534 
00535 bool GroupManager::showOnlyMinimized() const
00536 {
00537     return d->showOnlyMinimized;
00538 }
00539 
00540 void GroupManager::setShowOnlyMinimized(bool showOnlyMinimized)
00541 {
00542     d->showOnlyMinimized = showOnlyMinimized;
00543 }
00544 
00545 GroupManager::TaskSortingStrategy GroupManager::sortingStrategy() const
00546 {
00547     return d->sortingStrategy;
00548 }
00549 
00550 AbstractSortingStrategy* GroupManager::taskSorter() const
00551 {
00552     return d->abstractSortingStrategy;
00553 }
00554 
00555 void GroupManager::setSortingStrategy(TaskSortingStrategy sortOrder)
00556 {
00557     //kDebug() << sortOrder;
00558 
00559     if (d->abstractSortingStrategy) {
00560         if (d->abstractSortingStrategy->type() == sortOrder){
00561             return;
00562         } else {
00563             d->abstractSortingStrategy->deleteLater();
00564         }
00565     }
00566 
00567     switch (sortOrder) {
00568         case NoSorting: //manual and no grouping result both in non automatic grouping
00569             d->abstractSortingStrategy = 0;
00570             break;
00571         case ManualSorting:
00572             d->abstractSortingStrategy = new ManualSortingStrategy(this);
00573             d->abstractSortingStrategy->handleGroup(d->rootGroup);
00574             break;
00575 
00576         case AlphaSorting:
00577             d->abstractSortingStrategy = new AlphaSortingStrategy(this);
00578             d->abstractSortingStrategy->handleGroup(d->rootGroup);
00579             break;
00580 
00581         case DesktopSorting:
00582             d->abstractSortingStrategy = new DesktopSortingStrategy(this);
00583             d->abstractSortingStrategy->handleGroup(d->rootGroup);
00584             break;
00585 
00586         default:
00587             kDebug() << "Invalid Strategy";
00588             d->abstractSortingStrategy = 0;
00589     }
00590 
00591     d->sortingStrategy = sortOrder;
00592     d->reloadTasks();
00593 }
00594 
00595 GroupManager::TaskGroupingStrategy GroupManager::groupingStrategy() const
00596 {
00597     return d->groupingStrategy;
00598 }
00599 
00600 AbstractGroupingStrategy* GroupManager::taskGrouper() const
00601 {
00602     return d->abstractGroupingStrategy;
00603 }
00604 
00605 void GroupManager::setGroupingStrategy(TaskGroupingStrategy strategy)
00606 {
00607     if (d->changingGroupingStragegy ||
00608         (d->abstractGroupingStrategy && d->abstractGroupingStrategy->type() == strategy)) {
00609         return;
00610     }
00611 
00612     d->changingGroupingStragegy = true;
00613 
00614     //kDebug() << strategy << kBacktrace();
00615     if (d->onlyGroupWhenFull) {
00616         disconnect(d->rootGroup, SIGNAL(itemAdded(AbstractItemPtr)), this, SLOT(checkIfFull()));
00617         disconnect(d->rootGroup, SIGNAL(itemRemoved(AbstractItemPtr)), this, SLOT(checkIfFull()));
00618     }
00619 
00620     delete d->abstractGroupingStrategy;
00621     d->abstractGroupingStrategy = 0;
00622 
00623     switch (strategy) {
00624         case NoGrouping:
00625             d->abstractGroupingStrategy = 0;
00626             break;
00627         case ManualGrouping:
00628             d->abstractGroupingStrategy = new ManualGroupingStrategy(this);
00629             break;
00630 
00631         case ProgramGrouping:
00632             d->abstractGroupingStrategy = new ProgramGroupingStrategy(this);
00633             break;
00634 
00635         default:
00636             kDebug() << "Strategy not implemented";
00637             d->abstractGroupingStrategy = 0;
00638     }
00639 
00640     d->groupingStrategy = strategy;
00641 
00642     if (d->groupingStrategy) {
00643         connect(d->abstractGroupingStrategy, SIGNAL(groupRemoved(TaskGroup*)),
00644                 this, SIGNAL(groupRemoved(TaskGroup*)));
00645     }
00646 
00647     d->reloadTasks();
00648 
00649     if (d->onlyGroupWhenFull) {
00650         connect(d->rootGroup, SIGNAL(itemAdded(AbstractItemPtr)), this, SLOT(checkIfFull()));
00651         connect(d->rootGroup, SIGNAL(itemRemoved(AbstractItemPtr)), this, SLOT(checkIfFull()));
00652     }
00653 
00654     d->changingGroupingStragegy = false;
00655 }
00656 
00657 } // TaskManager namespace
00658 
00659 #include "groupmanager.moc"
00660 

libtaskmanager

Skip menu "libtaskmanager"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal