diff --git a/CMakeLists.txt b/CMakeLists.txt index f66ef94e1..79437fe9e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,6 +66,7 @@ set(plasma_LIB_SRCS delegate.cpp dialog.cpp extender.cpp + extendergroup.cpp extenderitem.cpp paintutils.cpp framesvg.cpp @@ -205,6 +206,7 @@ set(plasma_LIB_INCLUDES delegate.h dialog.h extender.h + extendergroup.h extenderitem.h paintutils.h framesvg.h diff --git a/applet.h b/applet.h index ede9f7394..f92382fa6 100644 --- a/applet.h +++ b/applet.h @@ -937,6 +937,8 @@ class PLASMA_EXPORT Applet : public QGraphicsWidget friend class PopupAppletPrivate; friend class Extender; + friend class ExtenderGroup; + friend class ExtenderGroupPrivate; friend class ExtenderPrivate; friend class ExtenderItem; }; diff --git a/extender.cpp b/extender.cpp index 0e1f563d6..43cf1e6a5 100644 --- a/extender.cpp +++ b/extender.cpp @@ -28,6 +28,7 @@ #include "applet.h" #include "containment.h" #include "corona.h" +#include "extendergroup.h" #include "extenderitem.h" #include "framesvg.h" #include "paintutils.h" @@ -206,6 +207,17 @@ Extender::Appearance Extender::appearance() const return d->appearance; } +QList Extender::groups() const +{ + QList result; + foreach (ExtenderItem *item, attachedItems()) { + if (item->isGroup() && !result.contains(item->group())) { + result.append(item->group()); + } + } + return result; +} + void Extender::saveState() { foreach (ExtenderItem *item, attachedItems()) { @@ -540,7 +552,12 @@ void ExtenderPrivate::loadExtenderItems() kDebug() << "sourceApplet is null? appletName = " << appletName; kDebug() << " extenderItemId = " << extenderItemId; } else { - ExtenderItem *item = new ExtenderItem(q, extenderItemId.toInt()); + ExtenderItem *item; + if (dg.readEntry("isGroup", false)) { + item = new ExtenderGroup(q, extenderItemId.toInt()); + } else { + item = new ExtenderItem(q, extenderItemId.toInt()); + } sourceApplet->initExtenderItem(item); if (temporarySourceApplet) { @@ -581,6 +598,16 @@ void ExtenderPrivate::updateEmptyExtenderLabel() } } +ExtenderGroup *ExtenderPrivate::findGroup(const QString &name) const +{ + foreach (ExtenderItem *item, q->attachedItems()) { + if (item->isGroup() && item->name() == name) { + return qobject_cast(item); + } + } + return 0; +} + } // Plasma namespace #include "extender.moc" diff --git a/extender.h b/extender.h index 0287c7ae0..5c0900fe4 100644 --- a/extender.h +++ b/extender.h @@ -27,6 +27,8 @@ namespace Plasma { + +class ExtenderGroup; class ExtenderPrivate; class ExtenderItem; class Applet; @@ -155,10 +157,16 @@ class PLASMA_EXPORT Extender : public QGraphicsWidget void setAppearance(Appearance appearance); /** - * @return the current way of rendering extender items that is used. + * @returns the current way of rendering extender items that is used. */ Appearance appearance() const; + /** + * @returns a list of groups that are contained in this extender. + * @since 4.3 + */ + QList groups() const; + protected: /** * Get's called after an item has been added to this extender. The bookkeeping has already @@ -168,7 +176,7 @@ class PLASMA_EXPORT Extender : public QGraphicsWidget * @param item The item that has just been added. * @param pos The location the item has been dropped in local coordinates. */ - virtual void itemAddedEvent(ExtenderItem *item, const QPointF &pos); + virtual void itemAddedEvent(ExtenderItem *item, const QPointF &pos = QPointF(-1, -1)); /** * Get's called after an item has been removed from this extender. All bookkeeping has @@ -271,6 +279,8 @@ class PLASMA_EXPORT Extender : public QGraphicsWidget ExtenderPrivate *const d; friend class ExtenderPrivate; + friend class ExtenderGroup; + friend class ExtenderGroupPrivate; friend class ExtenderItem; friend class ExtenderItemPrivate; //dialog needs access to the extender's applet location. diff --git a/extendergroup.cpp b/extendergroup.cpp new file mode 100644 index 000000000..1920adb2b --- /dev/null +++ b/extendergroup.cpp @@ -0,0 +1,177 @@ +/* + * Copyright 2009 by Rob Scheepmaker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include "applet.h" +#include "extender.h" +#include "extendergroup.h" +#include "extenderitem.h" + +namespace Plasma +{ + +class ExtenderGroupPrivate +{ + public: + ExtenderGroupPrivate(ExtenderGroup *group) + : collapsed(true), + hideIfEmpty(true) + { + q = group; + } + + ~ExtenderGroupPrivate() + { + } + + void addItemToGroup(Plasma::ExtenderItem *item) + { + if (item->group() == q) { + if (collapsed) { + q->extender()->itemRemovedEvent(item); + item->hide(); + } + if (!q->isVisible()) { + q->extender()->itemAddedEvent(q); + q->show(); + } + } + } + + void removeItemFromGroup(Plasma::ExtenderItem *item) + { + if (item->group() == q) { + if (q->items().isEmpty()) { + q->extender()->itemRemovedEvent(q); + q->hide(); + } + } + } + + ExtenderGroup *q; + bool collapsed; + bool hideIfEmpty; +}; + +class ExtenderItem; +class Applet; + +ExtenderGroup::ExtenderGroup(Extender *parent, uint groupId) + : ExtenderItem(parent, groupId), + d(new ExtenderGroupPrivate(this)) +{ + connect(extender(), SIGNAL(itemAttached(Plasma::ExtenderItem*)), + this, SLOT(addItemToGroup(Plasma::ExtenderItem*))); + connect(extender(), SIGNAL(itemDetached(Plasma::ExtenderItem*)), + this, SLOT(removeItemFromGroup(Plasma::ExtenderItem*))); + + config().writeEntry("isGroup", true); + + QAction *expand = new QAction(this); + expand->setIcon(KIcon("arrow-up")); + expand->setVisible(true); + expand->setToolTip(i18n("Show this group.")); + connect(expand, SIGNAL(triggered()), this, SLOT(expandGroup())); + addAction("expand", expand); + + QAction *collapse = new QAction(this); + collapse->setIcon(KIcon("arrow-down")); + collapse->setVisible(false); + collapse->setToolTip(i18n("Hide this group.")); + connect(collapse, SIGNAL(triggered()), this, SLOT(collapseGroup())); + addAction("collapse", collapse); + + QString groupName; + foreach (ExtenderItem *item, extender()->attachedItems()) { + groupName = item->config().readEntry("group", ""); + if (groupName != "" && groupName == name()) { + item->setGroup(this); + } + } + + if (items().isEmpty()) { + hide(); + extender()->itemRemovedEvent(this); + } +} + +ExtenderGroup::~ExtenderGroup() +{ + delete d; +} + +QList ExtenderGroup::items() const +{ + QList result; + foreach (ExtenderItem *item, extender()->attachedItems()) { + if (item->group() == this) { + result.append(item); + } + } + + return result; +} + +bool ExtenderGroup::hideIfEmpty() const +{ + return d->hideIfEmpty; +} + +void ExtenderGroup::setHideIfEmpty(bool hideIfEmpty) +{ + d->hideIfEmpty = hideIfEmpty; + if (hideIfEmpty && items().isEmpty()) { + hide(); + extender()->itemRemovedEvent(this); + } +} + +void ExtenderGroup::expandGroup() +{ + d->collapsed = false; + action("collapse")->setVisible(true); + action("expand")->setVisible(false); + foreach (ExtenderItem *item, extender()->attachedItems()) { + if (item->group() == this) { + item->show(); + extender()->itemAddedEvent(item); + } + } +} + +void ExtenderGroup::collapseGroup() +{ + d->collapsed = true; + action("collapse")->setVisible(false); + action("expand")->setVisible(true); + foreach (ExtenderItem *item, extender()->attachedItems()) { + if (item != this && item->group() == this) { + item->hide(); + extender()->itemRemovedEvent(item); + } + } +} + +} // Plasma namespace + +#include "extendergroup.moc" diff --git a/extendergroup.h b/extendergroup.h new file mode 100644 index 000000000..55d9e5a98 --- /dev/null +++ b/extendergroup.h @@ -0,0 +1,100 @@ +/* + * Copyright 2009 by Rob Scheepmaker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef PLASMA_EXTENDERGROUP_H +#define PLASMA_EXTENDERGROUP_H + +#include +#include + +#include "extenderitem.h" + +#include "plasma/plasma_export.h" + +namespace Plasma +{ + +class ExtenderGroupPrivate; +class ExtenderItem; +class Applet; + +/** + * @class ExtenderGroup plasma/extendergroup.h + * + * @short Allows for grouping of extender items. + * + * To be able to group multiple items together, you'll need to instantiate an ExtenderGroup, and + * call setGroup() on all extender items you wish to add to this group. + * This ExtenderGroup is just the same as any other ExtenderItem, except for the expand group and + * collapse group buttons it provides, and the fact that it will automatically hide itself if no + * other items belong to this group and hideIfEmpty is set to true. + * + * @since 4.3 + */ +class PLASMA_EXPORT ExtenderGroup : public ExtenderItem +{ + Q_OBJECT + Q_PROPERTY(bool hideIfEmpty READ hideIfEmpty WRITE setHideIfEmpty) + + public: + /** + * Creates a group. + * @param applet The applet this group is part of. Null is not allowed here. + */ + explicit ExtenderGroup(Extender *parent, uint groupId = 0); + + ~ExtenderGroup(); + + /** + * @return a list of items that belong to this group. + */ + QList items() const; + + /** + * @return whether or not this item hides itself if no other items belong to this group. + */ + bool hideIfEmpty() const; + + /** + * @param hideIfEmpty whether or not this item hides itself if no other items belong to this group. + */ + void setHideIfEmpty(bool hideIfEmpty); + + public Q_SLOTS: + /** + * Expands this group to show all ExtenderItems that are contained in this group. + */ + void expandGroup(); + + /** + * Collapses this group to hide all ExtenderItems that are contained in this group, and + * shows the summary item. + */ + void collapseGroup(); + + private: + ExtenderGroupPrivate * const d; + + Q_PRIVATE_SLOT(d, void addItemToGroup(Plasma::ExtenderItem *item)) + Q_PRIVATE_SLOT(d, void removeItemFromGroup(Plasma::ExtenderItem *item)) +}; +} // Plasma namespace + +#endif //PLASMA_EXTENDER_H + diff --git a/extenderitem.cpp b/extenderitem.cpp index 9bf19ddec..af31cf67f 100644 --- a/extenderitem.cpp +++ b/extenderitem.cpp @@ -40,6 +40,7 @@ #include "corona.h" #include "dialog.h" #include "extender.h" +#include "extendergroup.h" #include "framesvg.h" #include "popupapplet.h" #include "theme.h" @@ -103,6 +104,10 @@ ExtenderItem::ExtenderItem(Extender *hostExtender, uint extenderItemId) } d->collapseIcon = new IconWidget(KIcon(iconName), "", this); + //Find the group if it's already there. + QString groupName = dg.readEntry("group", ""); + d->group = hostExtender->d->findGroup(groupName); + //Find the sourceapplet. Corona *corona = hostExtender->d->applet->containment()->corona(); foreach (Containment *containment, corona->containments()) { @@ -277,6 +282,22 @@ Extender *ExtenderItem::extender() const return d->extender; } +void ExtenderItem::setGroup(ExtenderGroup *group) +{ + d->group = group; + config().writeEntry("group", group->name()); +} + +ExtenderGroup *ExtenderItem::group() const +{ + return d->group; +} + +bool ExtenderItem::isGroup() const +{ + return (config().readEntry("isGroup", false)); +} + bool ExtenderItem::isCollapsed() const { return d->collapsed; @@ -379,6 +400,7 @@ void ExtenderItem::destroy() d->hostApplet()->config("ExtenderItems").deleteGroup(QString::number(d->extenderItemId)); d->extender->d->removeExtenderItem(this); + emit d->extender->itemDetached(this); deleteLater(); } @@ -608,6 +630,7 @@ ExtenderItemPrivate::ExtenderItemPrivate(ExtenderItem *extenderItem, Extender *h toolbox(0), extender(hostExtender), sourceApplet(0), + group(0), dragger(new FrameSvg(extenderItem)), background(new FrameSvg(extenderItem)), collapseIcon(0), diff --git a/extenderitem.h b/extenderitem.h index 93b22e33c..12b047b34 100644 --- a/extenderitem.h +++ b/extenderitem.h @@ -32,6 +32,7 @@ namespace Plasma class Applet; class Extender; +class ExtenderGroup; class ExtenderItemPrivate; /** @@ -171,6 +172,24 @@ class PLASMA_EXPORT ExtenderItem : public QGraphicsWidget */ Extender *extender() const; + /** + * @param group the group you want this item to belong to. + * @since 4.3 + */ + void setGroup(ExtenderGroup *group); + + /** + * @returns the group this item belongs to. + * @since 4.3 + */ + ExtenderGroup *group() const; + + /** + * @returns whether or not this is an ExtenderGroup. + * @since 4.3 + */ + bool isGroup() const; + /** * @param time (in ms) before this extender item destroys itself unless it is detached, * in which case this extender stays around. 0 means forever and is the default. diff --git a/private/extender_p.h b/private/extender_p.h index ef7ea35d3..02a85d3de 100644 --- a/private/extender_p.h +++ b/private/extender_p.h @@ -34,6 +34,7 @@ namespace Plasma class Applet; class Extender; +class ExtenderGroup; class ExtenderItem; class Label; class Spacer; @@ -51,6 +52,7 @@ class ExtenderPrivate void loadExtenderItems(); void updateBorders(); void updateEmptyExtenderLabel(); + ExtenderGroup *findGroup(const QString &name) const; Extender *q; diff --git a/private/extenderitem_p.h b/private/extenderitem_p.h index 008ed2995..f22b421f0 100644 --- a/private/extenderitem_p.h +++ b/private/extenderitem_p.h @@ -34,6 +34,7 @@ class QTimer; namespace Plasma { class Applet; + class ExtenderGroup; class ExtenderItem; class Extender; class IconWidget; @@ -65,6 +66,7 @@ class ExtenderItemPrivate Extender *extender; Applet *sourceApplet; + ExtenderGroup *group; KConfigGroup config;