• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • workspace API Reference
  • KDE Home
  • Contact Us
 

GroupingDesktop

  • sources
  • kde-4.14
  • workspace
  • kdeplasma-addons
  • containments
  • groupingdesktop
  • lib
groupingcontainment.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2009-2010 by Giulio Camuffo <giuliocamuffo@gmail.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Library General Public License as
6  * published by the Free Software Foundation; either version 2, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this program; if not, write to the
16  * Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19 
20 #include "groupingcontainment.h"
21 #include "groupingcontainment_p.h"
22 
23 #include <QtGui/QGraphicsScene>
24 #include <QtGui/QGraphicsSceneContextMenuEvent>
25 #include <QtGui/QGraphicsLinearLayout>
26 #include <QtGui/QAction>
27 #include <QtGui/QGraphicsView>
28 #include <QtCore/QTimer>
29 
30 #include <KDebug>
31 #include <KMenu>
32 #include <KIcon>
33 
34 #include <kwindowsystem.h>
35 #include <netwm.h>
36 
37 #include <Plasma/Corona>
38 #include <Plasma/Animator>
39 #include <Plasma/Animation>
40 #include <Plasma/WindowEffects>
41 
42 #include "abstractgroup.h"
43 #include "abstractgroup_p.h"
44 #include "handle.h"
45 
46 #include "groupexplorer/explorerwindow.h"
47 
48 //----------------------GroupingContainmentPrivate-----------------------
49 
50 int GroupingContainmentPrivate::s_maxZValue = 0;
51 unsigned int GroupingContainmentPrivate::s_groupId = 0;
52 
53 GroupingContainmentPrivate::GroupingContainmentPrivate(GroupingContainment *containment)
54  : q(containment),
55  mainGroup(0),
56  mainGroupId(0),
57  layout(0),
58  loading(true),
59  movingWidget(0),
60  interestingWidget(0),
61  movementHelperWidget(new QGraphicsWidget(q)),
62  widgetToBeSetMoving(0),
63  blockSceneEventFilter(false)
64 {
65  newGroupAction = new QAction(i18n("Add Groups"), q);
66  newGroupAction->setIcon(KIcon("list-add"));
67 
68  deleteGroupAction = new QAction(q);
69  deleteGroupAction->setIcon(KIcon("edit-delete"));
70  deleteGroupAction->setVisible(false);
71 
72  configureGroupAction = new QAction(q);
73  configureGroupAction->setIcon(KIcon("configure"));
74  configureGroupAction->setVisible(false);
75 
76  separator = new QAction(q);
77  separator->setSeparator(true);
78 
79  q->connect(newGroupAction, SIGNAL(triggered()), q, SLOT(newGroupClicked()));
80  q->connect(deleteGroupAction, SIGNAL(triggered()), q, SLOT(deleteGroup()));
81  q->connect(configureGroupAction, SIGNAL(triggered()), q, SLOT(configureGroup()));
82 }
83 
84 GroupingContainmentPrivate::~GroupingContainmentPrivate()
85 {
86  //ensure we don't remain with an instance of ExplorerWindow when we don't have
87  //grouping containments anymore. Not the best way to do it but it won't cause
88  //any harm because it will be recreated the next time it's needed.
89  delete ExplorerWindow::instance();
90 }
91 
92 AbstractGroup *GroupingContainmentPrivate::createGroup(const QString &plugin, const QPointF &pos,
93  unsigned int id, bool delayInit)
94 {
95  foreach (AbstractGroup *group, groups) {
96  if (group->id() == id) {
97  return 0;
98  }
99  }
100 
101  AbstractGroup *group = AbstractGroup::load(plugin, q);
102 
103  if (!group) {
104  return 0;
105  }
106 
107  if (groups.contains(group)) {
108  delete group;
109  return 0;
110  }
111 
112  if (id == 0) {
113  id = ++s_groupId;
114  } else if (id > s_groupId) {
115  s_groupId = id;
116  }
117  group->d->id = id;
118 
119  groups << group;
120 
121  q->addGroup(group, pos);
122 
123  if (!delayInit) {
124  group->init();
125 
126  if (!loading) {
127  group->d->restoreChildren();
128  }
129  group->save(*(group->d->mainConfigGroup()));
130  emit q->configNeedsSaving();
131  }
132 
133  return group;
134 }
135 
136 void GroupingContainmentPrivate::handleDisappeared(Handle *handle)
137 {
138  if (handles.contains(handle->widget())) {
139  handles.remove(handle->widget());
140  handle->detachWidget();
141  if (q->scene()) {
142  q->scene()->removeItem(handle);
143  }
144  handle->deleteLater();
145  }
146 }
147 
148 void GroupingContainmentPrivate::onGroupRemoved(AbstractGroup *group)
149 {
150  kDebug()<<"Removed group"<<group->id();
151 
152  groups.removeAll(group);
153  group->removeEventFilter(q);
154  group->removeSceneEventFilter(q);
155 
156  if (handles.contains(group)) {
157  Handle *handle = handles.value(group);
158  handles.remove(group);
159  delete handle;
160  }
161 
162  emit q->groupRemoved(group);
163  emit q->configNeedsSaving();
164 }
165 
166 void GroupingContainmentPrivate::onAppletRemoved(Plasma::Applet *applet)
167 {
168  kDebug()<<"Removed applet"<<applet->id();
169 
170  applet->removeEventFilter(q);
171  applet->removeSceneEventFilter(q);
172 
173  if (handles.contains(applet)) {
174  Handle *handle = handles.value(applet);
175  handles.remove(applet);
176  delete handle;
177  }
178 }
179 
180 QList<AbstractGroup *> GroupingContainmentPrivate::groupsAt(const QPointF &pos, QGraphicsWidget *uppermostItem)
181 {
182  QList<AbstractGroup *> groups;
183 
184  if (pos.isNull()) {
185  return groups;
186  }
187 
188  QList<QGraphicsItem *> items = q->scene()->items(q->mapToScene(pos),
189  Qt::IntersectsItemShape,
190  Qt::DescendingOrder);
191 
192  if (items.isEmpty()) {
193  return groups;
194  }
195 
196  bool goOn;
197  if (uppermostItem && items.contains(uppermostItem)) {
198  do {
199  if (items.isEmpty()) {
200  return groups;
201  }
202  goOn = items.first() != uppermostItem;
203  items.removeFirst();
204  } while (goOn);
205  }
206 
207  for (int i = 0; i < items.size(); ++i) {
208  AbstractGroup *group = qgraphicsitem_cast<AbstractGroup *>(items.at(i));
209  if (group && group->contentsRect().contains(q->mapToItem(group, pos))) {
210  groups << group;
211  }
212  }
213 
214  return groups;
215 }
216 
217 AbstractGroup *GroupingContainmentPrivate::groupAt(const QPointF &pos, QGraphicsWidget *uppermostItem)
218 {
219  QList<AbstractGroup *> groups = groupsAt(pos, uppermostItem);
220  if (groups.isEmpty()) {
221  return 0;
222  }
223 
224  return groups.first();
225 }
226 
227 void GroupingContainmentPrivate::manageApplet(Plasma::Applet *applet, const QPointF &pos)
228 {
229  int z = applet->zValue();
230  if (GroupingContainmentPrivate::s_maxZValue < z) {
231  GroupingContainmentPrivate::s_maxZValue = z;
232  } else {
233  applet->setZValue(GroupingContainmentPrivate::s_maxZValue);
234  }
235 
236  AbstractGroup *group = 0;
237  if (interestingGroup) {
238  group = interestingGroup.data();
239  interestingGroup.clear();
240  } else {
241  group = groupAt(pos.x() < 0 || pos.y() < 0 ? QPointF(10, 10) : pos);
242  }
243 
244  if (group) {
245  group->addApplet(applet);
246  }
247 
248  applet->installEventFilter(q);
249  applet->installSceneEventFilter(q);
250 
251  q->connect(applet, SIGNAL(appletDestroyed(Plasma::Applet*)), q, SLOT(onAppletRemoved(Plasma::Applet*)));
252 }
253 
254 void GroupingContainmentPrivate::manageGroup(AbstractGroup *subGroup, const QPointF &pos)
255 {
256  q->raise(subGroup);
257 
258  AbstractGroup *group = 0;
259  if (interestingGroup) {
260  group = interestingGroup.data();
261  interestingGroup.clear();
262  } else {
263  group = groupAt(pos, subGroup);
264  }
265 
266  if (group && (group != subGroup)) {
267  group->addSubGroup(subGroup);
268  }
269 }
270 
271 void GroupingContainmentPrivate::newGroupClicked()
272 {
273  ExplorerWindow *w = ExplorerWindow::instance();
274  if (w->isHidden()) {
275  w->setContainment(q);
276  w->setLocation(q->location());
277  w->showGroupExplorer();
278  w->resize(w->sizeHint());
279 
280  bool moved = false;
281  if (q->containmentType() == Plasma::Containment::PanelContainment ||
282  q->containmentType() == Plasma::Containment::CustomPanelContainment) {
283  // try to align it with the appropriate panel view
284  QGraphicsView *view = q->view();
285  if (view) {
286  w->move(w->positionForPanelGeometry(view->geometry()));
287  moved = true;
288  }
289  }
290 
291  if (!moved) {
292  // set it to the bottom of the screen as we have no better hints to go by
293  QRect geom = q->corona()->screenGeometry(q->screen());
294  w->setGeometry(geom.x(), geom.bottom() - w->height(), geom.width(), w->height());
295  }
296 
297  w->show();
298  Plasma::WindowEffects::slideWindow(w, Plasma::BottomEdge);
299  KWindowSystem::setOnAllDesktops(w->winId(), true);
300  KWindowSystem::activateWindow(w->winId());
301  KWindowSystem::setState(w->winId(), NET::SkipTaskbar | NET::SkipPager | NET::Sticky | NET::KeepAbove);
302  }
303 }
304 
305 void GroupingContainmentPrivate::deleteGroup()
306 {
307  int id = deleteGroupAction->data().toInt();
308 
309  foreach (AbstractGroup *group, groups) {
310  if ((int)group->id() == id) {
311  group->destroy();
312 
313  return;
314  }
315  }
316 }
317 
318 void GroupingContainmentPrivate::configureGroup()
319 {
320  int id = configureGroupAction->data().toInt();
321 
322  foreach (AbstractGroup *group, groups) {
323  if ((int)group->id() == id) {
324  group->showConfigurationInterface();
325 
326  return;
327  }
328  }
329 }
330 
331 void GroupingContainmentPrivate::onAppletRemovedFromGroup(Plasma::Applet *applet, AbstractGroup *group)
332 {
333  Q_UNUSED(group)
334 
335  if (applet->parentItem() == q) {
336  applet->installEventFilter(q);
337  }
338 }
339 
340 void GroupingContainmentPrivate::onSubGroupRemovedFromGroup(AbstractGroup *subGroup, AbstractGroup *group)
341 {
342  Q_UNUSED(group)
343 
344  if (subGroup->parentItem() == q) {
345  subGroup->installEventFilter(q);
346  }
347 }
348 
349 void GroupingContainmentPrivate::widgetMovedAnimationComplete()
350 {
351  blockSceneEventFilter = false;
352 }
353 
354 void GroupingContainmentPrivate::onWidgetMoved(QGraphicsWidget *widget)
355 {
356  if (movingWidget != widget) {
357  return;
358  }
359 
360  movingWidget = 0;
361  interestingWidget = 0;
362  movementHelperWidget->setZValue(0);
363 
364  if (interestingGroup) {
365  AbstractGroup *interesting = interestingGroup.data();
366 
367  QGraphicsItem *parent = widget->parentItem();
368  QPointF initialPos(widget->pos());
369 
370  blockSceneEventFilter = true;
371 
372  //removing the handle if changing group, because the new group could provide a different type.
373  //would like to find a way to know if it is the case, but don't know how.
374  if (interesting != widget->property("group").value<AbstractGroup *>()) {
375  Handle *h = handles.value(widget);
376  if (h) {
377  h->deleteLater();
378  handles.remove(widget);
379  }
380  }
381 
382  if (q->corona()->immutability() == Plasma::Mutable) {
383  Plasma::Applet *applet = qobject_cast<Plasma::Applet *>(widget);
384  AbstractGroup *group = static_cast<AbstractGroup *>(widget);
385  if (applet) {
386  interesting->addApplet(applet, false);
387  } else if (!group->isAncestorOf(interesting) && interesting != group) {
388  interesting->addSubGroup(group, false);
389  } else {
390  interestingGroup.clear();
391  return;
392  }
393  }
394 
395  QRectF geom(widget->boundingRect());
396 
397  QRectF rect(interesting->contentsRect());
398  QPointF pos = interesting->mapFromItem(parent, initialPos);
399  if (pos.x() < rect.left()) {
400  pos.setX(rect.left());
401  }
402  if (pos.y() < rect.top()) {
403  pos.setY(rect.top());
404  }
405  interesting->layoutChild(widget, pos);
406  interesting->save(*(interesting->d->mainConfigGroup()));
407  interesting->saveChildren();
408 
409  geom.translate(widget->parentItem()->mapFromItem(parent, initialPos));
410  QRectF newGeom(widget->geometry());
411 
412  if (geom != newGeom) {
413  Plasma::Animation *anim = Plasma::Animator::create(Plasma::Animator::GeometryAnimation);
414  if (anim) {
415  q->connect(anim, SIGNAL(finished()), q, SLOT(widgetMovedAnimationComplete()));
416  anim->setTargetWidget(widget);
417  anim->setProperty("startGeometry", geom);
418  anim->setProperty("targetGeometry", newGeom);
419  anim->start(QAbstractAnimation::DeleteWhenStopped);
420  }
421  } else {
422  blockSceneEventFilter = false;
423  }
424 
425  interestingGroup.clear();
426 
427  } else {
428  widget->setParentItem(q);
429  }
430 
431  emit q->configNeedsSaving();
432 }
433 
434 void GroupingContainmentPrivate::onImmutabilityChanged(Plasma::ImmutabilityType immutability)
435 {
436  newGroupAction->setVisible(immutability == Plasma::Mutable);
437 
438  if (immutability != Plasma::Mutable) {
439  foreach (Handle *handle, handles) {
440  handleDisappeared(handle);
441  }
442  }
443 }
444 
445 void GroupingContainmentPrivate::restoreGroups()
446 {
447  KConfigGroup groupsConfig = q->config("Groups");
448  foreach (AbstractGroup *group, groups) {
449  KConfigGroup groupConfig(&groupsConfig, QString::number(group->id()));
450  KConfigGroup groupInfoConfig(&groupConfig, "GroupInformation");
451 
452  if (groupInfoConfig.isValid() && groupInfoConfig.exists()) {
453  int groupId = groupInfoConfig.readEntry("Group", -1);
454 
455  if (groupId != -1) {
456  AbstractGroup *parentGroup = 0;
457  foreach (AbstractGroup *g, groups) {
458  if ((int)g->id() == groupId) {
459  parentGroup = g;
460  break;
461  }
462  }
463  if (parentGroup) {
464  QTransform t = group->transform();
465  parentGroup->addSubGroup(group, false);
466  group->setTransform(t);
467  } else {
468  groupInfoConfig.deleteGroup();
469  manageGroup(group, group->pos());
470  }
471  }
472  } else if (group != mainGroup) {
473  manageGroup(group, group->pos());
474  }
475  }
476 
477  KConfigGroup appletsConfig = q->config("Applets");
478  foreach (Plasma::Applet *applet, q->applets()) {
479  KConfigGroup appletConfig(&appletsConfig, QString::number(applet->id()));
480  KConfigGroup groupConfig(&appletConfig, "GroupInformation");
481 
482  if (groupConfig.isValid() && groupConfig.exists()) {
483  int groupId = groupConfig.readEntry("Group", -1);
484 
485  if (groupId != -1) {
486  AbstractGroup *group = 0;
487  foreach (AbstractGroup *g, groups) {
488  if ((int)g->id() == groupId) {
489  group = g;
490  break;
491  }
492  }
493  if (group) {
494  QTransform t = applet->transform();
495  group->addApplet(applet, false);
496  applet->setTransform(t);
497  } else {
498  groupConfig.deleteGroup();
499  manageApplet(applet, applet->pos());
500  }
501  }
502  } else { //happens when changing a desktop activity to GroupingDesktop
503  manageApplet(applet, applet->pos());
504  }
505  }
506 
507  foreach (AbstractGroup *group, groups) {
508  group->d->restoreChildren();
509  }
510 
511  //since a Main Group won't have any modification that would cause it to save its settings
512  //we make sure here it saves all it has to save.
513  AbstractGroup *group = mainGroup;
514  if (group) {
515  KConfigGroup cg;
516  group->save(cg);
517  group->saveChildren();
518  emit q->configNeedsSaving();
519  }
520 }
521 
522 void GroupingContainmentPrivate::prepareWidgetToMove()
523 {
524  q->raise(widgetToBeSetMoving);
525  q->raise(movementHelperWidget);
526 
527  //need to do do this because when you have, e.g a flow group in a flow group in a flow group,
528  //when you move the top one outside of the mid one boundaries appears the
529  //lower one's spacer that causes the mid one to move and to propagate the move to its children,
530  //so the upper one would move too. It could be that after the move the lower one decides
531  //that the spacer has to go, causing the mid one to return to its original position and
532  //causing the spacer to flicker. setting the third one's parent to movementHelperWidget
533  //resolves this. i use that widget and not "q" or others because, setting its position equal
534  //to the parentItem's one, it doesn't break the movement via ItemIsMovable.
535  if (q->immutability() == Plasma::Mutable) {
536  movementHelperWidget->setTransform(QTransform());
537  QGraphicsItem *parent = widgetToBeSetMoving->parentItem();
538  QTransform t(parent->itemTransform(movementHelperWidget));
539  QTransform tr(t.m11(), t.m12(), t.m21(), t.m22(), 0, 0);
540  movementHelperWidget->setTransform(tr);
541  QPointF p(q->mapFromItem(parent, QPointF(0, 0)));
542  movementHelperWidget->setPos(p);
543  movementHelperWidget->setMinimumSize(widgetToBeSetMoving->size());
544  widgetToBeSetMoving->setParentItem(movementHelperWidget);
545  }
546 
547  interestingGroup = widgetToBeSetMoving->property("group").value<AbstractGroup *>();
548  movingWidget = widgetToBeSetMoving;
549 
550  if (q->immutability() != Plasma::Mutable) {
551  onWidgetMoved(widgetToBeSetMoving);
552  }
553 
554  widgetToBeSetMoving = 0;
555 }
556 
557 //------------------------GroupingContainment------------------------------
558 
559 GroupingContainment::GroupingContainment(QObject* parent, const QVariantList& args)
560  : Containment(parent, args),
561  d(new GroupingContainmentPrivate(this))
562 {
563  setContainmentType(Plasma::Containment::NoContainmentType);
564  useMainGroup("floating");
565 }
566 
567 GroupingContainment::~GroupingContainment()
568 {
569  delete d;
570 }
571 
572 void GroupingContainment::init()
573 {
574  Plasma::Containment::init();
575 
576  d->newGroupAction->setVisible(immutability() == Plasma::Mutable);
577  addToolBoxAction(d->newGroupAction);
578 
579  connect(this, SIGNAL(appletAdded(Plasma::Applet*,QPointF)),
580  this, SLOT(manageApplet(Plasma::Applet*,QPointF)));
581  connect(this, SIGNAL(immutabilityChanged(Plasma::ImmutabilityType)),
582  this, SLOT(onImmutabilityChanged(Plasma::ImmutabilityType)));
583 }
584 
585 void GroupingContainment::constraintsEvent(Plasma::Constraints constraints)
586 {
587  foreach (AbstractGroup *g, d->groups) {
588  g->updateConstraints(constraints);
589  }
590 }
591 
592 AbstractGroup *GroupingContainment::addGroup(const QString &plugin, const QPointF &pos, int id)
593 {
594  return d->createGroup(plugin, pos, id);
595 }
596 
597 void GroupingContainment::addGroup(AbstractGroup *group, const QPointF &pos)
598 {
599  if (!group) {
600  return;
601  }
602 
603  kDebug()<<"adding group"<<group->id();
604  connect(this, SIGNAL(immutabilityChanged(Plasma::ImmutabilityType)),
605  group, SLOT(setImmutability(Plasma::ImmutabilityType)));
606  connect(group, SIGNAL(groupDestroyed(AbstractGroup*)),
607  this, SLOT(onGroupRemoved(AbstractGroup*)));
608  connect(group, SIGNAL(appletRemovedFromGroup(Plasma::Applet*,AbstractGroup*)),
609  this, SLOT(onAppletRemovedFromGroup(Plasma::Applet*,AbstractGroup*)));
610  connect(group, SIGNAL(subGroupRemovedFromGroup(AbstractGroup*,AbstractGroup*)),
611  this, SLOT(onSubGroupRemovedFromGroup(AbstractGroup*,AbstractGroup*)));
612  connect(group, SIGNAL(configNeedsSaving()), this, SIGNAL(configNeedsSaving()));
613  group->setPos(pos);
614  group->setImmutability(immutability());
615  group->updateConstraints();
616 
617  int z = group->zValue();
618  if (GroupingContainmentPrivate::s_maxZValue < z) {
619  GroupingContainmentPrivate::s_maxZValue = z;
620  }
621 
622  emit groupAdded(group, pos);
623 
624  if (!d->loading && !pos.isNull()) {
625  d->manageGroup(group, pos);
626  Plasma::Animation *anim = Plasma::Animator::create(Plasma::Animator::AppearAnimation);
627  if (anim) {
628  anim->setTargetWidget(group);
629  anim->setDirection(QAbstractAnimation::Backward);
630  anim->start(QAbstractAnimation::DeleteWhenStopped);
631  }
632  }
633 
634  group->installEventFilter(this);
635  group->installSceneEventFilter(this);
636 }
637 
638 QList<AbstractGroup *> GroupingContainment::groups() const
639 {
640  return d->groups;
641 }
642 
643 QList<QAction *> GroupingContainment::contextualActions()
644 {
645  QList<QAction *> list;
646  list << d->newGroupAction << d->separator << d->configureGroupAction << d->deleteGroupAction;
647  return list;
648 }
649 
650 void GroupingContainment::useMainGroup(const QString &name)
651 {
652  if (!name.isEmpty()) {
653  d->mainGroupPlugin = name;
654  }
655 }
656 
657 void GroupingContainment::setMainGroup(AbstractGroup *group)
658 {
659  if (!group) {
660  return;
661  }
662 
663  d->mainGroup = group;
664 
665  layoutMainGroup();
666  group->setIsMainGroup();
667 
668  config().writeEntry("mainGroup", group->id());
669  emit configNeedsSaving();
670 }
671 
672 void GroupingContainment::layoutMainGroup()
673 {
674  if (!d->layout) {
675  d->layout = new QGraphicsLinearLayout(this);
676  d->layout->setContentsMargins(0, 0, 0, 0);
677  }
678  d->layout->addItem(d->mainGroup);
679 }
680 
681 AbstractGroup *GroupingContainment::mainGroup() const
682 {
683  return d->mainGroup;
684 }
685 
686 bool GroupingContainment::sceneEventFilter(QGraphicsItem* watched, QEvent* event)
687 {
688  if (d->blockSceneEventFilter) {
689  return true;
690  }
691 
692  Plasma::Applet *applet = qgraphicsitem_cast<Plasma::Applet *>(watched);
693  AbstractGroup *group = qgraphicsitem_cast<AbstractGroup *>(watched);
694 
695  QGraphicsWidget *widget = 0;
696  if (applet) {
697  widget = applet;
698  } else if (group) {
699  widget = group;
700  }
701 
702  if (event->type() == QEvent::GraphicsSceneHoverEnter || event->type() == QEvent::GraphicsSceneHoverMove) {
703  QGraphicsSceneHoverEvent *he = static_cast<QGraphicsSceneHoverEvent *>(event);
704  if (immutability() == Plasma::Mutable && ((group && !group->isMainGroup()) || applet)) {
705  if (d->handles.contains(widget)) {
706  Handle *handle = d->handles.value(widget);
707  if (handle) {
708  handle->setHoverPos(he->pos());
709  }
710  } else {
711 // kDebug() << "generated group handle";
712  AbstractGroup *parent = widget->property("group").value<AbstractGroup *>();
713  if (parent) {
714  Handle *handle = parent->createHandleForChild(widget);
715  if (handle) {
716  handle->setHoverPos(he->pos());
717  d->handles[widget] = handle;
718  connect(handle, SIGNAL(disappearDone(Handle*)),
719  this, SLOT(handleDisappeared(Handle*)));
720  connect(widget, SIGNAL(geometryChanged()),
721  handle, SLOT(widgetResized()));
722  connect(handle, SIGNAL(widgetMoved(QGraphicsWidget*)),
723  this, SLOT(onWidgetMoved(QGraphicsWidget*)));
724  }
725  }
726  }
727  }
728 
729  foreach (Handle *handle, d->handles) {
730  QGraphicsWidget *w = d->handles.key(handle);
731  if (w != widget && handle) {
732  handle->setHoverPos(w->mapFromScene(he->scenePos()));
733  }
734  }
735  }
736 
737  return false;
738 }
739 
740 bool GroupingContainment::eventFilter(QObject *obj, QEvent *event)
741 {
742  if (immutability() != Plasma::Mutable) {
743  return false;
744  }
745 
746  AbstractGroup *group = qobject_cast<AbstractGroup *>(obj);
747  Plasma::Applet *applet = qobject_cast<Plasma::Applet *>(obj);
748 
749  QGraphicsWidget *widget = 0;
750  if (applet) {
751  widget = applet;
752  } else if (group) {
753  widget = group;
754  }
755 
756  if (widget) {
757  switch (event->type()) {
758  case QEvent::GraphicsSceneMousePress:
759  if (static_cast<QGraphicsSceneMouseEvent *>(event)->button() == Qt::LeftButton &&
760  immutability() == Plasma::Mutable) {
761  d->interestingWidget = widget;
762  }
763  break;
764 
765  case QEvent::GraphicsSceneMove: {
766  if (d->movingWidget != widget && widget == d->interestingWidget) {
767  setMovingWidget(widget);
768  }
769  if (widget == d->movingWidget) {
770  //use the center of the widget to find the possible groups, but pass to
771  //their showDropZone the actual position of the widget, modulo an
772  //eventual shift to make it fit into their contentsRect
773  QPointF p = mapFromScene(widget->scenePos());
774  QRectF rect(widget->contentsRect());
775  QList<AbstractGroup *> groups = d->groupsAt(p + rect.center(), widget);
776  foreach (AbstractGroup *parentGroup ,groups) {
777  if (d->interestingGroup && d->interestingGroup.data() != parentGroup) {
778  d->interestingGroup.data()->showDropZone(QPointF());
779  d->interestingGroup.clear();
780  }
781  QPointF pos = mapToItem(parentGroup, p + rect.topLeft());
782  if (pos.x() < rect.left()) {
783  pos.setX(rect.left());
784  }
785  if (pos.y() < rect.top()) {
786  pos.setY(rect.top());
787  }
788  if (parentGroup->showDropZone(pos)) {
789  d->interestingGroup = parentGroup;
790  break;
791  }
792  }
793  }
794  }
795 
796  break;
797 
798  case QEvent::GraphicsSceneDragMove: {
799  QGraphicsSceneDragDropEvent *e = static_cast<QGraphicsSceneDragDropEvent *>(event);
800  bool ok = true;
801  const QMimeData *mime = e->mimeData();
802  if (mime->hasFormat(AbstractGroup::mimeType())) {
803  QString name = mime->data(AbstractGroup::mimeType());
804  GroupInfo gi = AbstractGroup::groupInfo(name);
805  if (!gi.formFactors().contains(formFactor())) {
806  ok = false;
807  }
808  }
809 
810  if (ok) {
811  QPointF pos(mapFromScene(e->scenePos()));
812  QList<AbstractGroup *> groups = d->groupsAt(pos);
813  foreach (AbstractGroup *group, groups) {
814  if (d->interestingGroup && d->interestingGroup.data() != group) {
815  d->interestingGroup.data()->showDropZone(QPointF());
816  d->interestingGroup.clear();
817  }
818  if (group->showDropZone(mapToItem(group, pos))) {
819  d->interestingGroup = group;
820  break;
821  }
822  }
823  } else {
824  e->ignore();
825  }
826  }
827  break;
828 
829  case QEvent::GraphicsSceneDrop: {
830  if (group) {
831  QGraphicsSceneDragDropEvent *e = static_cast<QGraphicsSceneDragDropEvent *>(event);
832  e->setPos(mapFromScene(e->scenePos()));
833  dropEvent(e);
834  }
835  if (d->interestingGroup) {
836  d->interestingGroup.data()->showDropZone(QPointF());
837  d->interestingGroup.clear();
838  }
839  }
840  break;
841 
842  case QEvent::GraphicsSceneMouseRelease:
843  if (d->movingWidget) {
844  d->onWidgetMoved(widget);
845  }
846  d->interestingWidget = 0;
847 
848  break;
849 
850  default:
851  break;
852  }
853  }
854 
855  return Plasma::Containment::eventFilter(obj, event);
856 }
857 
858 void GroupingContainment::saveContents(KConfigGroup &group) const
859 {
860  Plasma::Containment::saveContents(group);
861 
862  KConfigGroup groupsConfig(&group, "Groups");
863  foreach (AbstractGroup *g, d->groups) {
864  g->save(*(g->d->mainConfigGroup()));
865  g->saveChildren();
866  }
867 }
868 
869 void GroupingContainment::restoreContents(KConfigGroup &group)
870 {
871  Plasma::Containment::restoreContents(group);
872 
873  d->mainGroupId = group.readEntry("mainGroup", 0);
874 
875  KConfigGroup groupsConfig(&group, "Groups");
876  foreach (const QString &groupId, groupsConfig.groupList()) {
877  int id = groupId.toInt();
878  KConfigGroup groupConfig(&groupsConfig, groupId);
879  QString plugin = groupConfig.readEntry("plugin", QString());
880 
881  AbstractGroup *group = d->createGroup(plugin, QPointF(), id);
882  if (group) {
883  group->restore(groupConfig);
884  }
885  }
886 
887  if (d->mainGroupId != 0 && !d->mainGroup) {
888  foreach (AbstractGroup *group, d->groups) {
889  if (group->id() == d->mainGroupId) {
890  setMainGroup(group);
891  }
892  }
893  }
894 
895  if (!d->mainGroupPlugin.isEmpty() && !d->mainGroup) {
896  AbstractGroup *group = d->createGroup(d->mainGroupPlugin, QPointF(), 0, true);
897  setMainGroup(group);
898  group->init();
899  } else if (d->mainGroup && d->mainGroupPlugin != d->mainGroup->pluginName()) {
900  //switching activity between containments with different main groups
901  AbstractGroup *old = d->mainGroup;
902  AbstractGroup *group = d->createGroup(d->mainGroupPlugin, QPointF(), 0, true);
903  setMainGroup(group);
904  group->init();
905 
906  //don't call destroy() because it will wait for the anim to finish before actually destroying it
907  //and we don't have time to wait here
908  old->d->destroyGroup();
909  }
910  if (!d->mainGroup) {
911  kWarning()<<"You have not set a Main Group! This will really cause troubles! You *must* set a Main Group!";
912  }
913 
914  //delay so to allow the applets and subGroup to prepare themselves.
915  //without this PopupApplets in GridGroups would be restored always expanded,
916  //even if they were iconified the last session.
917  QTimer::singleShot(0, this, SLOT(restoreGroups()));
918 
919  d->loading = false;
920 }
921 
922 void GroupingContainment::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
923 {
924  d->deleteGroupAction->setVisible(false);
925  d->configureGroupAction->setVisible(false);
926  d->lastClick = event->pos();
927 
928  AbstractGroup *group = d->groupAt(event->pos());
929 
930  while (group && group->isMainGroup()) {
931  group = group->parentGroup();
932  if (!group) {
933  break;
934  }
935  }
936 
937  if (group && (immutability() == Plasma::Mutable) && (group->immutability() == Plasma::Mutable) && !group->isMainGroup()) {
938  d->deleteGroupAction->setVisible(true);
939  d->deleteGroupAction->setData(group->id());
940  d->deleteGroupAction->setText(i18n("Remove this %1",
941  AbstractGroup::groupInfo(group->pluginName()).prettyName()));
942  if (group->hasConfigurationInterface()) {
943  d->configureGroupAction->setVisible(true);
944  d->configureGroupAction->setText(i18n("Configure this %1",
945  AbstractGroup::groupInfo(group->pluginName()).prettyName()));
946  d->configureGroupAction->setData(group->id());
947  }
948  }
949 
950  event->ignore();
951 
952  Plasma::Containment::contextMenuEvent(event);
953 }
954 
955 void GroupingContainment::dropEvent(QGraphicsSceneDragDropEvent *event)
956 {
957  const QMimeData *mime = event->mimeData();
958  if (mime->hasFormat(AbstractGroup::mimeType())) {
959  QString name = mime->data(AbstractGroup::mimeType());
960  GroupInfo gi = AbstractGroup::groupInfo(name);
961  if (gi.formFactors().contains(formFactor())) {
962  d->createGroup(name, event->pos(), 0);
963  }
964  } else {
965  Plasma::Containment::dropEvent(event);
966  }
967 }
968 
969 void GroupingContainment::setMovingWidget(QGraphicsWidget *widget)
970 {
971  d->interestingWidget = 0;
972 
973  if (d->movingWidget) {
974  if (d->movingWidget == widget) {
975  return;
976  }
977  d->onWidgetMoved(d->movingWidget);
978  }
979 
980  AbstractGroup *group = widget->property("group").value<AbstractGroup *>();
981  if (group) {
982  group->releaseChild(widget);
983  }
984 
985  d->widgetToBeSetMoving = widget;
986  //delay so to allow the widget to receive and react to the events caused by the changes
987  //its group may do in releaseChild
988  QTimer::singleShot(0, this, SLOT(prepareWidgetToMove()));
989 }
990 
991 QGraphicsWidget *GroupingContainment::movingWidget() const
992 {
993  return d->movingWidget;
994 }
995 
996 void GroupingContainment::raise(QGraphicsWidget *widget)
997 {
998  widget->setZValue(++GroupingContainmentPrivate::s_maxZValue);
999 }
1000 
1001 #include "groupingcontainment.moc"
QTransform
GroupingContainment::mainGroup
AbstractGroup * mainGroup() const
Returns the Main Group of this Containment.
QGraphicsSceneDragDropEvent::mimeData
const QMimeData * mimeData() const
QEvent
GroupingContainment::GroupingContainment
GroupingContainment(QObject *parent, const QVariantList &args)
Default constructor.
Definition: groupingcontainment.cpp:559
QEvent::type
Type type() const
groupingcontainment.h
QMimeData::data
QByteArray data(const QString &mimeType) const
QWidget::isHidden
bool isHidden() const
QGraphicsLinearLayout
ExplorerWindow
Definition: explorerwindow.h:40
GroupingContainment::addGroup
AbstractGroup * addGroup(const QString &plugin, const QPointF &pos=QPointF(0, 0), int id=0)
Creates a new Group and it adds it to this Containment.
Definition: groupingcontainment.cpp:592
AbstractGroup::setImmutability
void setImmutability(Plasma::ImmutabilityType immutability)
Sets the immutability type for this Group (not immutable, user immutable or system immutable) ...
Definition: abstractgroup.cpp:285
QGraphicsSceneHoverEvent::scenePos
QPointF scenePos() const
GroupingContainment::raise
void raise(QGraphicsWidget *widget)
Raises a widget above all the other Applets or Groups.
Definition: groupingcontainment.cpp:996
QGraphicsObject::pos
pos
GroupingContainment::saveContents
virtual void saveContents(KConfigGroup &group) const
Reimplemented from Plasma::Containment.
Definition: groupingcontainment.cpp:858
AbstractGroup::showConfigurationInterface
virtual void showConfigurationInterface()
Lets the user interact with the Group options.
Definition: abstractgroup.cpp:775
QGraphicsItem::setParentItem
void setParentItem(QGraphicsItem *newParent)
QMimeData::hasFormat
virtual bool hasFormat(const QString &mimeType) const
QGraphicsSceneContextMenuEvent::pos
QPointF pos() const
GroupInfo::formFactors
QSet< Plasma::FormFactor > formFactors() const
Definition: groupinfo.cpp:77
QList::removeFirst
void removeFirst()
AbstractGroup::addApplet
void addApplet(Plasma::Applet *applet, bool layoutApplet=true)
Adds an Applet to this Group.
Definition: abstractgroup.cpp:317
QList::at
const T & at(int i) const
Handle::detachWidget
virtual void detachWidget()
Definition: handle.cpp:105
GroupingContainment::init
void init()
Reimplemented from Plasma::Applet.
Definition: groupingcontainment.cpp:572
Handle::setHoverPos
virtual void setHoverPos(const QPointF &hoverPos)
Definition: handle.cpp:173
QRect::translate
void translate(int dx, int dy)
AbstractGroup::setIsMainGroup
void setIsMainGroup()
Tells this Group it is a Main Group, causing it to: not paint a background; not be movable; not have ...
Definition: abstractgroup.cpp:657
QVariant::value
T value() const
QGraphicsItem
QRect::x
int x() const
Handle
Definition: handle.h:41
abstractgroup.h
AbstractGroup::immutability
Plasma::ImmutabilityType immutability() const
Returns the type of immutability of this Group.
Definition: abstractgroup.cpp:302
GroupingContainment::setMovingWidget
void setMovingWidget(QGraphicsWidget *widget)
Call this function when an Applet or a Group is being moved by the user.
Definition: groupingcontainment.cpp:969
QMimeData
AbstractGroup::load
static AbstractGroup * load(const QString &name, QGraphicsItem *parent=0)
Creates a new Group.
Definition: abstractgroup.cpp:839
QList::size
int size() const
QWidget::geometry
geometry
QPointF
GroupingContainment::groupAdded
void groupAdded(AbstractGroup *group, const QPointF &pos)
Emitted when a new Group is added to this Containment.
AbstractGroup::groupInfo
static GroupInfo groupInfo(const QString &name)
Definition: abstractgroup.cpp:855
QWidget::resize
void resize(int w, int h)
QGraphicsSceneHoverEvent::pos
QPointF pos() const
GroupingContainment::constraintsEvent
virtual void constraintsEvent(Plasma::Constraints constraints)
Reimplemented from Plasma::Applet.
Definition: groupingcontainment.cpp:585
handle.h
QRect
QGraphicsItem::zValue
qreal zValue() const
QString::number
QString number(int n, int base)
AbstractGroup::pluginName
virtual QString pluginName() const =0
Returns the plugin name for the Group.
QPointF::x
qreal x() const
QPointF::y
qreal y() const
GroupingContainment::eventFilter
virtual bool eventFilter(QObject *obj, QEvent *event)
Reimplemented from QObject.
Definition: groupingcontainment.cpp:740
QEvent::ignore
void ignore()
QObject::property
QVariant property(const char *name) const
GroupingContainment::sceneEventFilter
virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
Reimplemented from QGraphicsItem.
Definition: groupingcontainment.cpp:686
QObject::installEventFilter
void installEventFilter(QObject *filterObj)
GroupingContainment::~GroupingContainment
virtual ~GroupingContainment()
Default destructor.
Definition: groupingcontainment.cpp:567
QObject
AbstractGroup::isMainGroup
bool isMainGroup
Definition: abstractgroup.h:49
QGraphicsItem::setPos
void setPos(const QPointF &pos)
QTransform::m11
qreal m11() const
QTransform::m12
qreal m12() const
QTransform::m21
qreal m21() const
QTransform::m22
qreal m22() const
QString::toInt
int toInt(bool *ok, int base) const
QList::isEmpty
bool isEmpty() const
QString::isEmpty
bool isEmpty() const
QGraphicsItem::mapFromScene
QPointF mapFromScene(const QPointF &point) const
QGraphicsItem::itemTransform
QTransform itemTransform(const QGraphicsItem *other, bool *ok) const
AbstractGroup::createHandleForChild
virtual Handle * createHandleForChild(QGraphicsWidget *child)
Returns an handle for a child of this Group.
Definition: abstractgroup.cpp:633
AbstractGroup::parentGroup
AbstractGroup * parentGroup() const
Returns the Group that contains this one, 0 if there is no one.
Definition: abstractgroup.cpp:312
QWidget::move
void move(int x, int y)
QGraphicsWidget
QGraphicsSceneContextMenuEvent
QGraphicsItem::removeSceneEventFilter
void removeSceneEventFilter(QGraphicsItem *filterItem)
GroupingContainment::movingWidget
QGraphicsWidget * movingWidget() const
Returns the widget that is currently being moved by the user, or 0 if there is not any...
Definition: groupingcontainment.cpp:991
QWidget::winId
WId winId() const
QObject::deleteLater
void deleteLater()
QList::first
T & first()
GroupingContainment::contextualActions
QList< QAction * > contextualActions()
Reimplemented from Plasma::Applet.
Definition: groupingcontainment.cpp:643
QString
QList
AbstractGroup::releaseChild
virtual void releaseChild(QGraphicsWidget *child)
Called when an Applet or a Group starts to be moved by the user.
Definition: abstractgroup.cpp:829
QGraphicsSceneDragDropEvent::scenePos
QPointF scenePos() const
QGraphicsSceneHoverEvent
Handle::widget
QGraphicsWidget * widget() const
Definition: handle.cpp:80
QGraphicsSceneDragDropEvent::pos
QPointF pos() const
GroupingContainment::groups
QList< AbstractGroup * > groups() const
Returns a list of all the Groups contained in this Containment.
Definition: groupingcontainment.cpp:638
QVariant::clear
void clear()
ExplorerWindow::showGroupExplorer
void showGroupExplorer()
Definition: explorerwindow.cpp:341
GroupingContainment::setMainGroup
void setMainGroup(AbstractGroup *group)
Sets a Main Group for this Containment.
Definition: groupingcontainment.cpp:657
ExplorerWindow::setLocation
virtual void setLocation(const Plasma::Location &loc)
Definition: explorerwindow.cpp:254
ExplorerWindow::instance
static ExplorerWindow * instance()
Definition: explorerwindow.cpp:99
QList::contains
bool contains(const T &value) const
GroupingContainment::useMainGroup
void useMainGroup(const QString &type)
Tells the Containment to use a Main Group of the given type.
Definition: groupingcontainment.cpp:650
QWidget::sizeHint
sizeHint
QSet::contains
bool contains(const T &value) const
AbstractGroup::mimeType
static QString mimeType()
Definition: abstractgroup.cpp:834
GroupingContainment::layoutMainGroup
virtual void layoutMainGroup()
Lays out the Main Group.
Definition: groupingcontainment.cpp:672
QGraphicsItem::data
QVariant data(int key) const
AbstractGroup::saveChildren
virtual void saveChildren() const
Calls saveChildGroupInfo for every child.
Definition: abstractgroup.cpp:572
GroupingContainment::restoreContents
virtual void restoreContents(KConfigGroup &group)
Reimplemented from Plasma::Containment.
Definition: groupingcontainment.cpp:869
QRect::width
int width() const
AbstractGroup::showDropZone
virtual bool showDropZone(const QPointF &pos)
Shows a visual clue for drag and drop The default implementation does nothing, reimplement it in grou...
Definition: abstractgroup.cpp:619
AbstractGroup::init
virtual void init()
Method called a little after the constructor.
Definition: abstractgroup.cpp:280
QGraphicsItem::mapFromItem
QPointF mapFromItem(const QGraphicsItem *item, const QPointF &point) const
AbstractGroup::hasConfigurationInterface
bool hasConfigurationInterface() const
Returns true if this Group provides a GUI configuration.
Definition: abstractgroup.cpp:805
GroupingContainment
The base Containment class.
Definition: groupingcontainment.h:38
GroupingContainment::contextMenuEvent
virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
Reimplemented from QGraphicsItem.
Definition: groupingcontainment.cpp:922
GroupingContainment::dropEvent
virtual void dropEvent(QGraphicsSceneDragDropEvent *event)
Reimplemented from QGraphicsItem.
Definition: groupingcontainment.cpp:955
QRectF
AbstractGroup::restore
virtual void restore(KConfigGroup &group)
Restore the state information about this Group.
Definition: abstractgroup.cpp:588
QGraphicsItem::transform
QTransform transform() const
QPointF::setX
void setX(qreal x)
QPointF::setY
void setY(qreal y)
QAction
QGraphicsItem::setTransform
void setTransform(const QTransform &matrix, bool combine)
AbstractGroup::addSubGroup
void addSubGroup(AbstractGroup *group, bool layoutGroup=true)
Adds a Group to this Group.
Definition: abstractgroup.cpp:359
QRect::bottom
int bottom() const
AbstractGroup::layoutChild
virtual void layoutChild(QGraphicsWidget *child, const QPointF &pos)=0
Lays out a child inside the Group A sub class probably wants to reimplement this function.
QGraphicsItem::installSceneEventFilter
void installSceneEventFilter(QGraphicsItem *filterItem)
QGraphicsItem::parentItem
QGraphicsItem * parentItem() const
QRectF::contains
bool contains(const QPointF &point) const
QWidget::show
void show()
AbstractGroup::id
uint id
Definition: abstractgroup.h:47
QGraphicsLayoutItem::contentsRect
QRectF contentsRect() const
AbstractGroup::destroy
void destroy()
Destroy this Groups and its children, deleting the configurations too.
Definition: abstractgroup.cpp:476
QGraphicsSceneDragDropEvent
GroupInfo
Definition: groupinfo.h:30
ExplorerWindow::setContainment
virtual void setContainment(Plasma::Containment *containment)
Definition: explorerwindow.cpp:123
AbstractGroup
The base Group class.
Definition: abstractgroup.h:43
QGraphicsItem::setZValue
void setZValue(qreal z)
QGraphicsWidget::geometry
geometry
QGraphicsView
QGraphicsWidget::boundingRect
virtual QRectF boundingRect() const
ExplorerWindow::positionForPanelGeometry
QPoint positionForPanelGeometry(const QRect &panelGeom) const
Definition: explorerwindow.cpp:298
explorerwindow.h
QObject::removeEventFilter
void removeEventFilter(QObject *obj)
QWidget::height
height
AbstractGroup::save
virtual void save(KConfigGroup &group) const
Saves state information about this Group.
Definition: abstractgroup.cpp:548
AbstractGroup::updateConstraints
void updateConstraints(Plasma::Constraints constraints=Plasma::AllConstraints)
Called when any of the geometry constraints have been updated.
Definition: abstractgroup.cpp:815
QPointF::isNull
bool isNull() const
QTimer::singleShot
singleShot
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:42:57 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

GroupingDesktop

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

workspace API Reference

Skip menu "workspace API Reference"
  • kdeplasma-addons
  •       GroupingDesktop
  •     liblancelot

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal