21 #include "groupingcontainment_p.h"
23 #include <QtGui/QGraphicsScene>
24 #include <QtGui/QGraphicsSceneContextMenuEvent>
25 #include <QtGui/QGraphicsLinearLayout>
26 #include <QtGui/QAction>
27 #include <QtGui/QGraphicsView>
28 #include <QtCore/QTimer>
34 #include <kwindowsystem.h>
37 #include <Plasma/Corona>
38 #include <Plasma/Animator>
39 #include <Plasma/Animation>
40 #include <Plasma/WindowEffects>
43 #include "abstractgroup_p.h"
50 int GroupingContainmentPrivate::s_maxZValue = 0;
51 unsigned int GroupingContainmentPrivate::s_groupId = 0;
62 widgetToBeSetMoving(0),
63 blockSceneEventFilter(false)
65 newGroupAction =
new QAction(i18n(
"Add Groups"), q);
66 newGroupAction->setIcon(KIcon(
"list-add"));
68 deleteGroupAction =
new QAction(q);
69 deleteGroupAction->setIcon(KIcon(
"edit-delete"));
70 deleteGroupAction->setVisible(
false);
72 configureGroupAction =
new QAction(q);
73 configureGroupAction->setIcon(KIcon(
"configure"));
74 configureGroupAction->setVisible(
false);
76 separator =
new QAction(q);
77 separator->setSeparator(
true);
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()));
84 GroupingContainmentPrivate::~GroupingContainmentPrivate()
92 AbstractGroup *GroupingContainmentPrivate::createGroup(
const QString &plugin,
const QPointF &pos,
93 unsigned int id,
bool delayInit)
96 if (group->
id() == id) {
107 if (groups.contains(group)) {
114 }
else if (
id > s_groupId) {
121 q->addGroup(group, pos);
127 group->d->restoreChildren();
129 group->save(*(group->d->mainConfigGroup()));
130 emit q->configNeedsSaving();
136 void GroupingContainmentPrivate::handleDisappeared(
Handle *handle)
138 if (handles.contains(handle->
widget())) {
139 handles.remove(handle->
widget());
142 q->scene()->removeItem(handle);
144 handle->deleteLater();
148 void GroupingContainmentPrivate::onGroupRemoved(
AbstractGroup *group)
150 kDebug()<<
"Removed group"<<group->
id();
152 groups.removeAll(group);
153 group->removeEventFilter(q);
154 group->removeSceneEventFilter(q);
156 if (handles.contains(group)) {
157 Handle *handle = handles.value(group);
158 handles.remove(group);
162 emit q->groupRemoved(group);
163 emit q->configNeedsSaving();
166 void GroupingContainmentPrivate::onAppletRemoved(Plasma::Applet *applet)
168 kDebug()<<
"Removed applet"<<applet->id();
170 applet->removeEventFilter(q);
171 applet->removeSceneEventFilter(q);
173 if (handles.contains(applet)) {
174 Handle *handle = handles.value(applet);
175 handles.remove(applet);
180 QList<AbstractGroup *> GroupingContainmentPrivate::groupsAt(
const QPointF &pos,
QGraphicsWidget *uppermostItem)
182 QList<AbstractGroup *> groups;
188 QList<QGraphicsItem *> items = q->scene()->items(q->mapToScene(pos),
189 Qt::IntersectsItemShape,
190 Qt::DescendingOrder);
192 if (items.isEmpty()) {
197 if (uppermostItem && items.contains(uppermostItem)) {
199 if (items.isEmpty()) {
202 goOn = items.first() != uppermostItem;
207 for (
int i = 0; i < items.size(); ++i) {
209 if (group && group->contentsRect().contains(q->mapToItem(group, pos))) {
219 QList<AbstractGroup *> groups = groupsAt(pos, uppermostItem);
220 if (groups.isEmpty()) {
224 return groups.first();
227 void GroupingContainmentPrivate::manageApplet(Plasma::Applet *applet,
const QPointF &pos)
229 int z = applet->zValue();
230 if (GroupingContainmentPrivate::s_maxZValue < z) {
231 GroupingContainmentPrivate::s_maxZValue = z;
233 applet->setZValue(GroupingContainmentPrivate::s_maxZValue);
237 if (interestingGroup) {
238 group = interestingGroup.data();
239 interestingGroup.clear();
241 group = groupAt(pos.x() < 0 || pos.y() < 0 ? QPointF(10, 10) : pos);
248 applet->installEventFilter(q);
249 applet->installSceneEventFilter(q);
251 q->connect(applet, SIGNAL(appletDestroyed(Plasma::Applet*)), q, SLOT(onAppletRemoved(Plasma::Applet*)));
254 void GroupingContainmentPrivate::manageGroup(
AbstractGroup *subGroup,
const QPointF &pos)
259 if (interestingGroup) {
260 group = interestingGroup.data();
261 interestingGroup.clear();
263 group = groupAt(pos, subGroup);
266 if (group && (group != subGroup)) {
271 void GroupingContainmentPrivate::newGroupClicked()
278 w->resize(w->sizeHint());
281 if (q->containmentType() == Plasma::Containment::PanelContainment ||
282 q->containmentType() == Plasma::Containment::CustomPanelContainment) {
284 QGraphicsView *view = q->view();
293 QRect geom = q->corona()->screenGeometry(q->screen());
294 w->setGeometry(geom.x(), geom.bottom() - w->height(), geom.width(), w->height());
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);
305 void GroupingContainmentPrivate::deleteGroup()
307 int id = deleteGroupAction->data().toInt();
310 if ((
int)group->
id() == id) {
318 void GroupingContainmentPrivate::configureGroup()
320 int id = configureGroupAction->data().toInt();
323 if ((
int)group->
id() == id) {
331 void GroupingContainmentPrivate::onAppletRemovedFromGroup(Plasma::Applet *applet,
AbstractGroup *group)
335 if (applet->parentItem() == q) {
336 applet->installEventFilter(q);
344 if (subGroup->parentItem() == q) {
345 subGroup->installEventFilter(q);
349 void GroupingContainmentPrivate::widgetMovedAnimationComplete()
351 blockSceneEventFilter =
false;
354 void GroupingContainmentPrivate::onWidgetMoved(
QGraphicsWidget *widget)
356 if (movingWidget != widget) {
361 interestingWidget = 0;
362 movementHelperWidget->setZValue(0);
364 if (interestingGroup) {
367 QGraphicsItem *parent = widget->parentItem();
368 QPointF initialPos(widget->pos());
370 blockSceneEventFilter =
true;
374 if (interesting != widget->property(
"group").value<
AbstractGroup *>()) {
375 Handle *h = handles.value(widget);
378 handles.remove(widget);
382 if (q->corona()->immutability() == Plasma::Mutable) {
383 Plasma::Applet *applet = qobject_cast<Plasma::Applet *>(widget);
387 }
else if (!group->isAncestorOf(interesting) && interesting != group) {
390 interestingGroup.clear();
395 QRectF geom(widget->boundingRect());
397 QRectF rect(interesting->contentsRect());
398 QPointF pos = interesting->mapFromItem(parent, initialPos);
399 if (pos.x() < rect.left()) {
400 pos.setX(rect.left());
402 if (pos.y() < rect.top()) {
403 pos.setY(rect.top());
406 interesting->
save(*(interesting->d->mainConfigGroup()));
409 geom.translate(widget->parentItem()->mapFromItem(parent, initialPos));
410 QRectF newGeom(widget->geometry());
412 if (geom != newGeom) {
413 Plasma::Animation *anim = Plasma::Animator::create(Plasma::Animator::GeometryAnimation);
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);
422 blockSceneEventFilter =
false;
425 interestingGroup.clear();
428 widget->setParentItem(q);
431 emit q->configNeedsSaving();
434 void GroupingContainmentPrivate::onImmutabilityChanged(Plasma::ImmutabilityType immutability)
436 newGroupAction->setVisible(immutability == Plasma::Mutable);
438 if (immutability != Plasma::Mutable) {
439 foreach (
Handle *handle, handles) {
440 handleDisappeared(handle);
445 void GroupingContainmentPrivate::restoreGroups()
447 KConfigGroup groupsConfig = q->config(
"Groups");
449 KConfigGroup groupConfig(&groupsConfig, QString::number(group->
id()));
450 KConfigGroup groupInfoConfig(&groupConfig,
"GroupInformation");
452 if (groupInfoConfig.isValid() && groupInfoConfig.exists()) {
453 int groupId = groupInfoConfig.readEntry(
"Group", -1);
458 if ((
int)g->
id() == groupId) {
464 QTransform t = group->transform();
466 group->setTransform(t);
468 groupInfoConfig.deleteGroup();
469 manageGroup(group, group->pos());
472 }
else if (group != mainGroup) {
473 manageGroup(group, group->pos());
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");
482 if (groupConfig.isValid() && groupConfig.exists()) {
483 int groupId = groupConfig.readEntry(
"Group", -1);
488 if ((
int)g->
id() == groupId) {
494 QTransform t = applet->transform();
496 applet->setTransform(t);
498 groupConfig.deleteGroup();
499 manageApplet(applet, applet->pos());
503 manageApplet(applet, applet->pos());
508 group->d->restoreChildren();
518 emit q->configNeedsSaving();
522 void GroupingContainmentPrivate::prepareWidgetToMove()
524 q->raise(widgetToBeSetMoving);
525 q->raise(movementHelperWidget);
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);
547 interestingGroup = widgetToBeSetMoving->property(
"group").value<
AbstractGroup *>();
548 movingWidget = widgetToBeSetMoving;
550 if (q->immutability() != Plasma::Mutable) {
551 onWidgetMoved(widgetToBeSetMoving);
554 widgetToBeSetMoving = 0;
560 : Containment(parent, args),
561 d(new GroupingContainmentPrivate(this))
563 setContainmentType(Plasma::Containment::NoContainmentType);
574 Plasma::Containment::init();
576 d->newGroupAction->setVisible(immutability() == Plasma::Mutable);
577 addToolBoxAction(d->newGroupAction);
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)));
594 return d->createGroup(plugin, pos,
id);
603 kDebug()<<
"adding group"<<group->
id();
604 connect(
this, SIGNAL(immutabilityChanged(Plasma::ImmutabilityType)),
605 group, SLOT(setImmutability(Plasma::ImmutabilityType)));
608 connect(group, SIGNAL(appletRemovedFromGroup(Plasma::Applet*,
AbstractGroup*)),
609 this, SLOT(onAppletRemovedFromGroup(Plasma::Applet*,
AbstractGroup*)));
612 connect(group, SIGNAL(configNeedsSaving()),
this, SIGNAL(configNeedsSaving()));
617 int z = group->zValue();
618 if (GroupingContainmentPrivate::s_maxZValue < z) {
619 GroupingContainmentPrivate::s_maxZValue = z;
624 if (!d->loading && !pos.isNull()) {
625 d->manageGroup(group, pos);
626 Plasma::Animation *anim = Plasma::Animator::create(Plasma::Animator::AppearAnimation);
628 anim->setTargetWidget(group);
629 anim->setDirection(QAbstractAnimation::Backward);
630 anim->start(QAbstractAnimation::DeleteWhenStopped);
634 group->installEventFilter(
this);
635 group->installSceneEventFilter(
this);
645 QList<QAction *> list;
646 list << d->newGroupAction << d->separator << d->configureGroupAction << d->deleteGroupAction;
652 if (!name.isEmpty()) {
653 d->mainGroupPlugin = name;
663 d->mainGroup = group;
668 config().writeEntry(
"mainGroup", group->
id());
669 emit configNeedsSaving();
675 d->layout =
new QGraphicsLinearLayout(
this);
676 d->layout->setContentsMargins(0, 0, 0, 0);
678 d->layout->addItem(d->mainGroup);
688 if (d->blockSceneEventFilter) {
692 Plasma::Applet *applet = qgraphicsitem_cast<Plasma::Applet *>(watched);
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);
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()));
729 foreach (
Handle *handle, d->handles) {
731 if (w != widget && handle) {
732 handle->
setHoverPos(w->mapFromScene(he->scenePos()));
742 if (immutability() != Plasma::Mutable) {
747 Plasma::Applet *applet = qobject_cast<Plasma::Applet *>(obj);
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;
765 case QEvent::GraphicsSceneMove: {
766 if (d->movingWidget != widget && widget == d->interestingWidget) {
769 if (widget == d->movingWidget) {
773 QPointF p = mapFromScene(widget->scenePos());
774 QRectF rect(widget->contentsRect());
775 QList<AbstractGroup *> groups = d->groupsAt(p + rect.center(), widget);
777 if (d->interestingGroup && d->interestingGroup.data() != parentGroup) {
778 d->interestingGroup.data()->showDropZone(QPointF());
779 d->interestingGroup.clear();
781 QPointF pos = mapToItem(parentGroup, p + rect.topLeft());
782 if (pos.x() < rect.left()) {
783 pos.setX(rect.left());
785 if (pos.y() < rect.top()) {
786 pos.setY(rect.top());
789 d->interestingGroup = parentGroup;
798 case QEvent::GraphicsSceneDragMove: {
799 QGraphicsSceneDragDropEvent *e =
static_cast<QGraphicsSceneDragDropEvent *
>(event);
801 const QMimeData *mime = e->mimeData();
811 QPointF pos(mapFromScene(e->scenePos()));
812 QList<AbstractGroup *> groups = d->groupsAt(pos);
814 if (d->interestingGroup && d->interestingGroup.data() != group) {
815 d->interestingGroup.data()->showDropZone(QPointF());
816 d->interestingGroup.clear();
819 d->interestingGroup = group;
829 case QEvent::GraphicsSceneDrop: {
831 QGraphicsSceneDragDropEvent *e =
static_cast<QGraphicsSceneDragDropEvent *
>(event);
832 e->setPos(mapFromScene(e->scenePos()));
835 if (d->interestingGroup) {
836 d->interestingGroup.data()->showDropZone(QPointF());
837 d->interestingGroup.clear();
842 case QEvent::GraphicsSceneMouseRelease:
843 if (d->movingWidget) {
844 d->onWidgetMoved(widget);
846 d->interestingWidget = 0;
855 return Plasma::Containment::eventFilter(obj, event);
860 Plasma::Containment::saveContents(group);
862 KConfigGroup groupsConfig(&group,
"Groups");
864 g->
save(*(g->d->mainConfigGroup()));
871 Plasma::Containment::restoreContents(group);
873 d->mainGroupId = group.readEntry(
"mainGroup", 0);
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());
881 AbstractGroup *group = d->createGroup(plugin, QPointF(),
id);
887 if (d->mainGroupId != 0 && !d->mainGroup) {
889 if (group->
id() == d->mainGroupId) {
895 if (!d->mainGroupPlugin.isEmpty() && !d->mainGroup) {
896 AbstractGroup *group = d->createGroup(d->mainGroupPlugin, QPointF(), 0,
true);
899 }
else if (d->mainGroup && d->mainGroupPlugin != d->mainGroup->pluginName()) {
902 AbstractGroup *group = d->createGroup(d->mainGroupPlugin, QPointF(), 0,
true);
908 old->d->destroyGroup();
911 kWarning()<<
"You have not set a Main Group! This will really cause troubles! You *must* set a Main Group!";
917 QTimer::singleShot(0,
this, SLOT(restoreGroups()));
924 d->deleteGroupAction->setVisible(
false);
925 d->configureGroupAction->setVisible(
false);
926 d->lastClick =
event->pos();
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",
943 d->configureGroupAction->setVisible(
true);
944 d->configureGroupAction->setText(i18n(
"Configure this %1",
946 d->configureGroupAction->setData(group->
id());
952 Plasma::Containment::contextMenuEvent(event);
957 const QMimeData *mime =
event->mimeData();
962 d->createGroup(name, event->pos(), 0);
965 Plasma::Containment::dropEvent(event);
971 d->interestingWidget = 0;
973 if (d->movingWidget) {
974 if (d->movingWidget == widget) {
977 d->onWidgetMoved(d->movingWidget);
985 d->widgetToBeSetMoving = widget;
988 QTimer::singleShot(0,
this, SLOT(prepareWidgetToMove()));
993 return d->movingWidget;
998 widget->setZValue(++GroupingContainmentPrivate::s_maxZValue);
1001 #include "groupingcontainment.moc"
AbstractGroup * mainGroup() const
Returns the Main Group of this Containment.
GroupingContainment(QObject *parent, const QVariantList &args)
Default constructor.
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.
void setImmutability(Plasma::ImmutabilityType immutability)
Sets the immutability type for this Group (not immutable, user immutable or system immutable) ...
void raise(QGraphicsWidget *widget)
Raises a widget above all the other Applets or Groups.
virtual void saveContents(KConfigGroup &group) const
Reimplemented from Plasma::Containment.
virtual void showConfigurationInterface()
Lets the user interact with the Group options.
QSet< Plasma::FormFactor > formFactors() const
void addApplet(Plasma::Applet *applet, bool layoutApplet=true)
Adds an Applet to this Group.
virtual void detachWidget()
void init()
Reimplemented from Plasma::Applet.
virtual void setHoverPos(const QPointF &hoverPos)
void setIsMainGroup()
Tells this Group it is a Main Group, causing it to: not paint a background; not be movable; not have ...
Plasma::ImmutabilityType immutability() const
Returns the type of immutability of this Group.
void setMovingWidget(QGraphicsWidget *widget)
Call this function when an Applet or a Group is being moved by the user.
static AbstractGroup * load(const QString &name, QGraphicsItem *parent=0)
Creates a new Group.
void groupAdded(AbstractGroup *group, const QPointF &pos)
Emitted when a new Group is added to this Containment.
static GroupInfo groupInfo(const QString &name)
virtual void constraintsEvent(Plasma::Constraints constraints)
Reimplemented from Plasma::Applet.
virtual QString pluginName() const =0
Returns the plugin name for the Group.
virtual bool eventFilter(QObject *obj, QEvent *event)
Reimplemented from QObject.
virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event)
Reimplemented from QGraphicsItem.
virtual ~GroupingContainment()
Default destructor.
virtual Handle * createHandleForChild(QGraphicsWidget *child)
Returns an handle for a child of this Group.
AbstractGroup * parentGroup() const
Returns the Group that contains this one, 0 if there is no one.
QGraphicsWidget * movingWidget() const
Returns the widget that is currently being moved by the user, or 0 if there is not any...
QList< QAction * > contextualActions()
Reimplemented from Plasma::Applet.
virtual void releaseChild(QGraphicsWidget *child)
Called when an Applet or a Group starts to be moved by the user.
QGraphicsWidget * widget() const
QList< AbstractGroup * > groups() const
Returns a list of all the Groups contained in this Containment.
void setMainGroup(AbstractGroup *group)
Sets a Main Group for this Containment.
virtual void setLocation(const Plasma::Location &loc)
static ExplorerWindow * instance()
void useMainGroup(const QString &type)
Tells the Containment to use a Main Group of the given type.
static QString mimeType()
virtual void layoutMainGroup()
Lays out the Main Group.
virtual void saveChildren() const
Calls saveChildGroupInfo for every child.
virtual void restoreContents(KConfigGroup &group)
Reimplemented from Plasma::Containment.
virtual bool showDropZone(const QPointF &pos)
Shows a visual clue for drag and drop The default implementation does nothing, reimplement it in grou...
KConfigGroup config() const
Returns the KConfigGroup to access the Group configuration.
virtual void init()
Method called a little after the constructor.
bool hasConfigurationInterface() const
Returns true if this Group provides a GUI configuration.
The base Containment class.
virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
Reimplemented from QGraphicsItem.
virtual void dropEvent(QGraphicsSceneDragDropEvent *event)
Reimplemented from QGraphicsItem.
virtual void restore(KConfigGroup &group)
Restore the state information about this Group.
void addSubGroup(AbstractGroup *group, bool layoutGroup=true)
Adds a Group to this Group.
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.
void destroy()
Destroy this Groups and its children, deleting the configurations too.
virtual void setContainment(Plasma::Containment *containment)
QPoint positionForPanelGeometry(const QRect &panelGeom) const
virtual void save(KConfigGroup &group) const
Saves state information about this Group.
void updateConstraints(Plasma::Constraints constraints=Plasma::AllConstraints)
Called when any of the geometry constraints have been updated.