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

libtaskmanager

manualgroupingstrategy.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 "manualgroupingstrategy.h"
00025 
00026 #include <QAction>
00027 
00028 #include <KDebug>
00029 #include <KLocale>
00030 
00031 #include "abstractgroupingstrategy.h"
00032 #include "groupmanager.h"
00033 #include "taskmanager.h"
00034 
00035 
00036 namespace TaskManager
00037 {
00038 
00039 class ManualGroupingStrategy::Private
00040 {
00041 public:
00042     Private()
00043         : currentTemplate(0),
00044           editableGroupProperties(AbstractGroupingStrategy::All),
00045           tempItem(0),
00046           tempGroup(0),
00047           oldDesktop(TaskManager::self()->currentDesktop())
00048     {
00049     }
00050 
00051     GroupManager *groupManager;
00052     QHash<int, TaskGroupTemplate*> templateTrees;
00053     TaskGroupTemplate* currentTemplate;
00054     QList<TaskGroup*> protectedGroups;
00055     AbstractGroupingStrategy::EditableGroupProperties editableGroupProperties;
00056     AbstractGroupableItem *tempItem;
00057     TaskGroup *tempGroup;
00058     int oldDesktop;
00059 };
00060 
00061 
00062 
00063 ManualGroupingStrategy::ManualGroupingStrategy(GroupManager *groupManager)
00064     :AbstractGroupingStrategy(groupManager),
00065      d(new Private)
00066 {
00067     d->groupManager = groupManager;
00068     setType(GroupManager::ManualGrouping);
00069 }
00070 
00071 ManualGroupingStrategy::~ManualGroupingStrategy()
00072 {
00073     delete d;
00074 }
00075 
00076 AbstractGroupingStrategy::EditableGroupProperties ManualGroupingStrategy::editableGroupProperties()
00077 {
00078     return d->editableGroupProperties;
00079 }
00080 
00081 QList<QAction*> ManualGroupingStrategy::strategyActions(QObject *parent, AbstractGroupableItem *item)
00082 {
00083     QList<QAction*> actionList;
00084 
00085     if (item->isGrouped()) {
00086         QAction *a = new QAction(i18n("Leave Group"), parent);
00087         connect(a, SIGNAL(triggered()), this, SLOT(leaveGroup()));
00088         actionList.append(a);
00089         d->tempItem = item;
00090     }
00091 
00092     if (item->isGroupItem()) {
00093         QAction *a = new QAction(i18n("Remove Group"), parent);
00094         connect(a, SIGNAL(triggered()), this, SLOT(removeGroup()));
00095         actionList.append(a);
00096         d->tempGroup = dynamic_cast<TaskGroup*>(item);
00097     }
00098 
00099     return actionList;
00100 }
00101 
00102 void ManualGroupingStrategy::leaveGroup()
00103 {
00104     Q_ASSERT(d->tempItem);
00105     if (d->tempItem->isGrouped()) {
00106         d->tempItem->parentGroup()->parentGroup()->add(d->tempItem);
00107     }
00108     d->tempItem = 0;
00109 }
00110 
00111 void ManualGroupingStrategy::removeGroup()
00112 {
00113     Q_ASSERT(d->tempGroup);
00114     if (d->tempGroup->parentGroup()) {
00115         foreach (AbstractGroupableItem *item, d->tempGroup->members()) {
00116             d->tempGroup->parentGroup()->add(item);
00117         }
00118         //Group gets automatically closed on empty signal
00119     }
00120     d->tempGroup = 0;
00121 }
00122 
00123 void ManualGroupingStrategy::unprotectGroup(TaskGroup *group)
00124 {
00125     //kDebug() << group->name() << d->protectedGroups.count(group);
00126     d->protectedGroups.removeOne(group);
00127     if (group->members().isEmpty()) {
00128         closeGroup(group);//check if group is needed anymore
00129     }
00130 }
00131 
00132 void ManualGroupingStrategy::protectGroup(TaskGroup *group)
00133 {
00134     //kDebug() << group->name();
00135     d->protectedGroups.append(group);
00136 }
00137 
00138 //Check if the item was previously manually grouped
00139 void ManualGroupingStrategy::handleItem(AbstractItemPtr item)
00140 {
00141     //kDebug();
00142     if (d->currentTemplate) { //TODO this won't work over sessions because the task is identified by the pointer (maybe the name without the current status would work), one way would be to store the items per name if the session is closed and load them per name on startup but use the pointer otherwise because of changing names of browsers etc
00143         TaskGroupTemplate *templateGroup = d->currentTemplate;
00144         //kDebug() << templateGroup->name();
00145         if (templateGroup->hasMember(item)) { 
00146             //kDebug() << "item found in template tree";
00147             while(!templateGroup->hasDirectMember(item)) {//Create tree of groups if not already existing
00148                 //kDebug() << "Creating group tree";
00149                 TaskGroupTemplate *oldTemplateGroup = templateGroup;
00150                 AbstractGroupableItem *templateItem = templateGroup->directMember(item);
00151                 if (templateItem->isGroupItem()) {
00152                     templateGroup = dynamic_cast<TaskGroupTemplate*>(templateItem);
00153                 } else {
00154                     //kDebug() << "Error no template Found";
00155                 }
00156                 if (templateGroup->group()) {
00157                     oldTemplateGroup->group()->add(templateGroup->group()); //add group to parent Group
00158                 } else {
00159                     //kDebug();
00160                     d->groupManager->rootGroup()->add(item);
00161                     return;
00162                 }
00163             }
00164 
00165             //kDebug() << "Item added to group: " << templateGroup->name();
00166             templateGroup->group()->add(item);
00167             templateGroup->remove(item);
00168         } else {
00169             //kDebug() << "Item not in templates";
00170             d->groupManager->rootGroup()->add(item);
00171         }
00172     } else {
00173         d->groupManager->rootGroup()->add(item);
00174     }
00175 }
00176 
00177 TaskGroupTemplate *ManualGroupingStrategy::createDuplication(TaskGroup *group)
00178 {
00179     TaskGroupTemplate *templateGroup = new TaskGroupTemplate(this, group);
00180     return templateGroup;
00181 }
00182 
00183 
00184 void ManualGroupingStrategy::desktopChanged(int newDesktop)
00185 {
00186     //kDebug() << "old: " << d->oldDesktop << "new: " << newDesktop;
00187     if (d->oldDesktop == newDesktop) {
00188         return;
00189     }
00190 
00191     //Store the group under the current Desktop
00192     if (d->currentTemplate) {
00193         d->currentTemplate->clear();
00194     }
00195     //kDebug();
00196     TaskGroupTemplate *group = createDuplication(d->groupManager->rootGroup());
00197     d->templateTrees.insert(d->oldDesktop, group); 
00198     if (d->templateTrees.contains(newDesktop)) {
00199         //kDebug() << "Template found";
00200         d->currentTemplate = d->templateTrees.value(newDesktop);
00201         connect (d->currentTemplate, SIGNAL(destroyed()), this, SLOT(resetCurrentTemplate()));
00202     } else {
00203         d->currentTemplate = 0;
00204     }
00205     d->oldDesktop = newDesktop;
00206 }
00207 
00208 
00209 //This function makes sure that if the rootGroup template already got deleted nobody tries to access it again
00210 void ManualGroupingStrategy::resetCurrentTemplate()
00211 {
00212     //kDebug();
00213     d->currentTemplate = 0;
00214 }
00215 
00216 //The group was moved to another desktop, we have to move it to the rootTree of newDesk
00217 void ManualGroupingStrategy::groupChangedDesktop(int newDesktop)
00218 {
00219     //kDebug();
00220     TaskGroup *group = qobject_cast<TaskGroup*>(sender());
00221     if (!group) {
00222         return;
00223     }
00224     if (newDesktop && (newDesktop != d->oldDesktop)) {
00225         if (group->parentGroup()) {
00226             group->parentGroup()->remove(group);
00227         }
00228     }
00229     TaskGroupTemplate *templateGroup;
00230 if (newDesktop) {
00231     if (d->templateTrees.contains(newDesktop)) {
00232         //kDebug() << "Template found";
00233         templateGroup = d->templateTrees.value(newDesktop);
00234     } else {
00235         //kDebug() << "No Template found";
00236         templateGroup = new TaskGroupTemplate(this, 0);
00237         templateGroup->setGroup(d->groupManager->rootGroup());
00238         d->templateTrees.insert(newDesktop, templateGroup);
00239     }
00240     //Add group to all existing desktops
00241 } else {
00242     for (int i = 1; i <= TaskManager::self()->numberOfDesktops(); i++) {
00243         if (d->templateTrees.contains(newDesktop)) {
00244             //kDebug() << "Template found";
00245             templateGroup = d->templateTrees.value(newDesktop);
00246             if (templateGroup->hasMember(group)) {
00247                 continue;
00248             }
00249         } else {
00250             //kDebug() << "No Template found";
00251             templateGroup = new TaskGroupTemplate(this, 0);
00252             templateGroup->setGroup(d->groupManager->rootGroup());
00253             d->templateTrees.insert(newDesktop, templateGroup);
00254         }
00255         templateGroup->add(createDuplication(group));
00256     }
00257 }
00258 
00259 }
00260 
00261 bool ManualGroupingStrategy::groupItems(ItemList items)
00262 {
00263     //kDebug();
00264     TaskGroup *group = createGroup(items);
00265     connect(group, SIGNAL(movedToDesktop(int)), this, SLOT(groupChangedDesktop(int)));
00266     setName(nameSuggestions(group).first(), group);
00267     setColor(colorSuggestions(group).first(), group);
00268     setIcon(iconSuggestions(group).first(), group);
00269     return true;
00270 }
00271 
00272 void ManualGroupingStrategy::closeGroup(TaskGroup *group)
00273 {
00274     //kDebug();
00275     if (!d->protectedGroups.contains(group)) {
00276         AbstractGroupingStrategy::closeGroup(group);
00277     } else if (group->parentGroup()) {
00278         group->parentGroup()->remove(group);
00279         //kDebug() << "Group protected";
00280     }
00281 }
00282 
00283 class TaskGroupTemplate::Private
00284 {
00285 public:
00286     Private()
00287     : group(0),
00288       parentGroup(0),
00289       groupingStrategy(0)
00290     {
00291     }
00292 
00293     ItemList members;
00294     QString name;
00295     QColor color;
00296     QIcon icon;
00297     TaskGroup *group;
00298     TaskGroupTemplate *parentGroup;
00299     ManualGroupingStrategy *groupingStrategy;
00300 };
00301 
00302 
00303 TaskGroupTemplate::TaskGroupTemplate(ManualGroupingStrategy *parent, TaskGroup *group)
00304 :   AbstractGroupableItem(parent),
00305     d(new Private)
00306 {
00307     connect(this, SIGNAL(unprotectGroup(TaskGroup *)), parent, SLOT(unprotectGroup(TaskGroup *)));
00308     connect(this, SIGNAL(protectGroup(TaskGroup *)), parent, SLOT(protectGroup(TaskGroup *)));
00309     if (group) {
00310         d->name = group->name();
00311         d->color = group->color();
00312         d->icon = group->icon();
00313         setGroup(group);
00314         foreach (AbstractGroupableItem *item, group->members()) {
00315             //We don't use TaskGroup::add because this would inform the tasks about the change of the group
00316             //and we use the taskgroup just as a temporary container
00317             if (item->isGroupItem()) {
00318                 //kDebug() << "GroupItem Duplication";
00319                 TaskGroupTemplate *createdDuplication = new TaskGroupTemplate(parent, dynamic_cast<TaskGroup*>(item));
00320                 add(createdDuplication);
00321             } else {
00322                 add(item);
00323             }
00324         }
00325     }
00326     //kDebug() << "TemplateGroup Created: Name: " << d->name << "Color: " << d->color;
00327 }
00328 
00329 TaskGroupTemplate::~TaskGroupTemplate()
00330 {
00331     emit unprotectGroup(group());
00332     emit destroyed(this);
00333     //clear();
00334     //kDebug() << name();
00335     delete d;
00336 }
00337 
00338 TaskGroup *TaskGroupTemplate::group()
00339 {
00340     return d->group;
00341 }
00342 
00343 void TaskGroupTemplate::setGroup(TaskGroup *group)
00344 {
00345     if (d->group) {
00346         emit unprotectGroup(group);
00347     }
00348     if (group) {
00349         emit protectGroup(group);
00350     }
00351     d->group = group;
00352 }
00353 
00354 ItemList &TaskGroupTemplate::members() const
00355 {
00356     return d->members;
00357 }
00358 
00359 QIcon TaskGroupTemplate::icon() const
00360 {
00361     return d->icon;
00362 }
00363 
00364 QColor TaskGroupTemplate::color() const
00365 {
00366     return d->color;
00367 }
00368 
00369 QString TaskGroupTemplate::name() const
00370 {
00371     return d->name;
00372 }
00373 
00375 void TaskGroupTemplate::add(AbstractItemPtr item)
00376 {
00377     if (d->members.contains(item)) {
00378         return;
00379     }
00380     d->members.append(item);
00381     if (item->isGroupItem()) { 
00382         connect(item, SIGNAL(destroyed(AbstractGroupableItem *)), this, SLOT(itemDestroyed(AbstractGroupableItem *)));
00383         (dynamic_cast<TaskGroupTemplate*>(item))->setParentGroup(this);
00384     }
00385 }
00386 
00388 void TaskGroupTemplate::remove(AbstractItemPtr item)
00389 {
00390     disconnect(item, 0, this, 0);
00391     disconnect(this, 0, item, 0);
00392     d->members.removeAll(item);
00393     if (item->isGroupItem()) { 
00394         (dynamic_cast<TaskGroupTemplate*>(item))->setParentGroup(0);
00395     }
00396     if (d->members.isEmpty()) {
00397         closeGroup();
00398     }
00399 }
00400 
00402 void TaskGroupTemplate::clear()
00403 {
00404     foreach(AbstractGroupableItem *item, d->members) {
00405         Q_ASSERT(item);
00406         if (item->isGroupItem()) { 
00407             TaskGroupTemplate* templateGroup = qobject_cast<TaskGroupTemplate*>(item);
00408             Q_ASSERT(templateGroup);
00409             templateGroup->clear();
00410         } else {
00411             remove(item);
00412         }
00413     }
00414 }
00416 void TaskGroupTemplate::closeGroup()
00417 {
00418     if (parentGroup()) {
00419         foreach(AbstractGroupableItem *item, d->members) {
00420             Q_ASSERT(item);
00421             remove(item);
00422             parentGroup()->add(item);
00423         }
00424     } else {
00425         foreach(AbstractGroupableItem *item, d->members) {
00426             Q_ASSERT(item);
00427             remove(item);
00428         }
00429     }
00430     deleteLater();
00431 }
00432 
00433 
00434 TaskGroupTemplate *TaskGroupTemplate::parentGroup() const
00435 {
00436     return d->parentGroup;
00437 }
00438 
00439 void TaskGroupTemplate::setParentGroup(TaskGroupTemplate *group)
00440 {
00441     d->parentGroup = group;
00442 }
00443 
00444 void TaskGroupTemplate::addMimeData(QMimeData *mimeData) const
00445 {
00446     if (d->group) {
00447         d->group->addMimeData(mimeData);
00448     }
00449 }
00450 
00452 bool TaskGroupTemplate::hasDirectMember(AbstractItemPtr item) const
00453 {
00454     return d->members.contains(item);
00455 }
00456 
00458 bool TaskGroupTemplate::hasMember(AbstractItemPtr item) const
00459 {
00460     //kDebug();
00461     if (members().contains(item)) {
00462         return true;
00463     }
00464     ItemList::const_iterator iterator = members().constBegin();
00465     while (iterator != members().constEnd()) {
00466         if ((*iterator)->isGroupItem()) {
00467             if ((dynamic_cast<TaskGroupTemplate *>(*iterator))->hasMember(item)) { //look into group
00468                 return true;
00469             }
00470         }
00471         ++iterator;
00472     }
00473     return false;
00474 
00475 }
00476 
00478 AbstractItemPtr TaskGroupTemplate::directMember(AbstractItemPtr item) const
00479 {
00480     if (members().contains(item)) {
00481         return item;
00482     } else {
00483         ItemList::const_iterator iterator = members().constBegin();
00484         while (iterator != members().constEnd()) {
00485             if ((*iterator)->isGroupItem()) {
00486                 if ((dynamic_cast<TaskGroupTemplate*>(*iterator))->hasMember(item)) {
00487                     //kDebug() << "item found";
00488                     return (*iterator);
00489                 }
00490             } 
00491             ++iterator;
00492         }
00493     }
00494     kDebug() << "item not found";
00495     return AbstractItemPtr();
00496 }
00497 
00498 TaskGroupTemplate *TaskGroupTemplate::findParentGroup(AbstractItemPtr item) const
00499 {
00500     if (members().contains(item)) {
00501         return const_cast<TaskGroupTemplate*>(this);
00502     } else {
00503         ItemList::const_iterator iterator = members().constBegin();
00504         while (iterator != members().constEnd()) {
00505             if ((*iterator)->isGroupItem()) {
00506                 TaskGroupTemplate *returnedGroup = (dynamic_cast<TaskGroupTemplate*>(*iterator))->findParentGroup(item);
00507                 if (returnedGroup) {
00508                     //kDebug() << "item found";
00509                     return returnedGroup;
00510                 }
00511             }
00512             ++iterator;
00513         }
00514     }
00515     kDebug() << "item not found";
00516     return 0;
00517 }
00518 
00519 void TaskGroupTemplate::itemDestroyed(AbstractGroupableItem *item)
00520 {
00521     if (!item) {
00522         kDebug() << "Error";
00523         return;
00524     }
00525     //kDebug() << d->group->name(); 
00529     d->members.removeAll(item); // we can't use remove because the item was already deleted
00530     disconnect(item, 0, this, 0);
00531     disconnect(this, 0, item, 0);
00532     if (members().isEmpty()) {
00533         closeGroup();
00534     }
00535 }
00536 
00537 }//namespace
00538 
00539 #include "manualgroupingstrategy.moc"
00540 

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