add more spacing
[personal-kdebase.git] / workspace / plasma / applets / tasks / taskgroupitem.cpp
blob2100aa7ed670639f0ae90c609180fcfa6e3defcf
1 /***************************************************************************
2 * Copyright (C) 2007 by Robert Knight <robertknight@gmail.com> *
3 * Copyright (C) 2008 by Alexis Ménard <darktears31@gmail.com> *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
19 ***************************************************************************/
21 // Own
22 #include "taskgroupitem.h"
23 #include "layoutwidget.h"
24 #include "windowtaskitem.h"
25 #include "tasksmenu.h"
27 // Qt
28 #include <QGraphicsSceneContextMenuEvent>
29 #include <QStyleOptionGraphicsItem>
30 #include <QGraphicsView>
31 #include <QTimer>
32 #include <QApplication>
33 #include <QGraphicsLinearLayout>
34 #include <QInputDialog>
36 // KDE
37 #include <KAuthorized>
38 #include <KDebug>
39 #include <KIcon>
40 #include <KLocalizedString>
41 #include <KGlobalSettings>
42 #include <KIconLoader>
44 #include <taskmanager/taskactions.h>
45 #include <taskmanager/taskmanager.h>
46 #include <taskmanager/taskgroup.h>
47 #include <taskmanager/abstractgroupingstrategy.h>
49 #include <Plasma/Theme>
50 #include <Plasma/FrameSvg>
51 #include <Plasma/ToolTipManager>
52 #include <Plasma/Corona>
53 #include <Plasma/Containment>
55 #include "tasks.h"
56 #include "layoutwidget.h"
58 TaskGroupItem::TaskGroupItem(QGraphicsWidget *parent, Tasks *applet, const bool showTooltip)
59 : AbstractTaskItem(parent, applet, showTooltip),
60 m_group(0),
61 m_expandedLayout(0),
62 m_popupMenuTimer(0),
63 m_lastActivated(-1),
64 m_activeTaskIndex(0),
65 m_maximumRows(1),
66 m_forceRows(false),
67 m_splitPosition(0),
68 m_parentSplitGroup(0),
69 m_childSplitGroup(0)
71 setAcceptDrops(true);
75 bool TaskGroupItem::isSplit()
77 return m_childSplitGroup != 0;
80 void TaskGroupItem::setSplitGroup(TaskGroup *group)
82 m_group = group;
83 m_parentSplitGroup = dynamic_cast<TaskGroupItem*>(parentWidget());
84 if (!m_parentSplitGroup) {
85 kDebug() << "no parentSplit Group";
86 return;
88 expand();
91 //FIXME verify if this really works correctly
92 void TaskGroupItem::unsplitGroup()
94 //kDebug();
95 if (!m_childSplitGroup) {
96 return;
98 m_childSplitGroup->deleteLater();
99 m_childSplitGroup = 0;
100 m_splitPosition = 0;
101 reload();
105 TaskGroupItem * TaskGroupItem::splitGroup()
107 return m_childSplitGroup;
110 void TaskGroupItem::setSplitIndex(int position)
112 //kDebug() << position;
113 Q_ASSERT(m_expandedLayout);
114 Q_ASSERT(m_parentSplitGroup);
116 for (int i = position ; i < m_parentSplitGroup->group()->members().size() ; i++) {
117 //kDebug() << "add item to childSplitGroup" << i;
118 AbstractGroupableItem *item = m_parentSplitGroup->group()->members().at(i);
119 if (!m_groupMembers.contains(item)) {
120 m_groupMembers.insert(item, m_parentSplitGroup->abstractItem(item));
122 m_expandedLayout->addTaskItem(abstractItem(item));
124 m_splitPosition = position;
127 TaskGroupItem * TaskGroupItem::splitGroup(int newSplitPosition)
129 //kDebug() << "split position" << newSplitPosition;
130 Q_ASSERT(m_expandedLayout);
132 //remove all items which move to the splitgroup from the expandedLayout
133 for (int i = newSplitPosition ; i < m_groupMembers.size() ; i++) {
134 AbstractGroupableItem *item = group()->members().at(i);
135 m_expandedLayout->removeTaskItem(abstractItem(item));
136 //kDebug() << "remove from parentSplitGroup" << i;
138 //add items which arent in the splitgroup anymore and should be displayed again
139 if (m_splitPosition) { //if 0 is the init value and shouldn't happen otherwise
140 for (int i = m_splitPosition ; i < newSplitPosition ; i++) {
141 AbstractGroupableItem *item = group()->members().at(i);
142 m_expandedLayout->addTaskItem(abstractItem(item));
143 //kDebug() << "add Item to parentSplitGroup" << i;
147 if (!m_childSplitGroup) {
148 //kDebug() << "Normal scene " << scene();
149 m_childSplitGroup = new TaskGroupItem(this, m_applet, true);
150 m_childSplitGroup->setSplitGroup(m_group);
153 m_childSplitGroup->setSplitIndex(newSplitPosition);
154 m_splitPosition = newSplitPosition;
155 return m_childSplitGroup;
158 //scroll through items on every click
159 void TaskGroupItem::activate()
161 /*m_activeTaskIndex++;
162 if (m_activeTaskIndex >= m_groupMembers.size()) {
163 m_activeTaskIndex = 0;
166 // kDebug() << "Wheel event m_activeTaskIndex: " << m_activeTaskIndex << " of " << numberOfItems();
167 AbstractTaskItem *item = m_groupMembers.at(m_activeTaskIndex);
169 if (item) {
170 item->activate();
171 }//TODO: exclude group items? */
175 void TaskGroupItem::close()
177 // m_applet->removeGroupTask(m_group);
178 m_group = 0;
182 void TaskGroupItem::updateTask(::TaskManager::TaskChanges changes)
184 Q_ASSERT(m_group);
186 bool needsUpdate = false;
187 // task flags
188 TaskFlags flags = m_flags;
189 if (m_group->isActive()) {
190 flags |= TaskHasFocus;
191 emit activated(this);
192 } else {
193 flags &= ~TaskHasFocus;
196 if (m_group->demandsAttention()) {
197 flags |= TaskWantsAttention;
198 } else {
199 flags &= ~TaskWantsAttention;
202 if (m_group->isMinimized()) {
203 flags |= TaskIsMinimized;
204 } else {
205 flags &= ~TaskIsMinimized;
208 if (flags != m_flags) {
209 needsUpdate = true;
210 setTaskFlags(flags);
213 // basic title and icon
214 if (changes & TaskManager::IconChanged) {
215 needsUpdate = true;
216 setIcon(m_group->icon());
219 if (changes & TaskManager::NameChanged) {
220 needsUpdate = true;
221 setText(m_group->name());
224 if (m_showingTooltip &&
225 (changes & TaskManager::IconChanged ||
226 changes & TaskManager::NameChanged ||
227 changes & TaskManager::DesktopChanged)) {
228 updateToolTip();
231 if (needsUpdate) {
232 //redraw
233 queueUpdate();
237 void TaskGroupItem::updateToolTip()
239 if (!m_group) {
240 return;
243 Plasma::ToolTipContent data(m_group->name(),
244 i18nc("Which virtual desktop a window is currently on", "On %1",
245 KWindowSystem::desktopName(m_group->desktop())));
246 // data.image = m_group->icon().pixmap(QSize::small);
247 // data.windowToPreview = m_task->window();
249 Plasma::ToolTipManager::self()->setContent(this, data);
253 void TaskGroupItem::reload()
255 kDebug();
256 QList <AbstractItemPtr> itemsToRemove = m_groupMembers.keys();
258 foreach (AbstractItemPtr item, group()->members()) {
259 if (!item) {
260 kDebug() << "invalid Item";
261 continue;
263 itemsToRemove.removeAll(item);
264 itemAdded(item);
266 if (item->isGroupItem()) {
267 TaskGroupItem *group = qobject_cast<TaskGroupItem *>(abstractItem(item));
268 if (group) {
269 group->reload();
273 foreach (AbstractItemPtr item, itemsToRemove) { //remove unused items
274 if (!item) {
275 kDebug() << "invalid Item";
276 continue;
278 itemRemoved(item);
282 void TaskGroupItem::setGroup(TaskManager::GroupPtr group)
284 //kDebug();
285 m_group = group;
286 m_abstractItem = qobject_cast<AbstractItemPtr>(group);
287 if (!m_abstractItem) {
288 kDebug() << "error";
291 connect(m_group, SIGNAL(itemRemoved(AbstractItemPtr)), this, SLOT(itemRemoved(AbstractItemPtr)));
292 connect(m_group, SIGNAL(itemAdded(AbstractItemPtr)), this, SLOT(itemAdded(AbstractItemPtr)));
294 //connect(m_group, SIGNAL(destroyed()), this, SLOT(close()));
296 connect(m_group, SIGNAL(changed(::TaskManager::TaskChanges)),
297 this, SLOT(updateTask(::TaskManager::TaskChanges)));
299 connect(m_group, SIGNAL(itemPositionChanged(AbstractItemPtr)), this, SLOT(itemPositionChanged(AbstractItemPtr)));
300 connect(m_group, SIGNAL(groupEditRequest()), this, SLOT(editGroup()));
302 //Add already existing items
303 reload();
304 updateTask(::TaskManager::EverythingChanged);
306 //kDebug() << "Task added, isActive = " << task->isActive();
309 TaskManager::GroupPtr TaskGroupItem::group() const
311 return m_group;
314 void TaskGroupItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *e)
316 //kDebug();
317 if (!KAuthorized::authorizeKAction("kwin_rmb") || !m_group) {
318 QGraphicsWidget::contextMenuEvent(e);
319 return;
321 Q_ASSERT(m_applet);
322 //we are the master group item
323 if (m_applet == parentWidget()) {
324 e->ignore();
325 return;
328 QAction *a;
330 if (m_expandedLayout) {
331 a = new QAction(i18n("Collapse Group"), this);
332 connect(a, SIGNAL(triggered()), this, SLOT(collapse()));
333 } else {
334 a = new QAction(i18n("Expand Group"), this);
335 connect(a, SIGNAL(triggered()), this, SLOT(expand()));
338 QList <QAction*> actionList;
339 actionList.append(a);
341 TaskManager::BasicMenu menu(qobject_cast<QWidget*>(this), m_group, &m_applet->groupManager(), actionList);
342 menu.adjustSize();
344 Q_ASSERT(m_applet->containment());
345 Q_ASSERT(m_applet->containment()->corona());
346 menu.exec(m_applet->containment()->corona()->popupPosition(this, menu.size()));
349 QList<AbstractTaskItem*> TaskGroupItem::memberList() const
351 return m_groupMembers.values();
354 AbstractTaskItem *TaskGroupItem::createAbstractItem(TaskManager::AbstractItemPtr groupableItem)
356 //kDebug() << "item to create" << groupableItem << endl;
357 AbstractTaskItem *item = 0;
359 if (m_groupMembers.contains(groupableItem)) {
360 //kDebug() << "existing item found";
361 return m_groupMembers.value(groupableItem);
364 if (groupableItem->isGroupItem()) {
365 TaskGroupItem *groupItem = new TaskGroupItem(this, m_applet, m_applet->showTooltip());
366 groupItem->setGroup(static_cast<TaskManager::TaskGroup*>(groupableItem));
367 item = groupItem;
368 } else { //it's a window task
369 WindowTaskItem *windowItem = new WindowTaskItem(this, m_applet, m_applet->showTooltip());
370 windowItem->setTask(static_cast<TaskManager::TaskItem*>(groupableItem));
371 item = windowItem;
374 if (!item) {
375 kDebug() << "invalid Item";
376 return 0;
379 return item;
384 void TaskGroupItem::itemAdded(TaskManager::AbstractItemPtr groupableItem)
386 //kDebug();
387 if (!m_applet) {
388 kDebug() << "No applet";
389 return;
392 //returns the corresponding item or creates a new one
393 AbstractTaskItem *item = createAbstractItem(groupableItem);
395 if (!item) {
396 kDebug() << "invalid Item";
397 return;
400 m_groupMembers[groupableItem] = item;
401 item->setParentItem(this);
403 if (collapsed()) {
404 item->hide();
405 QRect rect = iconGeometry();
406 item->publishIconGeometry(rect);
407 } else if (isSplit()) {
408 splitGroup(m_splitPosition);
409 //emit changed();
410 //m_childSplitGroup->reload();
411 } else {
412 m_expandedLayout->addTaskItem(item);
415 if (item->isActive()) {
416 //kDebug() << "item is Active" ;
417 m_activeTaskIndex = indexOf(item);
418 } else if (m_group->members().size() == 1) {
419 m_activeTaskIndex = 0;
422 connect(item, SIGNAL(activated(AbstractTaskItem*)),
423 this, SLOT(updateActive(AbstractTaskItem*)));
427 void TaskGroupItem::itemRemoved(TaskManager::AbstractItemPtr groupableItem)
429 //kDebug();
430 if (!m_applet) {
431 kDebug() << "No Applet";
432 return;
434 AbstractTaskItem *item = m_groupMembers.take(groupableItem);;
436 if (!item) {
437 kDebug() << "Item not found";
438 return;
441 disconnect(item, 0, 0, 0);
443 if (m_expandedLayout) {
444 m_expandedLayout->removeTaskItem(item);
447 item->close();
448 item->deleteLater();
452 bool TaskGroupItem::isWindowItem() const
454 return false;
457 bool TaskGroupItem::isActive() const
459 kDebug() << "Not Implemented";
460 return false;
463 void TaskGroupItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
464 { //TODO add delay so we can still drag group items
465 if (event->buttons() & Qt::LeftButton) {
466 if (m_applet->groupManager().sortingStrategy() == TaskManager::GroupManager::ManualSorting ||
467 m_applet->groupManager().groupingStrategy() == TaskManager::GroupManager::ManualGrouping) {
468 if (!m_popupMenuTimer) {
469 m_popupMenuTimer = new QTimer(this);
470 m_popupMenuTimer->setSingleShot(true);
471 m_popupMenuTimer->setInterval(300);
472 connect(m_popupMenuTimer, SIGNAL(timeout()), this, SLOT(popupMenu()));
474 m_popupMenuTimer->start(300);
475 } else {
476 popupMenu();
480 event->accept();
483 void TaskGroupItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
485 if (event->button() == Qt::MidButton) {
486 expand();
489 if (m_popupMenuTimer) {
490 if (m_popupMenuTimer->isActive()) {
491 // clicked, released, didn't move -> show the popup!
492 popupMenu();
494 m_popupMenuTimer->stop();
497 AbstractTaskItem::mouseReleaseEvent(event);
500 void TaskGroupItem::popupMenu()
502 if (!m_expandedLayout) {
503 TaskManager::TasksMenu menu(qobject_cast<QWidget*>(this), m_group, &m_applet->groupManager(), m_applet);
504 menu.adjustSize();
505 Q_ASSERT(m_applet->containment());
506 Q_ASSERT(m_applet->containment()->corona());
507 menu.exec(m_applet->containment()->corona()->popupPosition(this, menu.size()));
511 void TaskGroupItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
513 if (QPoint(event->screenPos() - event->buttonDownScreenPos(Qt::LeftButton)).manhattanLength() < QApplication::startDragDistance()) {
514 return;
515 } //Wait a bit before starting drag
517 //kDebug();
518 if (m_popupMenuTimer) {
519 m_popupMenuTimer->stop();
520 } //Wait a bit before starting drag
521 AbstractTaskItem::mouseMoveEvent(event);
524 void TaskGroupItem::expand()
526 if (m_expandedLayout) {
527 //kDebug() << "already expanded";
528 return;
531 //kDebug();
532 m_expandedLayout = new LayoutWidget(this, m_applet);
533 m_expandedLayout->setMaximumRows(m_maximumRows);
534 m_expandedLayout->setForceRows(m_forceRows);
536 //setLayout(m_expandedLayout);
538 connect(m_applet, SIGNAL(constraintsChanged(Plasma::Constraints)), m_expandedLayout, SLOT(constraintsChanged(Plasma::Constraints)));
539 connect(m_expandedLayout, SIGNAL(sizeHintChanged(Qt::SizeHint)), this, SLOT(updatePreferredSize()));
540 updatePreferredSize();
541 emit changed();
542 checkSettings();
543 //kDebug() << "expanded";
547 LayoutWidget *TaskGroupItem::layoutWidget()
549 return m_expandedLayout;
552 void TaskGroupItem::collapse()
554 //kDebug() << (int)this;
555 if (!m_expandedLayout) {
556 //kDebug() << "already collapsed";
557 return;
560 if (m_parentSplitGroup) {
561 m_parentSplitGroup->collapse();
564 //kDebug();
565 unsplitGroup();
566 foreach (AbstractTaskItem *member, m_groupMembers) {
567 m_expandedLayout->removeTaskItem(member);
569 setLayout(0);
570 //kDebug();
571 //delete m_expandedLayout;
572 m_expandedLayout = 0;
573 updatePreferredSize();
574 //kDebug();
575 emit changed();
576 checkSettings();
579 bool TaskGroupItem::collapsed() const
581 return m_expandedLayout == 0;
584 void TaskGroupItem::updatePreferredSize()
586 if (layout()) {
587 setPreferredSize(layout()->preferredSize());
588 layout()->invalidate();
589 //kDebug() << "expanded group" << layout()->preferredSize();
590 } else {
591 //FIXME: copypaste from abstracttaskitem: to be done better with proper sizeHint()
592 setPreferredSize(basicPreferredSize());
594 //kDebug() << preferredSize();
595 emit sizeHintChanged(Qt::PreferredSize);
600 AbstractTaskItem *TaskGroupItem::directMember(AbstractTaskItem *item)
602 Q_ASSERT(item);
603 Q_ASSERT(m_group);
604 TaskManager::AbstractItemPtr directMember = m_group->directMember(item->abstractItem());
605 if (!directMember) {
606 kDebug() << "Error" << item->abstractItem();
608 return abstractItem(directMember);
611 void TaskGroupItem::paint(QPainter *painter,
612 const QStyleOptionGraphicsItem *option,
613 QWidget *widget)
615 if (!m_expandedLayout) {
616 AbstractTaskItem::paint(painter,option,widget);
617 }/* else {
618 if (m_group) {
619 //painter->fillRect(geometry(), m_group->color());
623 //kDebug() << "painter()";
624 //painter->setBrush(QBrush(background));
628 // TODO provide a way to edit all group properties
629 void TaskGroupItem::editGroup()
631 //it could look like the popup of the device notifier or the calendar of the clock..
632 //kDebug();
633 Q_ASSERT(m_group);
634 Q_ASSERT(m_applet);
635 if (m_applet->groupManager().taskGrouper()->editableGroupProperties() & TaskManager::AbstractGroupingStrategy::Name) {
636 bool ok;
637 QString text = QInputDialog::getText(qobject_cast<QWidget*>(this), tr("Edit Group"),
638 tr("New Group Name: "), QLineEdit::Normal,
639 m_group->name(), &ok);
640 if (ok && !text.isEmpty()) {
641 m_group->setName(text);
647 void TaskGroupItem::itemPositionChanged(AbstractItemPtr item)
649 //kDebug();
650 if (!m_expandedLayout) {
651 return;
654 Q_ASSERT(item);
656 if (item->isGroupItem()) {
657 TaskGroupItem *groupItem = static_cast<TaskGroupItem*>(abstractItem(item));
658 if (groupItem) {
659 groupItem->unsplitGroup();
663 AbstractTaskItem *taskItem = abstractItem(item);
665 m_expandedLayout->removeTaskItem(taskItem);
666 m_expandedLayout->insert(m_group->members().indexOf(item), taskItem);
670 void TaskGroupItem::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
672 //kDebug()<<"Drag enter";
673 if (!m_expandedLayout &&
674 (event->mimeData()->hasFormat(TaskManager::Task::mimetype()) ||
675 event->mimeData()->hasFormat(TaskManager::Task::groupMimetype()))) {
676 event->acceptProposedAction();
677 //kDebug()<<"Drag enter accepted";
678 } else {
679 event->accept();
680 if (!m_popupMenuTimer) {
681 m_popupMenuTimer = new QTimer(this);
682 m_popupMenuTimer->setSingleShot(true);
683 m_popupMenuTimer->setInterval(300);
684 connect(m_popupMenuTimer, SIGNAL(timeout()), this, SLOT(popupMenu()));
686 m_popupMenuTimer->start(300);
690 AbstractTaskItem *TaskGroupItem::taskItemForWId(WId id)
692 QHashIterator<AbstractItemPtr, AbstractTaskItem*> it(m_groupMembers);
694 while (it.hasNext()) {
695 it.next();
696 AbstractTaskItem *item = it.value();
697 TaskGroupItem *group = qobject_cast<TaskGroupItem*>(item);
699 if (group) {
700 item = group->taskItemForWId(id);
701 if (item) {
702 return item;
704 } else {
705 TaskManager::TaskItem *task = qobject_cast<TaskManager::TaskItem*>(it.key());
706 if (task && task->task() && task->task()->window() == id) {
707 return item;
712 return 0;
715 void TaskGroupItem::dropEvent(QGraphicsSceneDragDropEvent *event)
717 //kDebug() << "LayoutWidget dropEvent";
718 if (event->mimeData()->hasFormat(TaskManager::Task::mimetype()) ||
719 event->mimeData()->hasFormat(TaskManager::Task::groupMimetype())) {
720 bool ok;
721 QList<WId> ids = TaskManager::Task::idsFromMimeData(event->mimeData(), &ok);
723 if (!ok) {
724 //kDebug() << "FAIL!";
725 event->ignore();
726 return;
729 AbstractTaskItem *targetTask = dynamic_cast<AbstractTaskItem *>(scene()->itemAt(mapToScene(event->pos())));
730 // kDebug() << "Pos: " << event->pos() << mapToScene(event->pos()) << "item" << scene()->itemAt(mapToScene(event->pos())) << "target Task " << dynamic_cast<QGraphicsItem *>(targetTask);
732 //kDebug() << "got" << ids.count() << "windows";
733 foreach (WId id, ids) {
734 handleDroppedId(id, targetTask, event);
737 //kDebug() << "LayoutWidget dropEvent done";
738 event->acceptProposedAction();
739 } else {
740 event->ignore();
744 void TaskGroupItem::handleDroppedId(WId id, AbstractTaskItem *targetTask, QGraphicsSceneDragDropEvent *event)
746 AbstractTaskItem *taskItem = m_applet->rootGroupItem()->taskItemForWId(id);
748 if (!taskItem) {
749 //kDebug() << "Invalid TaskItem";
750 return;
753 if (!taskItem->parentGroup()) {
754 //kDebug() << "group invalid";
755 return;
758 TaskManager::GroupPtr group = taskItem->parentGroup()->group();
760 //kDebug() << id << taskItem->text() << (QObject*)targetTask;
762 // kDebug() << "first item: " << dynamic_cast<QGraphicsItem*>(m_taskItems.first()) << "layout widget" << dynamic_cast<QGraphicsItem*>(this);
764 if ((event->modifiers() == m_applet->groupModifierKey()) &&
765 m_applet->groupManager().groupingStrategy() == TaskManager::GroupManager::ManualGrouping) {
766 //kDebug() << "groupModifiaction";
768 if (!targetTask) {
769 //add item to this group
770 m_applet->groupManager().manualGroupingRequest(taskItem->abstractItem(), m_group);
771 } else if (targetTask->isWindowItem() && (group == m_group)) { //Both Items in same group
772 //Group Items together
773 int targetIndex = m_group->members().indexOf(targetTask->abstractItem());
774 int sourceIndex = m_group->members().indexOf(taskItem->abstractItem());
775 TaskManager::ItemList members;
776 members.append(targetTask->abstractItem());
777 members.append(taskItem->abstractItem());
779 if (m_applet->groupManager().manualGroupingRequest(members)) {
780 if (sourceIndex < targetIndex) {
781 //fix because the taskItem is removed so the index of the group should be targetIndex - 1
782 targetIndex--;
785 //move group to appropriate index if possible
786 m_applet->groupManager().manualSortingRequest(taskItem->abstractItem()->parentGroup(), targetIndex);
787 //kDebug() << "Group Created";
788 } else {
789 //kDebug() << "Couldn't create Group";
791 } else if (!targetTask->isWindowItem()) {
792 //Drop on collapsed group item
793 //kDebug() << "Add item to Group";
794 m_applet->groupManager().manualGroupingRequest(taskItem->abstractItem(), dynamic_cast<TaskManager::GroupPtr>(targetTask->abstractItem()));
796 } else if (m_applet->groupManager().sortingStrategy() == TaskManager::GroupManager::ManualSorting) {
797 //Move action
798 if (group == m_group) { //same group
799 //kDebug() << "Drag within group";
800 layoutTaskItem(taskItem, event->pos());
801 } else { //task item was dragged outside of group -> group move
802 AbstractTaskItem *directMember = abstractItem(m_group->directMember(group));
803 if (directMember) {
804 layoutTaskItem(directMember, event->pos()); //we need to get the group right under the receiver group
810 void TaskGroupItem::layoutTaskItem(AbstractTaskItem* item, const QPointF &pos)
812 if (!m_expandedLayout) {
813 return;
816 int insertIndex = m_expandedLayout->insertionIndexAt(pos);
817 // kDebug() << "Item inserting at: " << insertIndex << "of: " << numberOfItems();
818 if (insertIndex == -1) {
819 m_applet->groupManager().manualSortingRequest(item->abstractItem(), -1);
820 } else {
821 if (!m_parentSplitGroup) {
822 m_applet->groupManager().manualSortingRequest(item->abstractItem(), insertIndex);
823 } else {
824 m_applet->groupManager().manualSortingRequest(item->abstractItem(), insertIndex +
825 m_parentSplitGroup->m_groupMembers.size());
831 void TaskGroupItem::updateActive(AbstractTaskItem *task)
833 if (!m_expandedLayout) {
834 return;
837 m_activeTaskIndex = indexOf(task);
840 int TaskGroupItem::indexOf(AbstractTaskItem *task)
842 if (!m_group || !task) {
843 //kDebug() << "Error";
844 return -1;
847 int index = 0;
849 foreach (AbstractGroupableItem *item, group()->members()) {
850 AbstractTaskItem *taskItem = abstractItem(item);
851 if (taskItem) {
852 if (task == taskItem) {
853 TaskGroupItem *groupItem = qobject_cast<TaskGroupItem *>(taskItem);
854 if (groupItem) {
855 return index + groupItem->indexOf(groupItem->activeSubTask());
858 return index;
861 TaskGroupItem *groupItem = qobject_cast<TaskGroupItem *>(taskItem);
862 if (groupItem) {
863 int subIndex = groupItem->indexOf(task);
864 if(subIndex == -1) {
865 index += groupItem->memberList().count();
866 } else {
867 return index+subIndex;
869 } else {
870 index++;
874 return -1;
877 AbstractTaskItem * TaskGroupItem::activeSubTask()
879 foreach(AbstractGroupableItem *item, group()->members()) {
880 AbstractTaskItem *taskItem = abstractItem(item);
881 if (taskItem) {
882 if(taskItem->isActive()) {
883 TaskGroupItem *groupItem = qobject_cast<TaskGroupItem *>(taskItem);
884 if (groupItem) {
885 return groupItem->activeSubTask();
887 return taskItem;
891 return NULL;
894 int TaskGroupItem::totalSubTasks()
896 int count = 0;
898 foreach(AbstractGroupableItem *item, group()->members()) {
899 AbstractTaskItem *taskItem = abstractItem(item);
900 if (taskItem) {
901 TaskGroupItem *groupItem = qobject_cast<TaskGroupItem *>(taskItem);
902 if (groupItem) {
903 count += groupItem->memberList().count();
904 } else {
905 count++;
909 return count;
913 AbstractTaskItem * TaskGroupItem::selectSubTask(int index)
915 foreach(AbstractGroupableItem *item, group()->members()) {
916 AbstractTaskItem *taskItem = abstractItem(item);
917 if (taskItem) {
918 TaskGroupItem *groupItem = qobject_cast<TaskGroupItem *>(taskItem);
919 if (groupItem) {
920 if (index < groupItem->memberList().count()) {
921 return groupItem->abstractItem(groupItem->group()->members().at(index));
922 } else {
923 index -= groupItem->memberList().count();
925 } else if (index == 0) {
926 return taskItem;
927 } else {
928 --index;
932 return NULL;
935 void TaskGroupItem::wheelEvent(QGraphicsSceneWheelEvent *event)
937 int subTasks = totalSubTasks();
938 //zero or one tasks don't cycle
939 if (subTasks < 1) {
940 return;
943 //mouse wheel down
944 if (event->delta() < 0) {
945 m_activeTaskIndex++;
946 if (m_activeTaskIndex >= subTasks) {
947 m_activeTaskIndex = 0;
949 //mouse wheel up
950 } else {
951 m_activeTaskIndex--;
952 if (m_activeTaskIndex < 0) {
953 m_activeTaskIndex = subTasks - 1; //last item is a spacer
957 //kDebug() << "Wheel event m_activeTaskIndex: " << m_activeTaskIndex << " of " << subTasks;
958 AbstractTaskItem *taskItem = selectSubTask(m_activeTaskIndex);
959 if (taskItem) {
960 taskItem->activate();
964 int TaskGroupItem::maxRows()
966 return m_maximumRows;
969 void TaskGroupItem::setMaxRows(int rows)
971 m_maximumRows = rows;
972 if (m_expandedLayout) {
973 m_expandedLayout->setMaximumRows(m_maximumRows);
977 bool TaskGroupItem::forceRows()
979 return m_forceRows;
982 void TaskGroupItem::setForceRows(bool forceRows)
984 m_forceRows = forceRows;
985 if (m_expandedLayout) {
986 m_expandedLayout->setForceRows(m_forceRows);
990 int TaskGroupItem::optimumCapacity()
992 if (m_expandedLayout) {
993 return m_expandedLayout->maximumRows() * m_expandedLayout->preferredColumns();
996 return 1;
999 AbstractTaskItem* TaskGroupItem::abstractItem(AbstractItemPtr item)
1001 if (m_groupMembers.contains(item)) {
1002 return m_groupMembers.value(item);
1004 //kDebug() << "item not found";
1005 return 0;
1008 void TaskGroupItem::setAdditionalMimeData(QMimeData* mimeData)
1010 if (m_group) {
1011 m_group->addMimeData(mimeData);
1015 void TaskGroupItem::publishIconGeometry() const
1017 // only do this if we are a collapsed group, with a GroupPtr and members
1018 if (m_expandedLayout || !m_group || m_groupMembers.isEmpty()) {
1019 return;
1022 QRect rect = iconGeometry();
1023 publishIconGeometry(rect);
1026 void TaskGroupItem::publishIconGeometry(const QRect &rect) const
1028 foreach (AbstractTaskItem *item, m_groupMembers) {
1029 WindowTaskItem *windowItem = qobject_cast<WindowTaskItem *>(item);
1030 if (windowItem) {
1031 windowItem->publishIconGeometry(rect);
1032 continue;
1035 TaskGroupItem *groupItem = qobject_cast<TaskGroupItem *>(item);
1036 if (groupItem) {
1037 groupItem->publishIconGeometry(rect);
1042 #include "taskgroupitem.moc"