Plasma
extendergroup.cpp
Go to the documentation of this file.
00001 /* 00002 * Copyright 2009 by Rob Scheepmaker <r.scheepmaker@student.utwente.nl> 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, 00017 * Boston, MA 02110-1301 USA 00018 */ 00019 00020 #include "extendergroup.h" 00021 00022 #include <QAction> 00023 #include <QApplication> 00024 #include <QString> 00025 #include <QList> 00026 #include <QTimer> 00027 #include <QtGui/QGraphicsWidget> 00028 #include <QtGui/QGraphicsLinearLayout> 00029 #include <QtGui/QGraphicsSceneDragDropEvent> 00030 00031 #include "applet.h" 00032 #include "extender.h" 00033 #include "extenderitem.h" 00034 #include "theme.h" 00035 #include "widgets/scrollwidget.h" 00036 00037 #include "private/extender_p.h" 00038 #include "private/extendergroup_p.h" 00039 #include "private/extenderitemmimedata_p.h" 00040 00041 namespace Plasma 00042 { 00043 00044 ExtenderGroup::ExtenderGroup(Extender *parent, uint groupId) 00045 : ExtenderItem(parent, groupId), 00046 d(new ExtenderGroupPrivate(this)) 00047 { 00048 connect(extender(), SIGNAL(itemAttached(Plasma::ExtenderItem*)), 00049 this, SLOT(addItemToGroup(Plasma::ExtenderItem*))); 00050 connect(extender(), SIGNAL(itemDetached(Plasma::ExtenderItem*)), 00051 this, SLOT(removeItemFromGroup(Plasma::ExtenderItem*))); 00052 00053 //this isn't actually connected to anything, we will just check if it's running or not 00054 d->resizeTimer = new QTimer(this); 00055 d->resizeTimer->setSingleShot(true); 00056 00057 config().writeEntry("isGroup", true); 00058 00059 setAcceptDrops(true); 00060 00061 QGraphicsLinearLayout *lay = static_cast<QGraphicsLinearLayout *>(layout()); 00062 d->childsWidget = new QGraphicsWidget(this); 00063 d->childsWidget->installEventFilter(this); 00064 d->layout = new QGraphicsLinearLayout(Qt::Vertical, d->childsWidget); 00065 d->childsWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); 00066 lay->addItem(d->childsWidget); 00067 00068 QAction *expand = new QAction(this); 00069 expand->setVisible(false); 00070 expand->setToolTip(i18n("Show this group.")); 00071 connect(expand, SIGNAL(triggered()), this, SLOT(expandGroup())); 00072 addAction("expand", expand); 00073 00074 QAction *collapse = new QAction(this); 00075 collapse->setVisible(true); 00076 collapse->setToolTip(i18n("Hide this group.")); 00077 connect(collapse, SIGNAL(triggered()), this, SLOT(collapseGroup())); 00078 addAction("collapse", collapse); 00079 00080 d->themeChanged(); 00081 00082 QString groupName; 00083 foreach (ExtenderItem *item, extender()->attachedItems()) { 00084 groupName = item->config().readEntry("group", ""); 00085 if (!groupName.isEmpty() && groupName == name()) { 00086 item->setGroup(this); 00087 } 00088 } 00089 00090 if (items().isEmpty() && d->autoHide && !isDetached()) { 00091 extender()->itemRemovedEvent(this); 00092 hide(); 00093 } 00094 00095 if (!config().readEntry("groupCollapsed", true)) { 00096 expandGroup(); 00097 } 00098 00099 connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), 00100 this, SLOT(themeChanged())); 00101 00102 } 00103 00104 ExtenderGroup::~ExtenderGroup() 00105 { 00106 delete d; 00107 } 00108 00109 QList<ExtenderItem*> ExtenderGroup::items() const 00110 { 00111 QList<ExtenderItem*> result; 00112 foreach (ExtenderItem *item, extender()->attachedItems()) { 00113 if (item->group() == this) { 00114 result.append(item); 00115 } 00116 } 00117 00118 return result; 00119 } 00120 00121 bool ExtenderGroup::autoHide() const 00122 { 00123 return d->autoHide; 00124 } 00125 00126 void ExtenderGroup::setAutoHide(bool autoHide) 00127 { 00128 d->autoHide = autoHide; 00129 if (autoHide && items().isEmpty()) { 00130 extender()->itemRemovedEvent(this); 00131 hide(); 00132 } else if (!autoHide && !isVisible()) { 00133 extender()->itemAddedEvent(this); 00134 show(); 00135 } 00136 } 00137 00138 bool ExtenderGroup::isAutoCollapse() const 00139 { 00140 return d->autoCollapse; 00141 } 00142 00143 void ExtenderGroup::setAutoCollapse(bool collapse) 00144 { 00145 d->autoCollapse = collapse; 00146 } 00147 00148 bool ExtenderGroup::isGroupCollapsed() const 00149 { 00150 return d->collapsed; 00151 } 00152 00153 void ExtenderGroup::setGroupCollapsed(bool collapsed) 00154 { 00155 if (collapsed) { 00156 collapseGroup(); 00157 } else { 00158 expandGroup(); 00159 } 00160 } 00161 00162 void ExtenderGroup::expandGroup() 00163 { 00164 if (d->autoCollapse) { 00165 setCollapsed(false); 00166 } 00167 if (d->collapsed == false) { 00168 return; 00169 } 00170 00171 d->collapsed = false; 00172 config().writeEntry("groupCollapsed", d->collapsed); 00173 action("collapse")->setVisible(true); 00174 action("expand")->setVisible(false); 00175 00176 d->childsWidget->show(); 00177 static_cast<QGraphicsLinearLayout *>(layout())->addItem(d->childsWidget); 00178 updateGeometry(); 00179 00180 foreach (ExtenderItem *item, extender()->attachedItems()) { 00181 if (item->group() == this) { 00182 item->show(); 00183 extender()->itemAddedEvent(item); 00184 } 00185 } 00186 00187 //extender()->resize(extender()->effectiveSizeHint(Qt::PreferredSize)); 00188 } 00189 00190 void ExtenderGroup::collapseGroup() 00191 { 00192 if (d->autoCollapse) { 00193 setCollapsed(true); 00194 } 00195 if (d->collapsed == true) { 00196 return; 00197 } 00198 00199 d->collapsed = true; 00200 config().writeEntry("groupCollapsed", d->collapsed); 00201 action("collapse")->setVisible(false); 00202 action("expand")->setVisible(true); 00203 00204 d->childsWidget->hide(); 00205 static_cast<QGraphicsLinearLayout *>(layout())->removeItem(d->childsWidget); 00206 updateGeometry(); 00207 00208 foreach (ExtenderItem *item, extender()->attachedItems()) { 00209 if (item != this && item->group() == this) { 00210 item->hide(); 00211 extender()->itemRemovedEvent(item); 00212 } 00213 } 00214 } 00215 00216 void ExtenderGroup::resizeEvent(QGraphicsSceneResizeEvent *event) 00217 { 00218 ExtenderItem::resizeEvent(event); 00219 } 00220 00221 bool ExtenderGroup::eventFilter(QObject *watched, QEvent *event) 00222 { 00223 if (watched == d->childsWidget && event->type() == QEvent::GraphicsSceneResize) { 00224 static_cast<QGraphicsLayoutItem *>(extender()->d->scrollWidget)->updateGeometry(); 00225 if (!d->resizeTimer->isActive()) { 00226 static_cast<QGraphicsLayoutItem *>(extender())->updateGeometry(); 00227 extender()->d->adjustSize(); 00228 d->resizeTimer->start(0); 00229 } 00230 } 00231 00232 return ExtenderItem::eventFilter(watched, event); 00233 } 00234 00235 void ExtenderGroup::dragEnterEvent(QGraphicsSceneDragDropEvent *event) 00236 { 00237 if (event->mimeData()->hasFormat(ExtenderItemMimeData::mimeType())) { 00238 event->accept(); 00239 00240 dragMoveEvent(event); 00241 } 00242 } 00243 00244 void ExtenderGroup::dragMoveEvent(QGraphicsSceneDragDropEvent *event) 00245 { 00246 if (event->mimeData()->hasFormat(ExtenderItemMimeData::mimeType())) { 00247 const ExtenderItemMimeData *mimeData = 00248 qobject_cast<const ExtenderItemMimeData*>(event->mimeData()); 00249 00250 if (mimeData) { 00251 QPointF pos(event->pos()); 00252 if (d->spacerWidget && d->spacerWidget->geometry().contains(pos)) { 00253 return; 00254 } 00255 00256 //Make sure we remove any spacer that might already be in the layout. 00257 if (d->spacerWidget) { 00258 d->layout->removeItem(d->spacerWidget); 00259 } 00260 00261 int insertIndex = d->insertIndexFromPos(pos); 00262 00263 //Create a widget that functions as spacer, and add that to the layout. 00264 if (!d->spacerWidget) { 00265 Spacer *widget = new Spacer(this); 00266 ExtenderItem *item = mimeData->extenderItem(); 00267 qreal left, top, right, bottom; 00268 extender()->d->background->getMargins(left, top, right, bottom); 00269 widget->setMargins(left, 4, right, 4); 00270 00271 widget->setMinimumSize(item->minimumSize()); 00272 widget->setPreferredSize(item->preferredSize()); 00273 widget->setMaximumSize(item->maximumSize()); 00274 widget->setSizePolicy(item->sizePolicy()); 00275 d->spacerWidget = widget; 00276 } 00277 d->layout->insertItem(insertIndex, d->spacerWidget); 00278 00279 extender()->d->setPositionFromDragPosition(event->scenePos()); 00280 } 00281 } 00282 } 00283 00284 void ExtenderGroup::dropEvent(QGraphicsSceneDragDropEvent *event) 00285 { 00286 if (event->mimeData()->hasFormat(ExtenderItemMimeData::mimeType())) { 00287 const ExtenderItemMimeData *mimeData = 00288 qobject_cast<const ExtenderItemMimeData*>(event->mimeData()); 00289 00290 if (mimeData) { 00291 mimeData->extenderItem()->setGroup(this, event->pos()); 00292 QApplication::restoreOverrideCursor(); 00293 d->layout->removeItem(d->spacerWidget); 00294 d->spacerWidget->deleteLater(); 00295 d->spacerWidget = 0; 00296 } 00297 } 00298 } 00299 00300 void ExtenderGroup::dragLeaveEvent(QGraphicsSceneDragDropEvent *event) 00301 { 00302 if (event->mimeData()->hasFormat(ExtenderItemMimeData::mimeType())) { 00303 if (d->spacerWidget) { 00304 d->layout->removeItem(d->spacerWidget); 00305 d->spacerWidget->deleteLater(); 00306 d->spacerWidget = 0; 00307 } 00308 } 00309 } 00310 00311 ExtenderGroupPrivate::ExtenderGroupPrivate(ExtenderGroup *group) 00312 : q(group), 00313 spacerWidget(0), 00314 svg(new Svg(group)), 00315 collapsed(false), 00316 autoHide(true), 00317 autoCollapse(false) 00318 { 00319 } 00320 00321 ExtenderGroupPrivate::~ExtenderGroupPrivate() 00322 { 00323 } 00324 00325 void ExtenderGroupPrivate::addItemToGroup(Plasma::ExtenderItem *item, const QPointF &pos) 00326 { 00327 if (item->group() == q) { 00328 item->setParentItem(childsWidget); 00329 item->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); 00330 layout->insertItem(insertIndexFromPos(pos), item); 00331 layout->activate(); 00332 00333 if (!q->isVisible() && !q->items().isEmpty()) { 00334 q->extender()->itemAddedEvent(q); 00335 q->show(); 00336 } 00337 childsWidget->setVisible(!q->isGroupCollapsed()); 00338 00339 if (!q->isGroupCollapsed()) { 00340 layout->updateGeometry(); 00341 static_cast<QGraphicsLayoutItem *>(q)->updateGeometry(); 00342 static_cast<QGraphicsLayoutItem *>(childsWidget)->updateGeometry(); 00343 static_cast<QGraphicsLayoutItem *>(q->extender()->d->scrollWidget)->updateGeometry(); 00344 } 00345 00346 q->extender()->d->adjustSize(); 00347 } 00348 } 00349 00350 void ExtenderGroupPrivate::removeItemFromGroup(Plasma::ExtenderItem *item) 00351 { 00352 if (item->group() == q) { 00353 if (q->items().isEmpty() && autoHide && !q->isDetached()) { 00354 q->extender()->itemRemovedEvent(q); 00355 q->hide(); 00356 } 00357 layout->removeItem(item); 00358 item->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); 00359 00360 layout->updateGeometry(); 00361 static_cast<QGraphicsLayoutItem *>(q)->updateGeometry(); 00362 static_cast<QGraphicsLayoutItem *>(childsWidget)->updateGeometry(); 00363 static_cast<QGraphicsLayoutItem *>(q->extender()->d->scrollWidget)->updateGeometry(); 00364 00365 q->extender()->d->adjustSize(); 00366 } 00367 } 00368 00369 void ExtenderGroupPrivate::themeChanged() 00370 { 00371 svg->setImagePath("widgets/configuration-icons"); 00372 svg->resize(); 00373 00374 q->action("expand")->setIcon(QIcon(svg->pixmap("restore"))); 00375 q->action("collapse")->setIcon(QIcon(svg->pixmap("collapse"))); 00376 } 00377 00378 int ExtenderGroupPrivate::insertIndexFromPos(const QPointF &pos) const 00379 { 00380 int insertIndex = -1; 00381 00382 //XXX: duplicated from panel 00383 if (pos != QPointF(-1, -1)) { 00384 for (int i = 0; i < layout->count(); ++i) { 00385 QRectF siblingGeometry = layout->itemAt(i)->geometry(); 00386 qreal middle = (siblingGeometry.top() + siblingGeometry.bottom()) / 2.0; 00387 if (pos.y() < middle) { 00388 insertIndex = i; 00389 break; 00390 } else if (pos.y() <= siblingGeometry.bottom()) { 00391 insertIndex = i + 1; 00392 break; 00393 } 00394 } 00395 } 00396 00397 return insertIndex; 00398 } 00399 00400 } // Plasma namespace 00401 00402 #include "extendergroup.moc"
KDE 4.6 API Reference