From 7f624f85d937f2cdc1cb526f4b76443cfef4eeab Mon Sep 17 00:00:00 2001 From: Dan Meltzer Date: Fri, 29 Feb 2008 17:50:57 +0000 Subject: [PATCH] Revert one large git mess svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=780657 --- CMakeLists.txt | 13 +- applet.cpp | 86 +++-- applet.h | 7 +- containment.cpp | 128 ++----- containment.h | 7 +- corona.cpp | 21 +- corona.h | 5 - layouts/borderlayout.cpp | 94 ++--- layouts/borderlayout.h | 28 +- layouts/boxlayout.cpp | 581 ++++++++++++++++++++++++++++++ layouts/boxlayout.h | 127 +++++++ layouts/fliplayout.h | 5 +- layouts/flowlayout.cpp | 125 +++---- layouts/flowlayout.h | 27 +- layouts/freelayout.cpp | 79 ++-- layouts/freelayout.h | 23 +- layouts/layout.cpp | 212 +++++++++++ layouts/layout.h | 185 ++++++++++ layouts/layoutitem.cpp | 251 +++++++++++++ layouts/layoutitem.h | 223 ++++++++++++ layouts/nodelayout.cpp | 57 +-- layouts/nodelayout.h | 28 +- uiloader.cpp | 10 +- uiloader.h | 6 +- widgets/icon.cpp | 10 - widgets/icon.h | 1 - widgets/label.cpp | 8 +- widgets/label.h | 7 +- widgets/lineedit.cpp | 14 +- widgets/lineedit.h | 8 +- widgets/meter.cpp | 6 +- widgets/meter.h | 4 +- widgets/progressbar.cpp | 2 +- widgets/progressbar.h | 2 +- widgets/pushbutton.cpp | 9 +- widgets/pushbutton.h | 3 +- widgets/rectangle.cpp | 6 +- widgets/rectangle.h | 2 + widgets/signalplotter.cpp | 7 +- widgets/signalplotter.h | 2 + widgets/tests/testLayouts.cpp | 8 +- widgets/tests/testProgressBar.cpp | 7 +- widgets/widget.cpp | 220 ++++++++++- widgets/widget.h | 124 ++++++- 44 files changed, 2295 insertions(+), 483 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5258128ea..0dc6a0a9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,12 +35,15 @@ set(plasma_LIB_SRCS dataengine.cpp dataenginemanager.cpp dialog.cpp + layouts/boxlayout.cpp layouts/borderlayout.cpp layouts/freelayout.cpp layouts/nodelayout.cpp layouts/flowlayout.cpp layouts/fliplayout.cpp -# layouts/layoutanimator.cpp + layouts/layout.cpp + layouts/layoutanimator.cpp + layouts/layoutitem.cpp packages.cpp phase.cpp plasma.cpp @@ -161,13 +164,17 @@ install(FILES DESTINATION ${INCLUDE_INSTALL_DIR}/plasma/widgets) install(FILES + layouts/boxlayout.h + layouts/vboxlayout.h + layouts/hboxlayout.h layouts/borderlayout.h layouts/freelayout.h layouts/nodelayout.h layouts/flowlayout.h layouts/fliplayout.h -# layouts/layoutanimator.h -# layouts/layoutitem.h + layouts/layout.h + layouts/layoutanimator.h + layouts/layoutitem.h DESTINATION ${INCLUDE_INSTALL_DIR}/plasma/layouts) install(FILES diff --git a/applet.cpp b/applet.cpp index f0c2320d7..5bce23035 100644 --- a/applet.cpp +++ b/applet.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -62,6 +61,7 @@ #include "plasma/theme.h" #include "plasma/view.h" +#include "plasma/layouts/boxlayout.h" #include "plasma/widgets/widget.h" #include "plasma/widgets/lineedit.h" #include "plasma/widgets/pushbutton.h" @@ -331,7 +331,7 @@ Applet::Applet(QGraphicsItem *parent, } Applet::Applet(QObject* parentObject, const QVariantList& args) - : Widget(dynamic_cast(parentObject)), + : Widget(0,parentObject), d(new Private(KService::serviceByStorageId(args.count() > 0 ? args[0].toString() : QString()), args.count() > 1 ? args[1].toInt() : 0)) { @@ -619,13 +619,13 @@ void Applet::setDrawStandardBackground(bool drawBackground) int left, top, right, bottom; d->getBorderSize(left, top, right, bottom); - setContentsMargins(0, 0, right, bottom); + setMargins(0, 0, right, bottom); updateGeometry(); } } else if (d->background) { delete d->background; d->background = 0; - setContentsMargins(0, 0, 0, 0); + setMargins(0, 0, 0, 0); updateGeometry(); } } @@ -653,7 +653,7 @@ void Applet::setFailedToLaunch(bool failed, const QString& reason) if (d->failed == failed) { if (d->failureText) { d->failureText->setHtml(visibleFailureText(reason)); - setGeometry(QRectF(geometry().topLeft(), d->failureText->sizeHint(Qt::PreferredSize))); + setGeometry(QRectF(geometry().topLeft(), d->failureText->sizeHint())); } return; } @@ -667,8 +667,8 @@ void Applet::setFailedToLaunch(bool failed, const QString& reason) if (failed) { setDrawStandardBackground(true); - QGraphicsLinearLayout* failureLayout = new QGraphicsLinearLayout(Qt::Vertical, this); - failureLayout->setContentsMargins(0, 0, 0, 0); + Layout* failureLayout = new BoxLayout(BoxLayout::TopToBottom, this); + failureLayout->setMargins(0, 0, 0, 0); d->failureText = new LineEdit(this); d->failureText->setTextInteractionFlags( Qt::TextSelectableByMouse ); d->failureText->setStyled(false); @@ -680,7 +680,7 @@ void Applet::setFailedToLaunch(bool failed, const QString& reason) Theme::self()->colors()) .brush(QPalette::Normal).color()); failureLayout->addItem(d->failureText); - setGeometry(QRectF(geometry().topLeft(), d->failureText->sizeHint(Qt::PreferredSize))); + setGeometry(QRectF(geometry().topLeft(), d->failureText->sizeHint())); } update(); @@ -704,7 +704,7 @@ void Applet::setNeedsConfiguring(bool needsConfig) if (needsConfig) { setDrawStandardBackground(true); - QGraphicsLinearLayout* layout = new QGraphicsLinearLayout(Qt::Vertical,this); + Layout* layout = new BoxLayout(BoxLayout::TopToBottom,this); PushButton* button = new PushButton(this); button->setText(i18n("Configure...")); connect(button, SIGNAL(clicked()), this, SLOT(performSetupConfig())); @@ -821,7 +821,7 @@ QPainterPath Applet::shape() const return Plasma::roundedRectangle(boundingRect().adjusted(-2, -2, 2, 2), 10); } -QSizeF Applet::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const +QSizeF Applet::sizeHint() const { int left = 0; int right = 0; @@ -836,6 +836,15 @@ QSizeF Applet::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const return contentSizeHint() + QSizeF(left + right, top + bottom); } +Qt::Orientations Applet::expandingDirections() const +{ + if (d->square) { + return 0; + } + + return Widget::expandingDirections(); +} + QList Applet::contextActions() { //kDebug() << "empty context actions"; @@ -943,7 +952,7 @@ Containment* Applet::containment() const } */ - QGraphicsLayoutItem *parent = parentLayoutItem(); + QGraphicsItem *parent = parentItem(); Containment *c = 0; while (parent) { @@ -952,7 +961,7 @@ Containment* Applet::containment() const c = possibleC; break; } - parent = parent->parentLayoutItem(); + parent = parent->parentItem(); } return c; @@ -1010,38 +1019,37 @@ QSizeF Applet::contentSizeHint() const checkingScript = false; QSizeF size; if (layout()) { - size = layout()->effectiveSizeHint(Qt::PreferredSize); + size = layout()->sizeHint(); } else { size = contentSize(); } -//FIXME: This causes infinite recursion in qt code.. maximumContentSize calls -//sizeHint.. which eventually calls contentSizeHint again. -// QSizeF max = maximumContentSize(); -// size = size.boundedTo(max); -// if (d->square) { -// //kDebug() << "SizeHintIn: " << (QObject*)this << size; -// switch (formFactor()) { -// case Plasma::Vertical: -// if (size.width() > max.height()) { -// size.setWidth(max.height()); -// } -// -// size.setHeight(size.width()); -// case Plasma::Horizontal: -// case Plasma::Planar: -// case Plasma::MediaCenter: -// if (size.height() > max.width()) { -// size.setHeight(max.width()); -// } -// -// size.setWidth(size.height()); -// default: -// break; -// } + + QSizeF max = maximumContentSize(); + size = size.boundedTo(max); + if (d->square) { + //kDebug() << "SizeHintIn: " << (QObject*)this << size; + switch (formFactor()) { + case Plasma::Vertical: + if (size.width() > max.height()) { + size.setWidth(max.height()); + } + + size.setHeight(size.width()); + case Plasma::Horizontal: + case Plasma::Planar: + case Plasma::MediaCenter: + if (size.height() > max.width()) { + size.setHeight(max.width()); + } + + size.setWidth(size.height()); + default: + break; + } //kDebug() << "SizeHintOut: " << size; -// return size; -// } + return size; + } return size; } diff --git a/applet.h b/applet.h index c304b2b56..f20012bf0 100644 --- a/applet.h +++ b/applet.h @@ -593,7 +593,12 @@ class PLASMA_EXPORT Applet : public Widget /** * Reimplemented from LayoutItem */ - QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; + QSizeF sizeHint() const; + + /** + * Reimplemented from Plasma::Widget + */ + Qt::Orientations expandingDirections() const; /** * Reimplemented from QGraphicsItem diff --git a/containment.cpp b/containment.cpp index 7ff529777..6475309f4 100644 --- a/containment.cpp +++ b/containment.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -45,6 +44,7 @@ #include "svg.h" #include "layouts/freelayout.h" +#include "layouts/boxlayout.h" namespace Plasma { @@ -74,30 +74,12 @@ public: { if (!toolbox) { toolbox = new DesktopToolbox(q); - toolbox->setPos(toolboxPosition()); + toolbox->setPos(q->geometry().width() - toolbox->boundingRect().width(), 0); } return toolbox; } - QPointF toolboxPosition() - { - qreal yOffset = 0.0; - qreal xOffset = 0.0; - foreach (Containment *c, q->corona()->containments()) { - kDebug() << c->name() << " is at the: " << (Plasma::Location)c->location(); - if (c->location() == TopEdge) { - kDebug() << "Have a containemnt on the top Edge.. moving the item down"; - yOffset += c->geometry().height(); - } else if (c->location() == RightEdge) { - xOffset += c->geometry().width(); - } - } - QPointF ret(q->geometry().width() - toolbox->boundingRect().width() - xOffset, q->geometry().topRight().y() + yOffset); - kDebug() << "Moving to: " << ret; - return ret; - } - Containment *q; FormFactor formFactor; Location location; @@ -366,47 +348,24 @@ void Containment::setFormFactor(FormFactor formFactor) //kDebug() << "switching FF to " << formFactor; d->formFactor = formFactor; + Layout *lay = 0; //note: setting a new layout autodeletes the old one //and creating a layout calls setLayout on the parent switch (d->formFactor) { case Planar: - { - FreeLayout *fLay = new FreeLayout; - fLay->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding,QSizePolicy::DefaultType); - - foreach (Applet* applet, d->applets) { - fLay->addItem(applet); - applet->updateConstraints(Plasma::FormFactorConstraint); - } + lay = new FreeLayout(this); break; - } case Horizontal: - { - QGraphicsLinearLayout *hLay = new QGraphicsLinearLayout(Qt::Horizontal, this); - hLay->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding,QSizePolicy::DefaultType); - hLay->setContentsMargins(0, 0, 0, 0); - hLay->setSpacing(4); - - foreach (Applet* applet, d->applets) { - hLay->addItem(applet); - applet->updateConstraints(Plasma::FormFactorConstraint); - } + lay = new BoxLayout(BoxLayout::LeftToRight, this); + lay->setMargins(0, 0, 0, 0); + lay->setSpacing(4); break; - } case Vertical: - { - QGraphicsLinearLayout *vLay = new QGraphicsLinearLayout(Qt::Vertical, this); - vLay->setContentsMargins(0, 0, 0, 0); - vLay->setSpacing(4); - vLay->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding,QSizePolicy::DefaultType); - - foreach (Applet* applet, d->applets) { - vLay->addItem(applet); - applet->updateConstraints(Plasma::FormFactorConstraint); - } + lay = new BoxLayout(BoxLayout::TopToBottom, this); + lay->setMargins(0, 0, 0, 0); + lay->setSpacing(4); break; - } case MediaCenter: //FIXME: need a layout type here! setLayout(0); //auto-delete @@ -417,6 +376,13 @@ void Containment::setFormFactor(FormFactor formFactor) break; } + if (lay) { + foreach (Applet* applet, d->applets) { + lay->addItem(applet); + applet->updateConstraints(Plasma::FormFactorConstraint); + } + } + updateConstraints(Plasma::FormFactorConstraint); } @@ -481,13 +447,13 @@ Applet* Containment::addApplet(const QString& name, const QVariantList& args, ui addApplet(applet, appletGeometry.topLeft(), delayInit); if (containmentType() != PanelContainment) { -// kDebug() << "adding applet" << applet->name() << "with a default geometry of" << appletGeometry << appletGeometry.isValid(); + //kDebug() << "adding applet" << applet->name() << "with a default geometry of" << appletGeometry << appletGeometry.isValid(); if (appletGeometry.isValid()) { applet->setGeometry(appletGeometry); } else if (appletGeometry.x() != -1 && appletGeometry.y() != -1) { // yes, this means we can't have items start -1, -1 applet->setGeometry(QRectF(appletGeometry.topLeft(), - applet->effectiveSizeHint(Qt::PreferredSize))); + applet->sizeHint())); } else if (geometry().isValid()) { applet->setGeometry(geometryForApplet(applet)); } @@ -538,15 +504,14 @@ void Containment::addApplet(Applet *applet, const QPointF &pos, bool delayInit) KConfigGroup oldConfig = applet->config(); applet->resetConfigurationObject(); currentContainment->d->applets.removeAll(applet); + addChild(applet); + // now move the old config to the new location KConfigGroup c = config().group("Applets").group(QString::number(applet->id())); oldConfig.reparent(&c); } else { - applet->setParentLayoutItem(this); - applet->updateConstraints(Plasma::SizeConstraint); + addChild(applet); } - scene()->addItem(applet); - applet->setParentLayoutItem(this); d->applets << applet; @@ -555,10 +520,12 @@ void Containment::addApplet(Applet *applet, const QPointF &pos, bool delayInit) if (containmentType() == PanelContainment) { // Reposition the applet after adding has been done - - QGraphicsLinearLayout *l = dynamic_cast(layout()); - Q_ASSERT(l); - l->addItem(applet); + if (index != -1) { + BoxLayout *l = dynamic_cast(layout()); + l->insertItem(index, l->takeAt(l->indexOf(applet))); + d->applets.removeAll(applet); + d->applets.insert(index, applet); + } } else { //FIXME if it came from a panel its bg was disabled //maybe we should expect the applet to handle that on a constraint update? @@ -579,7 +546,7 @@ int Containment::indexAt(const QPointF &pos) const if (pos == QPointF(-1, -1)) { return -1; } - QGraphicsLinearLayout *l = dynamic_cast(layout()); + BoxLayout *l = dynamic_cast(layout()); if (l) { foreach (Applet *existingApplet, d->applets) { if (formFactor() == Horizontal) { @@ -590,37 +557,17 @@ int Containment::indexAt(const QPointF &pos) const // leftmost point. This also allows for dropping in the gap // between applets. if (pos.x() < middle) { - for (int i = 1; i < l->count(); i++) { - if (l->itemAt(i) == existingApplet) { - kDebug() << i; - return i; - } - } + return l->indexOf(existingApplet); } else if (pos.x() <= existingApplet->geometry().right()) { - for (int i = 1; i < l->count(); i++) { - if (l->itemAt(i) == existingApplet) { - kDebug() << i; - return i + 1; - } - } + return l->indexOf(existingApplet) + 1; } } else { qreal middle = (existingApplet->geometry().top() + existingApplet->geometry().bottom()) / 2.0; if (pos.y() < middle) { - for (int i = 1; i < l->count(); i++) { - if (l->itemAt(i) == existingApplet) { - kDebug() << i; - return i; - } - } + return l->indexOf(existingApplet); } else if (pos.y() <= existingApplet->geometry().bottom()) { - for (int i = 1; i < l->count(); i++) { - if (l->itemAt(i) == existingApplet) { - kDebug() << i; - return i + 1; - } - } + return l->indexOf(existingApplet) + 1; } } } @@ -656,7 +603,7 @@ QRectF Containment::geometryForApplet(Applet *applet) const xPositions[-offset.x()] = true; yPositions[-offset.y()] = true; - QRectF placement(QPointF(0, 0), applet->effectiveSizeHint(Qt::PreferredSize)); + QRectF placement(QPointF(0, 0), applet->sizeHint()); foreach (Applet *existingApplet, d->applets) { QPointF bottomRight = existingApplet->geometry().bottomRight(); if (bottomRight.x() + placement.width() < geometry().width()) { @@ -962,7 +909,7 @@ Plasma::Widget * Containment::addToolBoxTool(const QString& toolName, const QStr QSizeF iconSize = tool->sizeFromIconSize(22); tool->setMinimumSize(iconSize); tool->setMaximumSize(iconSize); - tool->resize(tool->effectiveSizeHint(Qt::PreferredSize)); + tool->resize(tool->sizeHint()); d->createToolbox()->addTool(tool, toolName); @@ -989,11 +936,6 @@ void Containment::hideToolbox() d->createToolbox()->hideToolbox(); } -void Containment::repositionToolbox() -{ - d->createToolbox()->setPos(d->toolboxPosition()); -} - } // Plasma namespace #include "containment.moc" diff --git a/containment.h b/containment.h index 0cc3dfccf..b59140d3c 100644 --- a/containment.h +++ b/containment.h @@ -205,7 +205,7 @@ class PLASMA_EXPORT Containment : public Applet * @param pos the containment-relative position */ virtual int indexAt(const QPointF &pos) const; - + /** * Sets the physical screen this Containment is associated with. * @@ -277,11 +277,6 @@ class PLASMA_EXPORT Containment : public Applet */ void hideToolbox(); - /** - * Repositions the Plasma toolbox. Useful to ensure its always in the correct place within the view. - */ - void repositionToolbox(); - Q_SIGNALS: /** * This signal is emitted when a new applet is created by the containment diff --git a/corona.cpp b/corona.cpp index 033d5f108..cc15e2239 100644 --- a/corona.cpp +++ b/corona.cpp @@ -23,7 +23,6 @@ #include #include -#include #include #include #include @@ -37,6 +36,7 @@ #include "containment.h" #include "dataengine.h" #include "phase.h" +#include "layouts/layout.h" #include "widgets/icon.h" using namespace Plasma; @@ -217,7 +217,7 @@ void Corona::loadApplets(const QString& configName) } int cid = group.toUInt(); -// kDebug() << "got a containment in the config, trying to make a" << containmentConfig.readEntry("plugin", QString()) << "from" << group; + //kDebug() << "got a containment in the config, trying to make a" << containmentConfig.readEntry("plugin", QString()) << "from" << group; Containment *c = addContainment(containmentConfig.readEntry("plugin", QString()), QVariantList(), cid, true); if (!c) { @@ -228,14 +228,14 @@ void Corona::loadApplets(const QString& configName) c->init(); c->loadConstraints(&containmentConfig); c->flushUpdatedConstraints(); -// kDebug() << "Containment" << c->id() << "geometry is" << c->geometry().toRect() << "config'd with" << containmentConfig.name(); + //kDebug() << "Containment" << c->id() << "geometry is" << c->geometry().toRect() << "config'd with" << appletConfig.name(); KConfigGroup applets(&containmentConfig, "Applets"); // Sort the applet configs in order of geometry to ensure that applets // are added from left to right or top to bottom for a panel containment QList appletConfigs; foreach (const QString &appletGroup, applets.groupList()) { -// kDebug() << "reading from applet group" << appletGroup; + //kDebug() << "reading from applet group" << appletGroup; KConfigGroup appletConfig(&applets, appletGroup); appletConfigs.append(appletConfig); } @@ -243,7 +243,7 @@ void Corona::loadApplets(const QString& configName) foreach (KConfigGroup appletConfig, appletConfigs) { int appId = appletConfig.name().toUInt(); -// kDebug() << "the name is" << appletConfig.name(); + //kDebug() << "the name is" << appletConfig.name(); QString plugin = appletConfig.readEntry("plugin", QString()); if (plugin.isEmpty()) { @@ -254,7 +254,7 @@ void Corona::loadApplets(const QString& configName) applet->restore(&appletConfig); } } - updateToolboxPositions(); + if (d->containments.count() < 1) { loadDefaultSetup(); } else { @@ -382,15 +382,6 @@ KSharedConfigPtr Corona::config() const return d->config; } -void Corona::updateToolboxPositions() -{ - foreach (Containment *c, d->containments) { - if (c->containmentType() == Containment::DesktopContainment) { - c->repositionToolbox(); - } - } -} - Containment* Corona::addContainment(const QString& name, const QVariantList& args, uint id, bool delayedInit) { QString pluginName = name; diff --git a/corona.h b/corona.h index f9308d15b..d4c6bcba2 100644 --- a/corona.h +++ b/corona.h @@ -89,11 +89,6 @@ public: */ KSharedConfig::Ptr config() const; - /** - * Updates all of the corona's containments with reguards to their tool box position.. - */ - void updateToolboxPositions(); - public Q_SLOTS: /** * Load applet layout from a config file diff --git a/layouts/borderlayout.cpp b/layouts/borderlayout.cpp index be1982c89..70494148e 100644 --- a/layouts/borderlayout.cpp +++ b/layouts/borderlayout.cpp @@ -26,8 +26,7 @@ public: BorderLayout * q; explicit Private(BorderLayout * parent = 0) - : q(parent), - spacing(6.0) + : q(parent) { sizes[LeftPositioned] = -1; sizes[RightPositioned] = -1; @@ -41,32 +40,36 @@ public: { } - QMap< Position, QGraphicsLayoutItem * > itemPositions; + QMap< Position, LayoutItem * > itemPositions; QMap< Position, qreal > sizes; - qreal spacing; }; -BorderLayout::BorderLayout(QGraphicsLayoutItem * parent) - : QGraphicsLayout(parent), - d(new Private(this)) +BorderLayout::BorderLayout(LayoutItem * parent) : + Layout(parent), d(new Private(this)) { - setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding,QSizePolicy::DefaultType); + if (parent) { + parent->setLayout(this); + } } BorderLayout::~BorderLayout() { + releaseManagedItems(); delete d; } +Qt::Orientations BorderLayout::expandingDirections() const +{ + return Qt::Horizontal | Qt::Vertical; +} + void BorderLayout::relayout() { QRectF rect = geometry(); - qreal leftMargin, topMargin, rightMargin, bottomMargin; - getContentsMargins(&leftMargin,&topMargin,&rightMargin,&bottomMargin); - rect.setTopLeft(rect.topLeft() + QPointF(leftMargin,topMargin)); - rect.setBottomRight(rect.bottomRight() - QPointF(rightMargin,bottomMargin)); + rect.setTopLeft(rect.topLeft() + QPointF(margin(LeftMargin), margin(TopMargin))); + rect.setBottomRight(rect.bottomRight() - QPointF(margin(RightMargin), margin(BottomMargin))); QPointF origin = rect.topLeft(); qreal top, bottom, left, right; @@ -76,7 +79,7 @@ void BorderLayout::relayout() right = rect.width() - ((d->sizes[RightPositioned] >= 0) ? d->sizes[RightPositioned] : 0); if (d->itemPositions[TopPositioned] /*&& d->itemPositions[TopPositioned]->isVisible()*/) { - top = (d->sizes[TopPositioned] >= 0) ? d->sizes[TopPositioned] : d->itemPositions[TopPositioned]->effectiveSizeHint(Qt::PreferredSize).height(); + top = (d->sizes[TopPositioned] >= 0) ? d->sizes[TopPositioned] : d->itemPositions[TopPositioned]->sizeHint().height(); d->itemPositions[TopPositioned]->setGeometry(QRectF(origin, QSizeF( rect.width(), top))); top += spacing(); @@ -84,7 +87,7 @@ void BorderLayout::relayout() if (d->itemPositions[BottomPositioned] /*&& d->itemPositions[BottomPositioned]->isVisible()*/) { bottom = (d->sizes[BottomPositioned] >= 0) ? d->sizes[BottomPositioned] - : d->itemPositions[BottomPositioned]->effectiveSizeHint(Qt::PreferredSize).height(); + : d->itemPositions[BottomPositioned]->sizeHint().height(); d->itemPositions[BottomPositioned]->setGeometry(QRectF(origin + QPointF(0, rect.height() - bottom), QSizeF(rect.width(), bottom))); @@ -92,14 +95,14 @@ void BorderLayout::relayout() } if (d->itemPositions[LeftPositioned] /*&& d->itemPositions[LeftPositioned]->isVisible()*/) { - left = (d->sizes[LeftPositioned] >= 0) ? d->sizes[LeftPositioned] : d->itemPositions[LeftPositioned]->effectiveSizeHint(Qt::PreferredSize).width(); + left = (d->sizes[LeftPositioned] >= 0) ? d->sizes[LeftPositioned] : d->itemPositions[LeftPositioned]->sizeHint().width(); d->itemPositions[LeftPositioned]->setGeometry(QRectF(origin + QPointF(0, top), QSizeF(left, bottom - top))); left += spacing(); } if (d->itemPositions[RightPositioned] /*&& d->itemPositions[RightPositioned]->isVisible()*/) { - right = (d->sizes[RightPositioned] >= 0) ? d->sizes[RightPositioned] : d->itemPositions[RightPositioned]->effectiveSizeHint(Qt::PreferredSize).width(); + right = (d->sizes[RightPositioned] >= 0) ? d->sizes[RightPositioned] : d->itemPositions[RightPositioned]->sizeHint().width(); d->itemPositions[RightPositioned]->setGeometry(QRectF(origin + QPointF( rect.width() - right, top), QSizeF(right, bottom - top))); right = rect.width() - right - spacing(); @@ -111,56 +114,63 @@ void BorderLayout::relayout() } } -QSizeF BorderLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const +void BorderLayout::releaseManagedItems() +{ + foreach (Plasma::LayoutItem *item, d->itemPositions) { + item->unsetManagingLayout(this); + } +} + +QSizeF BorderLayout::sizeHint() const { qreal hintHeight = 0.0; qreal hintWidth = 0.0; if (d->itemPositions[TopPositioned] /*&& d->itemPositions[TopPositioned]->isVisible()*/) { - hintHeight += d->itemPositions[TopPositioned]->effectiveSizeHint(Qt::PreferredSize).height(); + hintHeight += d->itemPositions[TopPositioned]->sizeHint().height(); } if (d->itemPositions[BottomPositioned] /*&& d->itemPositions[BottomPositioned]->isVisible()*/) { - hintHeight += d->itemPositions[BottomPositioned]->effectiveSizeHint(Qt::PreferredSize).height(); + hintHeight += d->itemPositions[BottomPositioned]->sizeHint().height(); } if (d->itemPositions[LeftPositioned] /*&& d->itemPositions[LeftPositioned]->isVisible()*/) { - hintWidth += d->itemPositions[LeftPositioned]->effectiveSizeHint(Qt::PreferredSize).width(); + hintWidth += d->itemPositions[LeftPositioned]->sizeHint().width(); } if (d->itemPositions[RightPositioned] /*&& d->itemPositions[RightPositioned]->isVisible()*/) { - hintWidth += d->itemPositions[RightPositioned]->effectiveSizeHint(Qt::PreferredSize).width(); + hintWidth += d->itemPositions[RightPositioned]->sizeHint().width(); } if (d->itemPositions[CenterPositioned] /*&& d->itemPositions[CenterPositioned]->isVisible()*/) { - hintHeight += d->itemPositions[CenterPositioned]->effectiveSizeHint(Qt::PreferredSize).height(); - hintWidth += d->itemPositions[CenterPositioned]->effectiveSizeHint(Qt::PreferredSize).width(); + hintHeight += d->itemPositions[CenterPositioned]->sizeHint().height(); + hintWidth += d->itemPositions[CenterPositioned]->sizeHint().width(); } - qreal leftMargin, topMargin, rightMargin, bottomMargin; - getContentsMargins(&leftMargin,&topMargin,&rightMargin,&bottomMargin); - return QSizeF(hintWidth + 2 + leftMargin + rightMargin, hintHeight + 2 + topMargin + bottomMargin); + return QSizeF(hintWidth + 2 + margin(LeftMargin) + margin(RightMargin), hintHeight + 2 + margin(TopMargin) + margin(BottomMargin)); } -void BorderLayout::addItem(QGraphicsLayoutItem * item) +void BorderLayout::addItem(Plasma::LayoutItem * item) { BorderLayout::addItem (item, CenterPositioned); } -void BorderLayout::addItem(QGraphicsLayoutItem * item, Position position) +void BorderLayout::addItem(Plasma::LayoutItem * item, Position position) { removeItem(item); d->itemPositions[position] = item; + item->setManagingLayout(this); updateGeometry(); } -void BorderLayout::removeItem(QGraphicsLayoutItem * item) +void BorderLayout::removeItem(LayoutItem * item) { - QMutableMapIterator< Position, QGraphicsLayoutItem * > i(d->itemPositions); + QMutableMapIterator< Position, Plasma::LayoutItem * > i(d->itemPositions); while (i.hasNext()) { i.next(); if (i.value() == item) { i.remove(); + item->unsetManagingLayout(this); } } updateGeometry(); @@ -169,7 +179,7 @@ void BorderLayout::removeItem(QGraphicsLayoutItem * item) int BorderLayout::count() const { int count = 0; - foreach (QGraphicsLayoutItem * i, d->itemPositions) { + foreach (Plasma::LayoutItem * i, d->itemPositions) { if (i) { ++count; } @@ -177,10 +187,10 @@ int BorderLayout::count() const return count; } -int BorderLayout::indexOf(QGraphicsLayoutItem * item) const +int BorderLayout::indexOf(LayoutItem * item) const { int count = 0; - foreach (QGraphicsLayoutItem * i, d->itemPositions) { + foreach (Plasma::LayoutItem * i, d->itemPositions) { if (i) { if (item == i) { return count; @@ -191,10 +201,10 @@ int BorderLayout::indexOf(QGraphicsLayoutItem * item) const return -1; } -QGraphicsLayoutItem * BorderLayout::itemAt(int index) const +LayoutItem * BorderLayout::itemAt(int index) const { int count = 0; - foreach (QGraphicsLayoutItem * i, d->itemPositions) { + foreach (Plasma::LayoutItem * i, d->itemPositions) { if (i) { if (index == count) { return i; @@ -207,9 +217,9 @@ QGraphicsLayoutItem * BorderLayout::itemAt(int index) const return 0; } -QGraphicsLayoutItem * BorderLayout::takeAt(int i) +Plasma::LayoutItem * BorderLayout::takeAt(int i) { - QGraphicsLayoutItem * item = itemAt(i); + Plasma::LayoutItem * item = itemAt(i); removeItem(item); return item; } @@ -234,14 +244,4 @@ qreal BorderLayout::size(Position border) return d->sizes[border]; } -qreal BorderLayout::spacing() const -{ - return d->spacing; -} - -void BorderLayout::setSpacing(qreal s) -{ - d->spacing = s; -} - } diff --git a/layouts/borderlayout.h b/layouts/borderlayout.h index c77708c77..d2f2213f9 100644 --- a/layouts/borderlayout.h +++ b/layouts/borderlayout.h @@ -22,10 +22,9 @@ #include -#include - #include #include +#include namespace Plasma { @@ -35,29 +34,33 @@ namespace Plasma { * * Similar to java.awt.BorderLayout from the Java's standard library */ -class PLASMA_EXPORT BorderLayout : public QGraphicsLayout { +class PLASMA_EXPORT BorderLayout : public Layout { public: - explicit BorderLayout(QGraphicsLayoutItem * parent = 0); + explicit BorderLayout(LayoutItem * parent = 0); virtual ~BorderLayout(); + virtual Qt::Orientations expandingDirections() const; + + QSizeF sizeHint() const; + /** * Adds item in the center. Equal to: * addItem(item, Plasma::CenterPositioned); */ - void addItem(QGraphicsLayoutItem * item); + void addItem(Plasma::LayoutItem * item); /** * Adds item at the specified position */ - void addItem(QGraphicsLayoutItem * item, Position position); + void addItem(Plasma::LayoutItem * item, Position position); - void removeItem(QGraphicsLayoutItem * item); + void removeItem(Plasma::LayoutItem * item); virtual int count() const; - virtual int indexOf(QGraphicsLayoutItem * item) const; - virtual QGraphicsLayoutItem * itemAt(int i) const; - virtual QGraphicsLayoutItem * takeAt(int i); + virtual int indexOf(LayoutItem * item) const; + virtual LayoutItem * itemAt(int i) const; + virtual LayoutItem * takeAt(int i); /** * Deactivates the automatic sizing of a border widget, @@ -81,12 +84,9 @@ public: */ qreal size(Position border); - qreal spacing() const; - void setSpacing(qreal s); - protected: void relayout(); - QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; + void releaseManagedItems(); private: class Private; diff --git a/layouts/boxlayout.cpp b/layouts/boxlayout.cpp index e69de29bb..505387cbd 100644 --- a/layouts/boxlayout.cpp +++ b/layouts/boxlayout.cpp @@ -0,0 +1,581 @@ +/* + * Copyright 2007 by Matias Valdenegro T. + * Copyright 2007 by Robert Knight + * Copyright 2008 by Olivier Goffart + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + + * + * This program 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 General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "boxlayout.h" + +#include + +#include +#include + +#include + + +#include "layoutanimator.h" + +namespace Plasma +{ + +class BoxLayout::Private +{ +public: + BoxLayout *const q; + Direction direction; + QList children; + bool expandingBoth; + bool multiRow; + int rowCount; + int colCount() const { + return ((children.count() - 1) / rowCount) + 1; + } + + Private(BoxLayout *parent) + : q(parent) + , direction(LeftToRight), expandingBoth(false), multiRow(false) , rowCount(1) + { + } + + // returns the component of 'size' in the expanding direction + // of this layout + qreal size(const QSizeF& size) const + { + switch (direction) { + case LeftToRight: + case RightToLeft: + return size.width(); + case TopToBottom: + case BottomToTop: + return size.height(); + default: + Q_ASSERT(false); + return 0; + } + } + + // returns the component of 'size' in the other direction + qreal size_o(const QSizeF& size) const + { + switch (direction) { + case LeftToRight: + case RightToLeft: + return size.height(); + case TopToBottom: + case BottomToTop: + return size.width(); + default: + Q_ASSERT(false); + return 0; + } + } + + + // returns the directions in which this layout expands + // or shrinks + Qt::Orientations expandingDirections() const + { + if (expandingBoth) { + return Qt::Horizontal|Qt::Vertical; + } + + switch (direction) { + case LeftToRight: + case RightToLeft: + return Qt::Horizontal; + case TopToBottom: + case BottomToTop: + return Qt::Vertical; + default: + Q_ASSERT(false); + return Qt::Horizontal; + } + } + + // returns the position from which layouting should + // begin depending on the direction of this layout + qreal startPos(const QRectF& geometry) const + { + switch (direction) { + case LeftToRight: + return geometry.left() + q->margin(LeftMargin); + case TopToBottom: + return geometry.top() + q->margin(TopMargin); + case RightToLeft: + return geometry.right() - q->margin(RightMargin); + case BottomToTop: + return geometry.bottom() - q->margin(BottomMargin); + default: + Q_ASSERT(false); + return 0; + } + } + + // lays out an item + // + // 'geometry' the geometry of the layout + // 'item' the item whoose geometry should be altered + // 'pos' the position of the item (in the expanding direction of the layout) + // 'size' the size of the item (in the expanding direction of the layout) + // + // returns the position for the next item in the layout + // + qreal layoutItem(const QRectF& geometry , LayoutItem *item , const qreal pos , qreal size, int row) + { + //kDebug() << "layoutItem: " << direction << "item size" << size; + + QRectF newGeometry; + qreal newPos = 0; + + qreal top = 0; + qreal height = 0; + + const QSizeF minSize = item->minimumSize(); + const QSizeF maxSize = item->maximumSize(); + switch (direction) { + case LeftToRight: + case RightToLeft: + height = (geometry.height() - q->spacing() * (rowCount - 1)) / rowCount; + top = geometry.top() + row * (height + q->spacing()); + height = qBound(minSize.height(), height, maxSize.height()); + if (size > geometry.width()) { + size = geometry.width(); + } + break; + case TopToBottom: + case BottomToTop: + height = (geometry.width() - q->spacing() * (rowCount - 1)) / rowCount; + top = geometry.left() + row * (height + q->spacing()); + height = qBound(minSize.width(), height, maxSize.width()); + if (size > geometry.height()) { + size = geometry.height(); + } + break; + } + + switch (direction) { + case LeftToRight: + newGeometry = QRectF(pos, top, size, height); + newPos = pos + size + q->spacing(); + break; + case RightToLeft: + newGeometry = QRectF(geometry.width() - pos - size, top, size, height); + newPos = pos - size - q->spacing(); + break; + case TopToBottom: + newGeometry = QRectF(top, pos, height, size); + newPos = pos + size + q->spacing(); + break; + case BottomToTop: + newGeometry = QRectF(top, geometry.height() - pos - size, height, size); + newPos = pos - size - q->spacing(); + break; + } + + // kDebug() << "Item geometry: " << newGeometry; + + if (q->animator()) { + q->animator()->setGeometry(item, newGeometry); + } else { + item->setGeometry(newGeometry); + } + + return newPos; + } + + enum SizeType + { + MinSize, + MaxSize, + HintSize + }; + + // this provides a + function which can be passed as the 'op' + // argument to calculateSize + static qreal sum(const qreal a, const qreal b) + { + return a + b; + } + + // calcualtes a size hint or value for this layout + // 'sizeType' - The item size ( minimum , maximum , hint ) to use + // 'dir' - The direction component of the item size to use + // 'op' - A function to apply to the size of each item in the layout + // , usually qMax,qMin or sum + template + qreal calculateSize(SizeType sizeType, Qt::Orientation dir, T (*op)(const T, const T)) const + { + qreal value = 0; + for (int i = 0; i < children.count(); i++) { + + QSizeF itemSize; + switch (sizeType) { + case MinSize: + itemSize = children[i]->minimumSize(); + break; + case MaxSize: + itemSize = children[i]->maximumSize(); + break; + case HintSize: + itemSize = children[i]->sizeHint(); + break; + } + + if (dir == Qt::Horizontal) { + value = op(value, itemSize.width()); + } else { + value = op(value, itemSize.height()); + } + } + + return value; + } + + // calculates a size hint or value for this layout + // 'calculateSizeType' specifies the value to be calculated + QSizeF calculateSize(SizeType calculateSizeType) const + { + QSizeF result; + + const qreal totalSpacingC = q->spacing() * (colCount() - 1); + const qreal totalSpacingR = q->spacing() * (rowCount - 1); + + switch (direction) { + case LeftToRight: + case RightToLeft: + result = QSizeF(calculateSize(calculateSizeType, Qt::Horizontal, sum) / rowCount, + calculateSize(calculateSizeType, Qt::Vertical, qMax) * rowCount); + + result.rwidth() += q->margin(LeftMargin) + q->margin(RightMargin) + totalSpacingC; + result.rheight() += q->margin(TopMargin) + q->margin(BottomMargin) + totalSpacingR; + + break; + case TopToBottom: + case BottomToTop: + result = QSizeF(calculateSize(calculateSizeType, Qt::Horizontal, qMax) / rowCount, + calculateSize(calculateSizeType, Qt::Vertical, sum) * rowCount); + + result.rheight() += q->margin(TopMargin) + q->margin(BottomMargin) + totalSpacingC; + result.rwidth() += q->margin(LeftMargin) + q->margin(RightMargin) + totalSpacingR; + + break; + } + + return result; + } +}; + + +BoxLayout::BoxLayout(Direction direction, LayoutItem *parent) + : Layout(parent), + d(new Private(this)) +{ + d->direction = direction; +} + +void BoxLayout::setDirection(Direction direction) +{ + d->direction = direction; + updateGeometry(); +} + +BoxLayout::Direction BoxLayout::direction() const +{ + return d->direction; +} + +BoxLayout::~BoxLayout() +{ + releaseManagedItems(); + delete d; +} + +Qt::Orientations BoxLayout::expandingDirections() const +{ + return d->expandingDirections(); +} + +int BoxLayout::count() const +{ + return d->children.count(); +} + +void BoxLayout::setAnimator(LayoutAnimator *animator) +{ + Layout::setAnimator(animator); + + if (animator) { + foreach (LayoutItem *item, d->children) { + animator->setGeometry(item, item->geometry()); + animator->setCurrentState(item, LayoutAnimator::StandardState); + } + } +} + +void BoxLayout::insertItem(int index, LayoutItem *item) +{ + if (!item || d->children.contains(item)) { + return; + } + + item->setManagingLayout(this); + + if (index == -1) { + index = d->children.size(); + } + + d->children.insert(index, item); + + if (animator()) { + animator()->setCurrentState(item, LayoutAnimator::InsertedState); + } + + updateGeometry(); +} + +void BoxLayout::addItem(LayoutItem *item) +{ + if (!item) { + return; + } + + insertItem(-1, item); +} + +void BoxLayout::removeItem(LayoutItem *item) +{ + if (!item) { + return; + } + + item->unsetManagingLayout(this); + d->children.removeAll(item); + + if (animator()) { + animator()->setCurrentState(item, LayoutAnimator::RemovedState); + } + + updateGeometry(); +} + +int BoxLayout::indexOf(LayoutItem *l) const +{ + return d->children.indexOf(l); +} + +LayoutItem *BoxLayout::itemAt(int i) const +{ + if (i >= d->children.count()) { + return 0; + } + + return d->children[i]; +} + +LayoutItem *BoxLayout::takeAt(int i) +{ + if (i >= d->children.count()) { + return 0; + } + + return d->children.takeAt(i); + // FIXME: This is never reached. Should it be called? + updateGeometry(); +} + +void BoxLayout::relayout() +{ + const QRectF margined = geometry().adjusted(margin(LeftMargin), margin(TopMargin), -margin(RightMargin), -margin(BottomMargin)); + + //kDebug() << "geo before " << geo << "and with margins" << margined << "margins" << margin(LeftMargin) + // << margin(TopMargin) << -margin(RightMargin) << -margin(BottomMargin); + //kDebug() << "Box layout beginning with geo" << geometry; + //kDebug() << "This box max size" << maximumSize(); + d->rowCount = 1; + if (d->multiRow) { + qreal minRowSize = 1; + qreal minWidth = 0; + for(int i = 0; i < d->children.count(); i++) { + minRowSize = qMax(minRowSize, d->size_o(d->children[i]->minimumSize())); + minWidth += d->size(d->children[i]->minimumSize()); + } + + const qreal ratio = 2.25; //maybe this should not be hardcoded + //we want the height of items be larger than the minimum size + int maxRow = (d->size_o(margined.size()) + spacing()) / + (minRowSize + spacing()); + //we want enough rows to be able to fit each items width. + int minRow = (minWidth + d->children.count() * spacing()) / + (d->size(margined.size()) + spacing() + 0.1); + //FIXME: this formula doesn't take the cellspacing in account + // it should also try to "fill" before adding a row + d->rowCount = 1 + sqrt(ratio * count() * d->size_o(margined.size()) / + (d->size(margined.size()) + 1)); + + d->rowCount = qMax(minRow, d->rowCount); + d->rowCount = qMin(maxRow, d->rowCount); + d->rowCount = qMax(1, d->rowCount); + } + + const int colCount = d->colCount(); + + QVector sizes(colCount, 0); + QVector expansionSpace(colCount, 0); + + qreal available = d->size(margined.size()) - spacing() * colCount; + qreal perItemSize = available / colCount; + + // initial distribution of space to items + for (int i = 0; i < colCount; i++) { + qreal minItemSize = 0; + qreal maxItemSize = 65536; + bool isExpanding = true; + qreal hint = 0; + + for (int f = i * d->rowCount; f < (i + 1) * d->rowCount; f++) { + if (f >= count()) { + break; + } + const LayoutItem *item = d->children[f]; + const bool itemExp = (item->expandingDirections() & d->expandingDirections()); + isExpanding = isExpanding && itemExp; + minItemSize = qMax(minItemSize, d->size(item->minimumSize())); + maxItemSize = qMin(maxItemSize, d->size(item->maximumSize())); + if (!itemExp) { + hint = qMax(hint, d->size(item->sizeHint())); + } + } + + if (isExpanding) { + sizes[i] = perItemSize; + } else { + sizes[i] = hint; + } + + // kDebug() << "Layout max item " << i << "size: " << maxItemSize; + + sizes[i] = qMin(sizes[i], maxItemSize); + sizes[i] = qMax(sizes[i], minItemSize); + + // kDebug() << "Available: " << available << "per item:" << perItemSize << + // "Initial size: " << sizes[i]; + + if (isExpanding) { + expansionSpace[i] = maxItemSize - sizes[i]; + } else { + expansionSpace[i] = 0; + } + + available -= sizes[i]; + // adjust the per-item size if the space was over or under used + if (sizes[i] != perItemSize && i != sizes.count() - 1) { + perItemSize = available / (sizes.count() - i - 1); + } + } + + // distribute out any remaining space to items which can still expand + // + // space is distributed equally amongst remaining items until we run + // out of space or items to expand + int expandable = sizes.count(); + const qreal threshold = 1.0; + while (available > threshold && expandable > 0) { + + const qreal extraSpace = available / expandable; + for (int i = 0; i < colCount; i++) { + if (expansionSpace[i] > threshold) { + qreal oldSize = sizes[i]; + + sizes[i] += qMin(extraSpace, expansionSpace[i]); + + expansionSpace[i] -= sizes[i] - oldSize; + available -= sizes[i] - oldSize; + } else { + expandable--; + } + } + } + + // set items' geometry according to new sizes + qreal pos = d->startPos(geometry()); + for (int col = 0; col < colCount; col++) { + int newPos = pos; + for (int row = 0; row < d->rowCount; row++) { + int i = col * d->rowCount + row; + if (i >= count()) { + break; + } + + //QObject *obj = dynamic_cast(d->children[i]); + //if ( obj ) + //kDebug() << "Item " << i << obj->metaObject()->className() << "size:" << sizes[i]; + + int p = d->layoutItem(margined, d->children[i], pos, sizes[col], row); + newPos = (row != 0 && p < pos) ? qMin(p, newPos) : qMax(p, newPos); + } + pos = newPos; + } + + startAnimation(); +} + +void BoxLayout::releaseManagedItems() +{ + foreach (LayoutItem* item, d->children) { + item->unsetManagingLayout(this); + } +} + +QSizeF BoxLayout::maximumSize() const +{ + return Layout::maximumSize(); +} +QSizeF BoxLayout::minimumSize() const +{ + return d->calculateSize(Private::MinSize); +} +QSizeF BoxLayout::sizeHint() const +{ + return d->calculateSize(Private::HintSize); +} + +void BoxLayout::setMultiRow(bool b) +{ + d->multiRow = b; +} + +void BoxLayout::setExpandingBoth(bool both) +{ + d->expandingBoth = both; +} + +HBoxLayout::HBoxLayout(LayoutItem *parent) + : BoxLayout(LeftToRight, parent) +{ +} + +VBoxLayout::VBoxLayout(LayoutItem *parent) + : BoxLayout(TopToBottom, parent) +{ +} + +} // Plasma namespace + + diff --git a/layouts/boxlayout.h b/layouts/boxlayout.h index e69de29bb..28b64c457 100644 --- a/layouts/boxlayout.h +++ b/layouts/boxlayout.h @@ -0,0 +1,127 @@ +/* + * Copyright 2007 by Matias Valdenegro T. + * Copyright 2007 by Robert Knight + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + + * + * This program 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 General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef PLASMA_BOX_LAYOUT +#define PLASMA_BOX_LAYOUT + +#include + +#include +#include + +namespace Plasma +{ + +/** + * The BoxLayout class lays out items in a horizontal or vertical line. + */ +class PLASMA_EXPORT BoxLayout : public Layout +{ + public: + /** + * This enum describes the directions in which items can be laid + * out. + */ + enum Direction + { + /** Lay items out horizontally, from left to right. */ + LeftToRight, + /** Lay items out horizontally, from right to left. */ + RightToLeft, + /** Lay items out vertically, from top to bottom. */ + TopToBottom, + /** Lay items out vertically, from bottom to top. */ + BottomToTop + }; + + /** + * Creates a new box layout which lays items out in the specified + * @p direction + */ + explicit BoxLayout(Direction direction, LayoutItem *parent = 0); + ~BoxLayout(); + + /** Sets the direction in which items are laid out. */ + void setDirection(Direction direction); + /** Returns the direction in which items are laid out. */ + Direction direction() const; + + /** Inserts a new item into the layout at the specified index. */ + void insertItem(int index, LayoutItem *l); + + /** Set whether this layout will take several rows */ + void setMultiRow(bool b); + + /** Set whether this layout will expand in both directions */ + void setExpandingBoth(bool both); + + // reimplemented from Layout + virtual void addItem(LayoutItem *l); + virtual void removeItem(LayoutItem *l); + virtual int indexOf(LayoutItem *l) const; + virtual LayoutItem *itemAt(int i) const; + virtual LayoutItem *takeAt(int i); + virtual Qt::Orientations expandingDirections() const; + virtual int count() const; + virtual void setAnimator(LayoutAnimator* animator); + + virtual QSizeF minimumSize() const; + virtual QSizeF maximumSize() const; + virtual QSizeF sizeHint() const; + + protected: + void relayout(); + void releaseManagedItems(); + + private: + class Private; + Private *const d; +}; + +/** + * A BoxLayout which defaults to laying items out + * horizontally in a left-to-right order. + * + * Equivalent to creating a BoxLayout and passing LeftToRight + * in the constructor. + */ +class PLASMA_EXPORT HBoxLayout : public BoxLayout +{ +public: + explicit HBoxLayout(LayoutItem *parent = 0); +}; + +/** + * A BoxLayout which defaults to laying items out + * vertically in a top-to-bottom order. + * + * Equivalent to creating a BoxLayout and passing TopToBottom + * in the constructor. + */ +class PLASMA_EXPORT VBoxLayout : public BoxLayout +{ +public: + explicit VBoxLayout(LayoutItem *parent = 0); +}; + +} + +#endif /* PLASMA_BOX_LAYOUT */ diff --git a/layouts/fliplayout.h b/layouts/fliplayout.h index fd5a6cee3..062532807 100644 --- a/layouts/fliplayout.h +++ b/layouts/fliplayout.h @@ -20,9 +20,8 @@ #ifndef PLASMA_FLIPLAYOUT_H_ #define PLASMA_FLIPLAYOUT_H_ -#include - #include +#include #include namespace Plasma @@ -58,7 +57,7 @@ protected: QRectF childGeometry; for (int i = 0; i < count; i++) { - QGraphicsLayoutItem * item = SuperLayout::itemAt(i); + Plasma::LayoutItem * item = SuperLayout::itemAt(i); if (!item) continue; diff --git a/layouts/flowlayout.cpp b/layouts/flowlayout.cpp index 344883a7d..1e1e86eac 100644 --- a/layouts/flowlayout.cpp +++ b/layouts/flowlayout.cpp @@ -29,28 +29,27 @@ #include -// #include "layoutanimator.h" +#include "layoutanimator.h" using namespace Plasma; class FlowLayout::Private { public: - Private() : columnWidth( -1 ), spacing(6.0) {} - QList items; + Private() : columnWidth( -1 ) {} + QList items; qreal columnWidth; - qreal spacing; }; -FlowLayout::FlowLayout(QGraphicsLayoutItem* parent) - : QGraphicsLayout(parent) +FlowLayout::FlowLayout(LayoutItem* parent) + : Layout(parent) , d(new Private) { - setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding,QSizePolicy::DefaultType); } FlowLayout::~FlowLayout() { + releaseManagedItems(); delete d; } @@ -59,35 +58,37 @@ int FlowLayout::count() const return d->items.count(); } -void FlowLayout::addItem(QGraphicsLayoutItem* item) +void FlowLayout::addItem(LayoutItem* item) { if (!item || d->items.contains(item)) { return; } + item->setManagingLayout(this); d->items << item; -//FIXME: Port -// if (animator()) { -// animator()->setCurrentState(item,LayoutAnimator::InsertedState); -// } + + if (animator()) { + animator()->setCurrentState(item,LayoutAnimator::InsertedState); + } updateGeometry(); } -void FlowLayout::removeItem(QGraphicsLayoutItem* item) +void FlowLayout::removeItem(LayoutItem* item) { if (!item) { return; } + item->unsetManagingLayout(this); d->items.removeAll(item); -//FIXME: Port -// if (animator()) { -// animator()->setCurrentState(item,LayoutAnimator::RemovedState); -// } + + if (animator()) { + animator()->setCurrentState(item,LayoutAnimator::RemovedState); + } updateGeometry(); } -int FlowLayout::indexOf(QGraphicsLayoutItem* item) const +int FlowLayout::indexOf(LayoutItem* item) const { if (!item) { return -1; @@ -95,7 +96,7 @@ int FlowLayout::indexOf(QGraphicsLayoutItem* item) const return d->items.indexOf(item); } -QGraphicsLayoutItem* FlowLayout::itemAt(int i) const +LayoutItem* FlowLayout::itemAt(int i) const { if (i >= d->items.count()) { return 0; @@ -104,7 +105,7 @@ QGraphicsLayoutItem* FlowLayout::itemAt(int i) const return d->items[i]; } -QSizeF FlowLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const +QSizeF FlowLayout::sizeHint() const { // TODO A proper algorithm here // @@ -117,7 +118,7 @@ QSizeF FlowLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const return QSizeF(500,500); } -QGraphicsLayoutItem* FlowLayout::takeAt(int i) +LayoutItem* FlowLayout::takeAt(int i) { if (i >= d->items.count()) { return 0; @@ -127,58 +128,6 @@ QGraphicsLayoutItem* FlowLayout::takeAt(int i) // FIXME: Should updateGeometry() be called? } -void FlowLayout::removeAt(int i) -{ - if (i >= d->items.count()) { - return; - } - - d->items.removeAt(i); -} - -QRectF FlowLayout::geometry() const -{ - if (parentLayoutItem()) { - return parentLayoutItem()->geometry(); - } - - return QRectF(QPointF(0, 0), maximumSize()); -} - -void FlowLayout::setGeometry(const QRectF &geom) -{ - if (!geom.isValid() || geom == geometry()) { - return; - } - -// QRectF newGeom = geom; - // -// if (d->parent && !dynamic_cast(d->parent)) { -// newGeom = d->parent->adjustToMargins(newGeom); -// //kDebug() << "parent rect is" << d->parent->topLeft() << d->parent->size() -// // << "and we are" << geometry() << "but aiming for" -// // << newGeom << "from" << geom; -// } - // -// d->pos = newGeom.topLeft(); - setPreferredSize(geom.size()); - // TODO: respect minimum and maximum sizes: is it possible? - //setSize(newGeom.size().expandedTo(minimumSize()).boundedTo(maximumSize())); - - //kDebug() << "geometry is now" << geometry(); - invalidate(); -} - -qreal FlowLayout::spacing() const -{ - return d->spacing; -} - -void FlowLayout::setSpacing(qreal s) -{ - d->spacing = s; -} - template T qSum(const QList& container) { @@ -191,8 +140,7 @@ T qSum(const QList& container) void FlowLayout::relayout() { -// const QRectF rect = adjustToMargins(geometry()); - const QRectF rect = geometry(); + const QRectF rect = adjustToMargins(geometry()); const qreal space = spacing(); const qreal rectWidth = rect.width(); @@ -210,7 +158,7 @@ void FlowLayout::relayout() int colCnt = 0; int rowCnt = 0; - foreach(QGraphicsLayoutItem *item , d->items) { + foreach(LayoutItem *item , d->items) { maxItemWidth = (maxItemWidth < item->maximumSize().width()) ? item->maximumSize().width() : maxItemWidth; minItemWidth = (minItemWidth < item->minimumSize().width()) ? @@ -280,7 +228,7 @@ void FlowLayout::relayout() // lay the items out in left-to-right , top-to-bottom order int insertColumn = 0; qreal rowPos = 0; - foreach(QGraphicsLayoutItem *item , d->items) { + foreach(LayoutItem *item , d->items) { if(insertColumn >= colCnt) { insertColumn = 0; @@ -296,15 +244,26 @@ void FlowLayout::relayout() //kDebug() << "newGeometry: " << newGeometry; insertColumn++; - //FIXME: Port -/* if ( animator() ){ + if ( animator() ){ animator()->setGeometry( item , newGeometry ); - } else {*/ + } else { item->setGeometry( newGeometry ); -// } + } } -//FIXME: Port -// startAnimation(); + + startAnimation(); +} + +void FlowLayout::releaseManagedItems() +{ + foreach (LayoutItem *item, d->items) { + item->unsetManagingLayout(this); + } +} + +Qt::Orientations FlowLayout::expandingDirections() const +{ + return Qt::Vertical | Qt::Horizontal; } qreal FlowLayout::columnWidth() const diff --git a/layouts/flowlayout.h b/layouts/flowlayout.h index 88ff1f9f5..e110fae2c 100644 --- a/layouts/flowlayout.h +++ b/layouts/flowlayout.h @@ -20,9 +20,8 @@ #ifndef __FLOWLAYOUT__ #define __FLOWLAYOUT__ -#include - #include +#include namespace Plasma { @@ -32,31 +31,29 @@ namespace Plasma * * This is similar to the layout of items in a QListView. */ -class PLASMA_EXPORT FlowLayout : public QGraphicsLayout +class PLASMA_EXPORT FlowLayout : public Layout { public: /** Construct a new flow layout with the specified parent. */ - explicit FlowLayout(QGraphicsLayoutItem* parent); + explicit FlowLayout(LayoutItem* parent); virtual ~FlowLayout(); // reimplemented virtual int count() const; - virtual void addItem(QGraphicsLayoutItem* item); - virtual void removeItem(QGraphicsLayoutItem* item); - virtual int indexOf(QGraphicsLayoutItem* item) const; - virtual QGraphicsLayoutItem* itemAt(int i) const; - virtual QGraphicsLayoutItem* takeAt(int i); - virtual void removeAt(int i); + virtual void addItem(LayoutItem* item); + virtual void removeItem(LayoutItem* item); + virtual int indexOf(LayoutItem* item) const; + virtual LayoutItem* itemAt(int i) const; + virtual LayoutItem* takeAt(int i); + + virtual QSizeF sizeHint() const; + virtual Qt::Orientations expandingDirections() const; virtual void setColumnWidth( const qreal width ); virtual qreal columnWidth() const; - virtual QRectF geometry() const; - virtual void setGeometry(const QRectF &geom); - qreal spacing() const; - void setSpacing(qreal s); protected: void relayout(); - virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; + void releaseManagedItems(); private: class Private; diff --git a/layouts/freelayout.cpp b/layouts/freelayout.cpp index 4b69430ec..9da312325 100644 --- a/layouts/freelayout.cpp +++ b/layouts/freelayout.cpp @@ -22,51 +22,60 @@ #include +#include + namespace Plasma { class FreeLayout::Private { public: - QList children; + QList children; }; -FreeLayout::FreeLayout(QGraphicsLayoutItem *parent) - : QGraphicsLayout(parent), +FreeLayout::FreeLayout(LayoutItem *parent) + : Layout(parent), d(new Private) { - setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding,QSizePolicy::DefaultType); } FreeLayout::~FreeLayout() { + releaseManagedItems(); delete d; } -void FreeLayout::addItem(QGraphicsLayoutItem *item) +Qt::Orientations FreeLayout::expandingDirections() const +{ + return Qt::Horizontal | Qt::Vertical; +} + +void FreeLayout::addItem(LayoutItem *item) { if (d->children.contains(item)) { return; } d->children << item; + item->setManagingLayout(this); } -void FreeLayout::removeItem(QGraphicsLayoutItem *item) +void FreeLayout::removeItem(LayoutItem *item) { if (!item) { return; } d->children.removeAll(item); + item->unsetManagingLayout(this); } -int FreeLayout::indexOf(QGraphicsLayoutItem *item) const +int FreeLayout::indexOf(LayoutItem *item) const { return d->children.indexOf(item); } -QGraphicsLayoutItem * FreeLayout::itemAt(int i) const +LayoutItem * FreeLayout::itemAt(int i) const { return d->children[i]; } @@ -76,64 +85,42 @@ int FreeLayout::count() const return d->children.count(); } -QGraphicsLayoutItem * FreeLayout::takeAt(int i) +LayoutItem * FreeLayout::takeAt(int i) { return d->children.takeAt(i); } -void FreeLayout::removeAt(int i) -{ - d->children.removeAt(i); -} - void FreeLayout::relayout() { - foreach (QGraphicsLayoutItem *child , d->children) { - if (child->geometry().size() != child->effectiveSizeHint(Qt::PreferredSize)) { - const QSizeF newSize = child->effectiveSizeHint(Qt::PreferredSize).expandedTo(minimumSize()).boundedTo(maximumSize()); + foreach (LayoutItem *child , d->children) { + if (child->geometry().size() != child->sizeHint()) { + const QSizeF newSize = child->sizeHint().expandedTo(minimumSize()).boundedTo(maximumSize()); child->setGeometry(QRectF(child->geometry().topLeft(), newSize)); } } } +void FreeLayout::releaseManagedItems() +{ + foreach (LayoutItem *item, d->children) { + item->unsetManagingLayout(this); + } +} + QRectF FreeLayout::geometry() const { - if (parentLayoutItem()) { - return parentLayoutItem()->geometry(); + if (parent()) { + return parent()->geometry(); } return QRectF(QPointF(0, 0), maximumSize()); } -void FreeLayout::setGeometry(const QRectF &geom) +QSizeF FreeLayout::sizeHint() const { - if (!geom.isValid() || geom == geometry()) { - return; - } - -// QRectF newGeom = geom; -// -// if (d->parent && !dynamic_cast(d->parent)) { -// newGeom = d->parent->adjustToMargins(newGeom); -// //kDebug() << "parent rect is" << d->parent->topLeft() << d->parent->size() -// // << "and we are" << geometry() << "but aiming for" -// // << newGeom << "from" << geom; -// } -// -// d->pos = newGeom.topLeft(); - setPreferredSize(geom.size()); - // TODO: respect minimum and maximum sizes: is it possible? - //setSize(newGeom.size().expandedTo(minimumSize()).boundedTo(maximumSize())); - - //kDebug() << "geometry is now" << geometry(); - invalidate(); -} - -QSizeF FreeLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const -{ - if (parentLayoutItem()) { + if (parent()) { //kDebug() << "returning size hint from freelayout of" << parent()->geometry().size(); - return parentLayoutItem()->geometry().size(); + return parent()->geometry().size(); } //kDebug() << "returning size hint from freelayout of" << maximumSize(); diff --git a/layouts/freelayout.h b/layouts/freelayout.h index 162f47e78..990260938 100644 --- a/layouts/freelayout.h +++ b/layouts/freelayout.h @@ -23,9 +23,8 @@ #include -#include - #include +#include namespace Plasma { @@ -38,30 +37,30 @@ namespace Plasma * Whenever this layout is updated, all child items are resized to * their sizeHint() and left in their existing positions. */ -class PLASMA_EXPORT FreeLayout : public QGraphicsLayout +class PLASMA_EXPORT FreeLayout : public Layout { public: /** * Creates a new free layout */ - explicit FreeLayout(QGraphicsLayoutItem *parent = 0); + explicit FreeLayout(LayoutItem *parent = 0); ~FreeLayout(); // reimplemented from Layout - virtual void addItem(QGraphicsLayoutItem *l); - virtual void removeItem(QGraphicsLayoutItem *l); - virtual int indexOf(QGraphicsLayoutItem *l) const; - virtual QGraphicsLayoutItem *itemAt(int i) const; - virtual QGraphicsLayoutItem *takeAt(int i); - virtual void removeAt(int i); + virtual void addItem(LayoutItem *l); + virtual void removeItem(LayoutItem *l); + virtual int indexOf(LayoutItem *l) const; + virtual LayoutItem *itemAt(int i) const; + virtual LayoutItem *takeAt(int i); + virtual Qt::Orientations expandingDirections() const; virtual QRectF geometry() const; - virtual void setGeometry(const QRectF &geom); virtual int count() const; - virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; + virtual QSizeF sizeHint() const; protected: void relayout(); + void releaseManagedItems(); private: class Private; diff --git a/layouts/layout.cpp b/layouts/layout.cpp index e69de29bb..efd73efe7 100644 --- a/layouts/layout.cpp +++ b/layouts/layout.cpp @@ -0,0 +1,212 @@ +/* + * Copyright 2007 by Matias Valdenegro T. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + + * + * This program 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 General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "layout.h" + +#include +#include + +#include +#include +#include + +#include + +#include "widgets/widget.h" +#include "layouts/layoutanimator.h" + +namespace Plasma +{ + +class Layout::Private +{ + public: + Private() + : spacing(6.0), + parent(0), + animator(0), + relayouting(false) + { + } + + ~Private() {} + + qreal spacing; + + LayoutItem *parent; + LayoutAnimator *animator; + + bool relayouting; + QPointF pos; +}; + + +Layout::Layout(LayoutItem *parent) + : LayoutItem(), + d(new Private) +{ + setMargins(12, 12, 12, 12); + setParent(parent); +} + +void Layout::setParent(LayoutItem *parent) +{ + if (d->parent == parent) { + return; + } + + if (d->parent && d->parent->layout() == this) { + d->parent->unsetLayout(); + releaseManagedItems(); + } + + d->parent = parent; + + if (parent && parent->layout() != this) { + parent->setLayout(this); + } +} + +Layout::~Layout() +{ + if (d->parent) { + d->parent->unsetLayout(); + d->parent = 0; + } + + delete d; +} + +bool Layout::isEmpty() const +{ + return count() == 0; +} + +void Layout::updateGeometry() +{ + if (d->relayouting) { + return; + } + + d->relayouting = true; + relayout(); + d->relayouting = false; +} + +QRectF Layout::geometry() const +{ + return QRectF(d->pos, size()); +} + +void Layout::setGeometry(const QRectF &geom) +{ + if (!geom.isValid() || geom == geometry()) { + return; + } + + QRectF newGeom = geom; + + if (d->parent && !dynamic_cast(d->parent)) { + newGeom = d->parent->adjustToMargins(newGeom); + //kDebug() << "parent rect is" << d->parent->topLeft() << d->parent->size() + // << "and we are" << geometry() << "but aiming for" + // << newGeom << "from" << geom; + } + + d->pos = newGeom.topLeft(); + setSize(newGeom.size()); + // TODO: respect minimum and maximum sizes: is it possible? + //setSize(newGeom.size().expandedTo(minimumSize()).boundedTo(maximumSize())); + + //kDebug() << "geometry is now" << geometry(); + invalidate(); +} + +void Layout::invalidate() +{ + if (d->relayouting) { + return; + } + + d->relayouting = true; + // find and update the top level layout + Layout *layout = this; + Layout *parentLayout = 0; + + do { + parentLayout = dynamic_cast(layout->parent()); + if (parentLayout) { + if (parentLayout->d->relayouting) { + break; + } + layout = parentLayout; + } + } while (parentLayout); + + layout->relayout(); + d->relayouting = false; +} + + +LayoutAnimator* Layout::animator() const +{ + return d->animator; +} + +void Layout::setAnimator(LayoutAnimator *animator) +{ + d->animator = animator; +} + +qreal Layout::spacing() const +{ + return d->spacing; +} + +void Layout::setSpacing(qreal s) +{ + d->spacing = s; +} + +LayoutItem *Layout::parent() const +{ + return d->parent; +} + +QSizeF Layout::minimumSize() const +{ + return QSizeF(0,0); +} +QSizeF Layout::maximumSize() const +{ + return QSizeF(std::numeric_limits::infinity(),std::numeric_limits::infinity()); +} + +void Layout::startAnimation() +{ + if (animator() && animator()->timeLine()) { + if (animator()->timeLine()->state() == QTimeLine::NotRunning) { + animator()->timeLine()->setCurrentTime(0); + animator()->timeLine()->start(); + } + } +} + +} diff --git a/layouts/layout.h b/layouts/layout.h index e69de29bb..5f22604bf 100644 --- a/layouts/layout.h +++ b/layouts/layout.h @@ -0,0 +1,185 @@ +/* + * Copyright 2007 by Matias Valdenegro T. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + + * + * This program 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 General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __LAYOUT__ +#define __LAYOUT__ + +#include +#include + +#include +#include +#include + +namespace Plasma +{ + +class LayoutAnimator; + +/** + * Base class for Plasma Layout managers + * + * @author Matias Valdenegro T. + * + * All layout managers must implement this class. Normal users should use the specific layouts, + * like Plasma::VBoxLayout, Plasma::HBoxLayout and Plasma::GridLayout. + */ + +class PLASMA_EXPORT Layout : public LayoutItem +{ + public: + /** + * Constructor. + */ + explicit Layout(LayoutItem *parent); + + /** + * Virtual Destructor. + */ + virtual ~Layout(); + + /** + * Returns the spacing between Layout elements of this Layout. + */ + qreal spacing() const; + + /** + * Sets the spacing of this Layout. + */ + void setSpacing(qreal s); + + /** + * Returns the parent of this Layout. + */ + LayoutItem *parent() const; + + /** + * Sets the parent of this layout. + */ + void setParent(LayoutItem *parent); + + /** + * Returns the number of elements of this Layout. + */ + virtual int count() const = 0; + + /** + * Returns true if this Layout contains no elements, false otherwise. + */ + bool isEmpty() const; + + /** + * Adds a Item to this Layout. + * @param l Pointer to the Item to be added. + */ + virtual void addItem(LayoutItem *l) = 0; + + /** + * Removes a Item from this Layout. + * @param l Pointer to the Item to be removed. + */ + virtual void removeItem(LayoutItem *l) = 0; + + /** + * Returns the index of a Item in this Layout. + * @param l Pointer to an Item to be queryed. + */ + virtual int indexOf(LayoutItem *l) const = 0; + + /** + * Returns a Pointer to an Item in this Layout. + * @param i Index of the desired Item. + */ + virtual LayoutItem *itemAt(int i) const = 0; + + /** + * Takes the Pointer of an Item in this Layout. + * @param i Index of the desired Item. + */ + virtual LayoutItem *takeAt(int i) = 0; + + /** + * Returns the object controlling animation of changes + * in this layout or 0 if no animator has been set. + */ + virtual LayoutAnimator* animator() const; + + /** + * Sets the object controlling animation of changes in this + * layout. + */ + virtual void setAnimator( LayoutAnimator* animator ); + + /** + * Returns the current geometry for this layout + */ + virtual QRectF geometry() const; + + /** + * Changes the geometry of this layout + */ + void setGeometry(const QRectF &geometry); + + /** Triggers an update of the layout. */ + void updateGeometry(); + + /** + * Returns the minimum size of this layout. + * The default implementation allows unlimited resizing. + */ + virtual QSizeF minimumSize() const; + /** + * Returns the maximum size of this layout. The default + * implementation allows unlimited resizing. + */ + virtual QSizeF maximumSize() const; + + /** TODO Document me */ + void invalidate(); + + protected: + /** + * Triggers a layout, usually after a change in geometry + */ + virtual void relayout() = 0; + + /** + * When called, the layout must cease management of any + * current LayoutItems it is managing. + */ + virtual void releaseManagedItems() = 0; + + /** + * Starts a layout animation. Subclasses may call this + * at the end of their relayout() implementation to + * start the timeline associated with the layout's animator() + * if there is one. If an animation is already in progress then + * the timeline is reset to 0ms and the animation continues. + */ + void startAnimation(); + + private: + class Private; + Private *const d; +}; + +} + +#endif /* __LAYOUT__ */ diff --git a/layouts/layoutitem.cpp b/layouts/layoutitem.cpp index e69de29bb..39fabbc85 100644 --- a/layouts/layoutitem.cpp +++ b/layouts/layoutitem.cpp @@ -0,0 +1,251 @@ +/* + * Copyright 2007 by Matias Valdenegro T. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + + * + * This program 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 General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "layoutitem.h" + +#include + +#include "layout.h" + +namespace Plasma +{ + +class LayoutItem::Private +{ + public: + Private() + : layout(0), + managingLayout(0), + leftMargin(0), + rightMargin(0), + topMargin(0), + bottomMargin(0) + { + } + + ~Private() {} + + Layout* layout; + Layout* managingLayout; + QSizeF size; + qreal leftMargin; + qreal rightMargin; + qreal topMargin; + qreal bottomMargin; +}; + +LayoutItem::LayoutItem() + : d(new Private()) +{ +} + +LayoutItem::~LayoutItem() +{ + if (d->managingLayout) { + d->managingLayout->removeItem(this); + } + + delete d->layout; + delete d; +} + +QGraphicsItem* LayoutItem::graphicsItem() +{ + return 0; +} + +bool LayoutItem::hasHeightForWidth() const +{ + return false; +} + +qreal LayoutItem::heightForWidth(qreal w) const +{ + Q_UNUSED (w); + return 0.0; +} + +bool LayoutItem::hasWidthForHeight() const +{ + return false; +} + +qreal LayoutItem::widthForHeight(qreal h) const +{ + Q_UNUSED (h); + return 0.0; +} + +void LayoutItem::setLayout(Layout* layout) +{ + if (d->layout == layout) { + return; + } + + delete d->layout; + d->layout = layout; + + if (layout) { + layout->setParent(this); + } +} + +void LayoutItem::unsetLayout() +{ + d->layout = 0; +} + +Layout* LayoutItem::layout() const +{ + return d->layout; +} + +void LayoutItem::setManagingLayout(Layout* layout) +{ + if (layout == d->managingLayout) { + return; + } + + if (d->managingLayout) { + d->managingLayout->removeItem(this); + } + + d->managingLayout = layout; + managingLayoutChanged(); +} + +void LayoutItem::unsetManagingLayout(Layout* layout) +{ + if (d->managingLayout == layout) { + d->managingLayout = 0; + } + managingLayoutChanged(); +} + +void LayoutItem::managingLayoutChanged() +{ +} + +QPointF LayoutItem::topLeft() const +{ + return QPointF(0, 0); +} + +Layout* LayoutItem::managingLayout() const +{ + return d->managingLayout; +} + +qreal LayoutItem::margin(Plasma::MarginEdge edge) const +{ + switch (edge) { + case LeftMargin: + return d->leftMargin; + break; + case RightMargin: + return d->rightMargin; + break; + case TopMargin: + return d->topMargin; + break; + case BottomMargin: + return d->bottomMargin; + break; + } + + return 0; +} + +QRectF LayoutItem::adjustToMargins(const QRectF &rect) const +{ + QRectF r(rect); + + if (r.x() <= d->leftMargin) { + r.setX(d->leftMargin); + } + + if (r.y() <= d->topMargin) { + r.setY(d->topMargin); + } + + QPointF tl = topLeft(); + qreal maxWidth = d->size.width() + tl.x() - d->leftMargin - d->rightMargin; + if (r.width() > maxWidth) { + r.setWidth(maxWidth); + } + + qreal maxHeight = d->size.height() + tl.y() - d->topMargin - d->bottomMargin; + if (r.height() > maxHeight) { + r.setHeight(maxHeight); + } + + return r; +} + +void LayoutItem::setMargin(Plasma::MarginEdge edge, qreal m) +{ + switch (edge) { + case LeftMargin: + d->leftMargin = m; + break; + case RightMargin: + d->rightMargin = m; + break; + case TopMargin: + d->topMargin = m; + break; + case BottomMargin: + d->bottomMargin = m; + break; + } + + if (d->layout) { + d->layout->setGeometry(d->layout->geometry()); + } +} + +void LayoutItem::setMargin(qreal m) +{ + setMargins(m, m, m, m); +} + +void LayoutItem::setMargins(qreal left, qreal top, qreal right, qreal bottom) +{ + d->leftMargin = left; + d->rightMargin = right; + d->topMargin = top; + d->bottomMargin = bottom; + + if (d->layout) { + d->layout->setGeometry(d->layout->geometry()); + } +} + +QSizeF LayoutItem::size() const +{ + return d->size; +} + +void LayoutItem::setSize(const QSizeF &size) +{ + d->size = size; +} + +} diff --git a/layouts/layoutitem.h b/layouts/layoutitem.h index e69de29bb..48c93d541 100644 --- a/layouts/layoutitem.h +++ b/layouts/layoutitem.h @@ -0,0 +1,223 @@ +/* + * Copyright 2007 by Matias Valdenegro T. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2, or + * (at your option) any later version. + + * + * This program 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 General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __LAYOUT_ITEM__ +#define __LAYOUT_ITEM__ + +#include +#include + +#include +#include + +class QGraphicsItem; + +namespace Plasma +{ + +class Layout; + +/** + * Base class for Plasma layout-managed items + * + * @author Matias Valdenegro T. + * + * All layout-managed items should implement this class, but regular users just need to use + * Plasma::Widget and Plasma::Layout. + */ +class PLASMA_EXPORT LayoutItem +{ + public: + + /** + * Constructor. + */ + explicit LayoutItem(); + + /** + * Virtual Destructor. + */ + virtual ~LayoutItem(); + + /** + * Returns a bitmask with the directions that this Item can be expanded. + */ + virtual Qt::Orientations expandingDirections() const = 0; + + /** + * Returns the minimum size of this Item and it's contents. + */ + virtual QSizeF minimumSize() const = 0; + + /** + * Returns the maximum size of this Item. + */ + virtual QSizeF maximumSize() const = 0; + + /** + * Returns true whatever this Item can use height-for-width layout management, + * false otherwise. + */ + virtual bool hasHeightForWidth() const; + + /** + * Returns the corresponding height for a given width. + * @param w Width + */ + virtual qreal heightForWidth(qreal w) const; + + /** + * Returns true whatever this Item can use width-for-height layout management, + * false otherwise. + */ + virtual bool hasWidthForHeight() const; + + /** + * Returns the corresponding width for a given height. + * @param h Height + */ + virtual qreal widthForHeight(qreal h) const; + + /** + * Returns the geometry of this Item. + */ + virtual QRectF geometry() const = 0; + + /** + * Sets the geometry of this Item. + */ + virtual void setGeometry(const QRectF& geometry) = 0; + + /** + * Updates the layouting of the item without first changing its geometry. + * Calling this may result in a geometry change, but may not, depending + * on the managing layout if any. + */ + virtual void updateGeometry() = 0; + + /** + * Returns the most appropriate size of this Item to hold whatever contents it has. + */ + virtual QSizeF sizeHint() const = 0; + + /** + * Sets the layout that will manage children items. The LayoutItem + * takes ownership of the layout from that point forward, unless + * unsetLayout() is called. + * + * @param layout The Layout that this LayoutItem will be managed by. + */ + void setLayout(Layout* layout); + + /** + * Resets the layout that will manage children items to no layout. + * Note that the caller of this method must alert any items managed + * by the layout of this change if necessary. Primarily, this should + * only be used from the dtors of LayoutItem subclasses. + */ + void unsetLayout(); + + /** + * @return the layout this item is currently associated with. + */ + Layout* layout() const; + + /** + * Sets the layout that manages this item's geometry + * + * @param layout the layout that manage this item's geometry + **/ + void setManagingLayout(Layout* layout); + + /** + * Resets the layout that manges this item's geometry if it is the + * currently associated layout + * + * @param layout to unset + **/ + void unsetManagingLayout(Layout* layout); + + /** + * @return the layout that manages this item's geometry, or 0 if none + **/ + Layout* managingLayout() const; + + /** + * Returns the margin of this Layout. + */ + qreal margin(Plasma::MarginEdge edge) const; + + /** + * @return the rect adjust to the margins of this item + */ + QRectF adjustToMargins(const QRectF &rect) const; + + /** + * Sets the margin of this Layout. + */ + void setMargin(Plasma::MarginEdge edge, qreal m); + + /** + * Sets all the margins of this Layout. + */ + void setMargin(qreal m); + + /** + * Sets all the margins of this Layout. + */ + void setMargins(qreal left, qreal top, qreal right, qreal bottom); + + /** + * Sets the size of the layout item + */ + void setSize(const QSizeF &size); + + /** + * @return the size of this item + */ + QSizeF size() const; + + /** + * Returns the graphics item associated with this layout item or 0 + * if there is no associated graphics item. + * + * The default implementation returns 0. + */ + virtual QGraphicsItem* graphicsItem(); + + /** + * Get the topLeft of the item in its coordinate space + */ + virtual QPointF topLeft() const; + + protected: + /** + * Reimplement to respond to a change in managing layout + */ + virtual void managingLayoutChanged(); + + private: + class Private; + Private *const d; +}; + +} + +#endif /* __LAYOUT_ITEM__ */ diff --git a/layouts/nodelayout.cpp b/layouts/nodelayout.cpp index 860a3cd53..be95901e1 100644 --- a/layouts/nodelayout.cpp +++ b/layouts/nodelayout.cpp @@ -67,7 +67,7 @@ NodeLayout::NodeCoordinate NodeLayout::NodeCoordinate::simple(qreal x, qreal y, class NodeLayout::Private { public: - QMap > items; + QMap > items; //QRectF geometry; NodeLayout * parent; QSizeF sizeHint; @@ -97,7 +97,7 @@ public: } - QRectF calculateRectangle(QGraphicsLayoutItem * item, QRectF geometry = QRectF()) const + QRectF calculateRectangle(LayoutItem * item, QRectF geometry = QRectF()) const { if (geometry == QRectF()) { geometry = parent->geometry(); @@ -113,25 +113,25 @@ public: if (items[item].second.xa != std::numeric_limits::infinity()) { result.setRight(calculateXPosition(items[item].second, geometry)); } else { - result.setWidth(item->effectiveSizeHint(Qt::PreferredSize).width()); + result.setWidth(item->sizeHint().width()); result.moveLeft(result.left() - items[item].second.xr * result.width()); } if (items[item].second.ya != std::numeric_limits::infinity()) { result.setBottom(calculateYPosition(items[item].second, geometry)); } else { - result.setHeight(item->effectiveSizeHint(Qt::PreferredSize).height()); + result.setHeight(item->sizeHint().height()); result.moveTop(result.top() - items[item].second.yr * result.height()); } return result; } - void calculateSizeHint(QGraphicsLayoutItem * item = NULL) { + void calculateSizeHint(LayoutItem * item = NULL) { if (item == NULL) { // Recalculate the sizeHint using all items sizeHint = QSizeF(); - foreach (QGraphicsLayoutItem * item, items.keys()) { + foreach (LayoutItem * item, items.keys()) { if (item) { calculateSizeHint(item); } @@ -145,8 +145,8 @@ public: // not do anything smarter concerning the sizeHint when there are // autosized elements. - qreal width = item->effectiveSizeHint(Qt::PreferredSize).width() / qMin(scaled.width(), qreal(1.0)); - qreal height = item->effectiveSizeHint(Qt::PreferredSize).height() / qMin(scaled.height(), qreal(1.0)); + qreal width = item->sizeHint().width() / qMin(scaled.width(), qreal(1.0)); + qreal height = item->sizeHint().height() / qMin(scaled.height(), qreal(1.0)); if (width > sizeHint.width()) sizeHint.setWidth(width); if (height > sizeHint.height()) sizeHint.setHeight(height); @@ -156,47 +156,60 @@ public: }; -NodeLayout::NodeLayout(QGraphicsLayoutItem * parent) - : QGraphicsLayout(parent), d(new Private(this)) +NodeLayout::NodeLayout(LayoutItem * parent) + : Layout(parent), d(new Private(this)) { - setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding,QSizePolicy::DefaultType); } NodeLayout::~NodeLayout() { + releaseManagedItems(); delete d; } +Qt::Orientations NodeLayout::expandingDirections() const +{ + return Qt::Horizontal | Qt::Vertical; +} + void NodeLayout::relayout() { - foreach (QGraphicsLayoutItem * item, d->items.keys()) { + foreach (LayoutItem * item, d->items.keys()) { if (item) { item->setGeometry(d->calculateRectangle(item)); } } } -QSizeF NodeLayout::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const +void NodeLayout::releaseManagedItems() +{ + foreach (LayoutItem * item, d->items.keys()) { + item->unsetManagingLayout(this); + } +} + +QSizeF NodeLayout::sizeHint() const { return d->sizeHint; } -void NodeLayout::addItem(QGraphicsLayoutItem * item) +void NodeLayout::addItem(LayoutItem * item) { NodeLayout::addItem(item, NodeCoordinate()); } -void NodeLayout::addItem(QGraphicsLayoutItem * item, NodeCoordinate topLeft, NodeCoordinate bottomRight) +void NodeLayout::addItem(LayoutItem * item, NodeCoordinate topLeft, NodeCoordinate bottomRight) { if (!item) { return; } d->items[item] = QPair(topLeft, bottomRight); + item->setManagingLayout(this); d->calculateSizeHint(item); } -void NodeLayout::addItem(QGraphicsLayoutItem * item, NodeCoordinate node, qreal xr, qreal yr) +void NodeLayout::addItem(LayoutItem * item, NodeCoordinate node, qreal xr, qreal yr) { if (!item) { return; @@ -204,15 +217,17 @@ void NodeLayout::addItem(QGraphicsLayoutItem * item, NodeCoordinate node, qreal d->items[item] = QPair(node, NodeCoordinate::simple(xr, yr, NodeCoordinate::InnerRelative, NodeCoordinate::InnerRelative)); + item->setManagingLayout(this); d->calculateSizeHint(item); } -void NodeLayout::removeItem(QGraphicsLayoutItem * item) +void NodeLayout::removeItem(LayoutItem * item) { if (!item) { return; } + item->unsetManagingLayout(this); d->items.remove(item); d->calculateSizeHint(); } @@ -222,7 +237,7 @@ int NodeLayout::count() const return d->items.count(); } -int NodeLayout::indexOf(QGraphicsLayoutItem * item) const +int NodeLayout::indexOf(LayoutItem * item) const { if (!item) { return -1; @@ -231,7 +246,7 @@ int NodeLayout::indexOf(QGraphicsLayoutItem * item) const return d->items.keys().indexOf(item); } -QGraphicsLayoutItem * NodeLayout::itemAt(int i) const +LayoutItem * NodeLayout::itemAt(int i) const { if (i >= d->items.count()) { return 0; @@ -240,13 +255,13 @@ QGraphicsLayoutItem * NodeLayout::itemAt(int i) const return d->items.keys()[i]; } -QGraphicsLayoutItem * NodeLayout::takeAt(int i) +LayoutItem * NodeLayout::takeAt(int i) { if (i >= d->items.count()) { return 0; } - QGraphicsLayoutItem * item = itemAt(i); + LayoutItem * item = itemAt(i); removeItem(item); return item; } diff --git a/layouts/nodelayout.h b/layouts/nodelayout.h index 92afbbdc7..1168d7e4e 100644 --- a/layouts/nodelayout.h +++ b/layouts/nodelayout.h @@ -23,10 +23,9 @@ #include #include -#include - #include #include +#include namespace Plasma { @@ -49,7 +48,7 @@ namespace Plasma { * the item will be bound to the defined node. */ -class PLASMA_EXPORT NodeLayout : public QGraphicsLayout { +class PLASMA_EXPORT NodeLayout : public Layout { public: class PLASMA_EXPORT NodeCoordinate { public: @@ -71,21 +70,24 @@ public: float yr, ya; }; - explicit NodeLayout(QGraphicsLayoutItem * parent = 0); + // reimplemented + virtual Qt::Orientations expandingDirections() const; + + explicit NodeLayout(LayoutItem * parent = 0); virtual ~NodeLayout(); - + QSizeF sizeHint() const; /** * Adds item at top-left corner, with automatic sizing * (using sizeHint of the item) */ - void addItem (QGraphicsLayoutItem * item); + void addItem (LayoutItem * item); /** * Adds item with specified top-left and bottom right corners. */ - void addItem (QGraphicsLayoutItem * item, + void addItem (LayoutItem * item, NodeCoordinate topLeft, NodeCoordinate bottomRight); /** @@ -94,19 +96,19 @@ public: * are relative coordinates so (0, 0) represent top left corner, * (0.5, 0.5) represent the center of the item etc. */ - void addItem (QGraphicsLayoutItem * item, + void addItem (LayoutItem * item, NodeCoordinate node, qreal xr = 0, qreal yr = 0); - void removeItem (QGraphicsLayoutItem * item); + void removeItem (LayoutItem * item); virtual int count() const; - virtual int indexOf(QGraphicsLayoutItem * item) const; - virtual QGraphicsLayoutItem * itemAt(int i) const; - virtual QGraphicsLayoutItem * takeAt(int i); + virtual int indexOf(LayoutItem * item) const; + virtual LayoutItem * itemAt(int i) const; + virtual LayoutItem * takeAt(int i); protected: void relayout(); - QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; + void releaseManagedItems(); private: class Private; diff --git a/uiloader.cpp b/uiloader.cpp index e64a9090e..9a5b7aca9 100644 --- a/uiloader.cpp +++ b/uiloader.cpp @@ -21,8 +21,6 @@ #include -#include - #include "plasma/widgets/checkbox.h" #include "plasma/widgets/flash.h" #include "plasma/widgets/icon.h" @@ -31,6 +29,8 @@ #include "plasma/widgets/radiobutton.h" #include "plasma/widgets/meter.h" +#include "plasma/layouts/hboxlayout.h" +#include "plasma/layouts/vboxlayout.h" #include "plasma/layouts/flowlayout.h" namespace Plasma @@ -103,13 +103,13 @@ QStringList UiLoader::availableLayouts() const return d->layouts; } -QGraphicsLayout *UiLoader::createLayout( const QString &className, QGraphicsLayoutItem *parent ) +Layout *UiLoader::createLayout( const QString &className, LayoutItem *parent ) { if (className == QString("HBoxLayout")) { - return new QGraphicsLinearLayout( Qt::Horizontal, parent ); + return new HBoxLayout( parent ); } else if (className == QString("VBoxLayout")) { - return new QGraphicsLinearLayout( Qt::Vertical, parent ); + return new VBoxLayout( parent ); } else if (className == QString("FlowLayout")) { return new FlowLayout( parent ); diff --git a/uiloader.h b/uiloader.h index 8f292be00..e763703cb 100644 --- a/uiloader.h +++ b/uiloader.h @@ -25,13 +25,13 @@ #include class QGraphicsItem; -class QGraphicsLayout; -class QGraphicsLayoutItem; namespace Plasma { class Widget; +class Layout; +class LayoutItem; /** * Dynamically create plasma Widgets and Layouts. @@ -50,7 +50,7 @@ public: Widget *createWidget(const QString &className, Widget *parent = 0); QStringList availableLayouts() const; - QGraphicsLayout *createLayout(const QString &className, QGraphicsLayoutItem *parent); + Layout *createLayout(const QString &className, LayoutItem *parent); private: class Private; diff --git a/widgets/icon.cpp b/widgets/icon.cpp index 7d27da836..301d0971f 100644 --- a/widgets/icon.cpp +++ b/widgets/icon.cpp @@ -930,16 +930,6 @@ void Icon::drawActionButtonBase(QPainter* painter, const QSize &size, int elemen painter->drawEllipse(QRectF(QPointF(.0, .0), size)); } -QSizeF Icon::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const -{ - if (which == Qt::MinimumSize) { - return QSizeF(25,25); - } else if (which == Qt::PreferredSize) { - return iconSize(); - } else /*maximumSize*/ { - return constraint.isValid() ? constraint : QSizeF(1000,1000); - } -} void Icon::setText(const QString& text) { diff --git a/widgets/icon.h b/widgets/icon.h index 72c7203a9..2d2e15bbf 100644 --- a/widgets/icon.h +++ b/widgets/icon.h @@ -211,7 +211,6 @@ public Q_SLOTS: protected: void paintWidget(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; Q_SIGNALS: /** diff --git a/widgets/label.cpp b/widgets/label.cpp index 279af8606..441d87a2e 100644 --- a/widgets/label.cpp +++ b/widgets/label.cpp @@ -47,7 +47,6 @@ Label::Label(Widget *parent) { setAlignment(Qt::AlignHCenter); setPen(QPen(Qt::black, 1)); - setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding,QSizePolicy::Label); } Label::~Label() @@ -55,6 +54,11 @@ Label::~Label() delete d; } +Qt::Orientations Label::expandingDirections() const +{ + return Qt::Horizontal | Qt::Vertical; +} + bool Label::hasHeightForWidth() const { return true; @@ -69,7 +73,7 @@ qreal Label::heightForWidth(qreal w) const return 0; } -QSizeF Label::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const +QSizeF Label::sizeHint() const { QFontMetricsF m(d->textFont); return m.boundingRect(QRectF(0,0,9999,9999), d->alignment | Qt::TextWordWrap, d->text).size(); diff --git a/widgets/label.h b/widgets/label.h index 52e908d21..640ddd479 100644 --- a/widgets/label.h +++ b/widgets/label.h @@ -57,6 +57,11 @@ class PLASMA_EXPORT Label : public Plasma::Widget */ virtual ~Label(); + /** + * Labels can expand in Horizontal and Vertical directions. + */ + Qt::Orientations expandingDirections() const; + /** * Labels can use height-for-width geometry management. */ @@ -70,7 +75,7 @@ class PLASMA_EXPORT Label : public Plasma::Widget /** * Reimplemented from Plasma::Widget. */ - QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constrant = QSizeF()) const; + QSizeF sizeHint() const; /** * Sets the text to be displayed. diff --git a/widgets/lineedit.cpp b/widgets/lineedit.cpp index 5c3e6c4d0..91d8ecdd2 100644 --- a/widgets/lineedit.cpp +++ b/widgets/lineedit.cpp @@ -59,7 +59,6 @@ LineEdit::LineEdit(QGraphicsItem *parent) setTextInteractionFlags(Qt::TextEditorInteraction); setCursor(Qt::IBeamCursor); setFlag(QGraphicsItem::ItemIsSelectable); - setSizePolicy(QSizePolicy::Fixed,QSizePolicy::Expanding,QSizePolicy::LineEdit); } LineEdit::~LineEdit() @@ -129,6 +128,11 @@ bool LineEdit::styled() const return d->styled; } +Qt::Orientations LineEdit::expandingDirections() const +{ + return Qt::Vertical; +} + QSizeF LineEdit::minimumSize() const { QSizeF sh = document()->size(); @@ -185,10 +189,14 @@ void LineEdit::setGeometry(const QRectF& geometry) void LineEdit::updateGeometry() { - setGeometry(QRectF(pos(), sizeHint(Qt::PreferredSize))); + if (managingLayout()) { + managingLayout()->invalidate(); + } else { + setGeometry(QRectF(pos(), sizeHint())); + } } -QSizeF LineEdit::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const +QSizeF LineEdit::sizeHint() const { QSizeF sh = document()->size(); diff --git a/widgets/lineedit.h b/widgets/lineedit.h index 3eb1bac14..e67c5071e 100644 --- a/widgets/lineedit.h +++ b/widgets/lineedit.h @@ -23,12 +23,12 @@ #include #include -#include #include #include #include +#include namespace Plasma { @@ -36,7 +36,7 @@ namespace Plasma /** * Class that emulates a QLineEdit inside plasma */ -class PLASMA_EXPORT LineEdit : public QGraphicsTextItem, public QGraphicsLayoutItem +class PLASMA_EXPORT LineEdit : public QGraphicsTextItem, public LayoutItem { Q_OBJECT Q_PROPERTY( bool styled READ styled WRITE setStyled ) @@ -51,6 +51,8 @@ class PLASMA_EXPORT LineEdit : public QGraphicsTextItem, public QGraphicsLayoutI void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); + Qt::Orientations expandingDirections() const; + QSizeF minimumSize() const; QSizeF maximumSize() const; @@ -69,7 +71,7 @@ class PLASMA_EXPORT LineEdit : public QGraphicsTextItem, public QGraphicsLayoutI QRectF geometry() const; void setGeometry(const QRectF& geometry); void updateGeometry(); - QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; + QSizeF sizeHint() const; void setDefaultText(const QString &text); const QString toHtml(); diff --git a/widgets/meter.cpp b/widgets/meter.cpp index fd760300a..bebec5097 100644 --- a/widgets/meter.cpp +++ b/widgets/meter.cpp @@ -111,8 +111,8 @@ public: int maxrotate; }; -Meter::Meter(QGraphicsItem *parent) : - Plasma::Widget(parent), +Meter::Meter(QGraphicsItem *parent, QObject *parentObject) : + Plasma::Widget(parent, parentObject), d(new Private) { } @@ -256,7 +256,7 @@ Meter::MeterType Meter::meterType() const return d->meterType; } -QSizeF Meter::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const +QSizeF Meter::sizeHint() const { return d->sizeHint; } diff --git a/widgets/meter.h b/widgets/meter.h index 213d84313..bbc7e6918 100644 --- a/widgets/meter.h +++ b/widgets/meter.h @@ -73,7 +73,7 @@ public: * @param parent the QGraphicsItem this meter is parented to. * @param parent the QObject this meter is parented to. */ - explicit Meter(QGraphicsItem *parent = 0); + explicit Meter(QGraphicsItem *parent = 0, QObject *parentObject = 0); /** * Destructor @@ -134,7 +134,7 @@ public: /** * Reimplemented from Plasma::Widget */ - virtual QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; + virtual QSizeF sizeHint() const; /** * Set text label for the meter diff --git a/widgets/progressbar.cpp b/widgets/progressbar.cpp index 7371d23ef..6832c03cc 100644 --- a/widgets/progressbar.cpp +++ b/widgets/progressbar.cpp @@ -209,7 +209,7 @@ void ProgressBar::paintWidget(QPainter *painter, const QStyleOptionGraphicsItem style->drawControl(QStyle::CE_ProgressBar, &options, painter, widget); } -QSizeF ProgressBar::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const +QSizeF ProgressBar::sizeHint() const { QFontMetrics fm(font()); QStyleOptionProgressBarV2 options; diff --git a/widgets/progressbar.h b/widgets/progressbar.h index bae33bb59..d9063ba4b 100644 --- a/widgets/progressbar.h +++ b/widgets/progressbar.h @@ -119,7 +119,7 @@ public: void paintWidget(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); - QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; + QSizeF sizeHint() const; public Q_SLOTS: void reset(); diff --git a/widgets/pushbutton.cpp b/widgets/pushbutton.cpp index 8f600cb19..0b28865a3 100644 --- a/widgets/pushbutton.cpp +++ b/widgets/pushbutton.cpp @@ -122,7 +122,6 @@ PushButton::PushButton(Widget *parent) d(new Private) { d->init(this); - setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed,QSizePolicy::PushButton); } PushButton::PushButton(const QString &text, Widget *parent) @@ -131,7 +130,6 @@ PushButton::PushButton(const QString &text, Widget *parent) { d->init(this); setText(text); - setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Fixed,QSizePolicy::PushButton); } PushButton::PushButton(const KIcon &icon, const QString &text, Widget *parent) @@ -290,7 +288,12 @@ QSizeF PushButton::minimumSize() const return m.boundingRect(text()).size() + QSizeF(5.0f, 5.0f); } -QSizeF PushButton::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const +Qt::Orientations PushButton::expandingDirections() const +{ + return Qt::Horizontal; +} + +QSizeF PushButton::sizeHint() const { int width = 0; int height = 0; diff --git a/widgets/pushbutton.h b/widgets/pushbutton.h index 2f168f481..99f31b674 100644 --- a/widgets/pushbutton.h +++ b/widgets/pushbutton.h @@ -162,7 +162,8 @@ public: // NOTE: bogus QSizeF minimumSize() const; - QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; + Qt::Orientations expandingDirections() const; + QSizeF sizeHint() const; Q_SIGNALS: /** diff --git a/widgets/rectangle.cpp b/widgets/rectangle.cpp index 6e8e75fb6..4e359a24d 100644 --- a/widgets/rectangle.cpp +++ b/widgets/rectangle.cpp @@ -29,13 +29,17 @@ Rectangle::Rectangle(Widget *parent) { resize(400.0f, 400.0f); setFlag(QGraphicsItem::ItemIsMovable); - setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding,QSizePolicy::DefaultType); } Rectangle::~Rectangle() { } +Qt::Orientations Rectangle::expandingDirections() const +{ + return Qt::Horizontal | Qt::Vertical; +} + void Rectangle::paintWidget(QPainter *p, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option); diff --git a/widgets/rectangle.h b/widgets/rectangle.h index 95f1061a9..cb9fa158e 100644 --- a/widgets/rectangle.h +++ b/widgets/rectangle.h @@ -31,6 +31,8 @@ class PLASMA_EXPORT Rectangle : public Plasma::Widget Rectangle(Widget *parent); virtual ~Rectangle(); + Qt::Orientations expandingDirections() const; + void paintWidget(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); private: diff --git a/widgets/signalplotter.cpp b/widgets/signalplotter.cpp index e8085812b..806519f41 100644 --- a/widgets/signalplotter.cpp +++ b/widgets/signalplotter.cpp @@ -130,8 +130,6 @@ SignalPlotter::SignalPlotter(Widget *parent) d->svgBackground = 0; d->backgroundColor = QColor(0,0,0); - - setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding,QSizePolicy::DefaultType); } SignalPlotter::~SignalPlotter() @@ -139,6 +137,11 @@ SignalPlotter::~SignalPlotter() delete d; } +Qt::Orientations SignalPlotter::expandingDirections() const +{ + return Qt::Horizontal | Qt::Vertical; +} + QString SignalPlotter::unit() const { return d->unit; diff --git a/widgets/signalplotter.h b/widgets/signalplotter.h index 801af68d9..ca255b292 100644 --- a/widgets/signalplotter.h +++ b/widgets/signalplotter.h @@ -62,6 +62,8 @@ public: SignalPlotter(Widget *parent = 0); ~SignalPlotter(); + Qt::Orientations expandingDirections() const; + /** * Add a new line to the graph plotter, with the specified color. * Note that the order you add the plots must be the same order that diff --git a/widgets/tests/testLayouts.cpp b/widgets/tests/testLayouts.cpp index 9ca95fa36..c7c9cfbb7 100644 --- a/widgets/tests/testLayouts.cpp +++ b/widgets/tests/testLayouts.cpp @@ -8,7 +8,7 @@ #include #include -#include "plasma/layouts/flowlayout.h" +#include "plasma/layouts/boxlayout.h" #include "plasma/widgets/pushbutton.h" #include "plasma/widgets/lineedit.h" #include "plasma/widgets/widget.h" @@ -26,11 +26,11 @@ int main(int argc, char **argv) QGraphicsScene scene; view.setScene(&scene); - Plasma::FlowLayout *widgetLayout = new Plasma::FlowLayout(0); + Plasma::VBoxLayout *widgetLayout = new Plasma::VBoxLayout(0); widgetLayout->setGeometry( QRectF(0.0, 0.0, 400.0, 700.0) ); - Plasma::FlowLayout *h1 = new Plasma::FlowLayout( 0 ); - Plasma::FlowLayout *h2 = new Plasma::FlowLayout( 0 ); + Plasma::HBoxLayout *h1 = new Plasma::HBoxLayout( 0 ); + Plasma::HBoxLayout *h2 = new Plasma::HBoxLayout( 0 ); widgetLayout->addItem( h1 ); widgetLayout->addItem( h2 ); diff --git a/widgets/tests/testProgressBar.cpp b/widgets/tests/testProgressBar.cpp index 7103fb16f..0f1893646 100644 --- a/widgets/tests/testProgressBar.cpp +++ b/widgets/tests/testProgressBar.cpp @@ -1,5 +1,4 @@ #include -#include #include #include #include @@ -10,6 +9,8 @@ #include #include + +#include "plasma/layouts/boxlayout.h" #include "plasma/widgets/progressbar.h" class Counter : QObject @@ -77,10 +78,10 @@ int main(int argc, char **argv) QGraphicsScene scene; view.setScene(&scene); - QGraphicsLinearLayout *widgetLayout = new QGraphicsLinearLayout(Qt::Vertical,0); + Plasma::VBoxLayout *widgetLayout = new Plasma::VBoxLayout(0); widgetLayout->setGeometry(QRectF(0.0, 0.0, 350.0, 30.0)); - QGraphicsLinearLayout *h1 = new QGraphicsLinearLayout(Qt::Horizontal,0); + Plasma::HBoxLayout *h1 = new Plasma::HBoxLayout(0); widgetLayout->addItem(h1); Plasma::ProgressBar *progressBar = new Plasma::ProgressBar(0); diff --git a/widgets/widget.cpp b/widgets/widget.cpp index 6e7890d63..8c9ab8ec2 100644 --- a/widgets/widget.cpp +++ b/widgets/widget.cpp @@ -51,7 +51,10 @@ class Widget::Private { public: Private() - : opacity(1.0), + : minimumSize(0,0), + maximumSize(std::numeric_limits::infinity(), + std::numeric_limits::infinity()), + opacity(1.0), wasMovable(false), toolTip(0) { } @@ -61,6 +64,9 @@ class Widget::Private delete toolTip; } + QSizeF minimumSize; + QSizeF maximumSize; + qreal opacity; bool wasMovable; @@ -115,14 +121,19 @@ bool Widget::Private::shouldPaint(QPainter *painter, const QTransform &transform return true; } -Widget::Widget(QGraphicsItem *parent) - : QGraphicsWidget(parent), +Widget::Widget(QGraphicsItem *parent, QObject* parentObject) + : QObject(parentObject), + QGraphicsItem(parent), d(new Private) { setFlag(QGraphicsItem::ItemClipsToShape, true); setFlag(QGraphicsItem::ItemClipsChildrenToShape, true); setCacheMode(DeviceCoordinateCache); -// setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding,QSizePolicy::DefaultType); + + Widget *w = dynamic_cast(parent); + if (w) { + w->addChild(this); + } } Widget::~Widget() @@ -153,6 +164,44 @@ Widget::CachePaintMode Widget::cachePaintMode() const return CachePaintMode(cacheMode()); } +void Widget::update(const QRectF &rect) +{ + QGraphicsItem::update(rect); +} + +Qt::Orientations Widget::expandingDirections() const +{ + return Qt::Horizontal | Qt::Vertical; +} + +void Widget::setMinimumSize(const QSizeF& newMin) +{ + d->minimumSize = newMin; + QSizeF s = size(); + if (s != s.expandedTo(newMin)) { + setGeometry(QRectF(pos(), s.expandedTo(newMin))); + } +} + +QSizeF Widget::minimumSize() const +{ + return d->minimumSize; +} + +void Widget::setMaximumSize(const QSizeF& newMax) +{ + d->maximumSize = newMax; + QSizeF s = size(); + if (s != s.boundedTo(newMax)) { + setGeometry(QRectF(pos(), s.boundedTo(newMax))); + } +} + +QSizeF Widget::maximumSize() const +{ + return d->maximumSize; +} + bool Widget::hasHeightForWidth() const { return false; @@ -177,6 +226,135 @@ qreal Widget::widthForHeight(qreal h) const return -1.0; } +QRectF Widget::geometry() const +{ + return QRectF(pos(), size()); +} + +void Widget::setSize(const QSizeF &s) +{ + LayoutItem::setSize(s); +} + +void Widget::setGeometry(const QRectF& geometry) +{ + setPos(geometry.topLeft()); + if (geometry.size().width() > 0 && geometry.size().height() > 0 && size() != geometry.size()) { + prepareGeometryChange(); + qreal width = qBound(d->minimumSize.width(), geometry.size().width(), d->maximumSize.width()); + qreal height = qBound(d->minimumSize.height(), geometry.size().height(), d->maximumSize.height()); + + setSize(QSizeF(width, height)); + + qreal xd = topLeft().x(); + qreal yd = topLeft().y(); + + if (xd < 0) { + width -= xd; + xd = 0; + } + + if (yd < 0) { + height -= yd; + yd = 0; + } + + if (layout()) { + QRectF r(QPointF(xd, yd), QSizeF(width, height)); + r = adjustToMargins(r); + layout()->setGeometry(r); + /*if (qobject_cast(this)) { + kDebug() << (QObject*)this << this->geometry() << this->topLeft() + << "layout geometry is now" << r << margin(RightMargin); + }*/ + } + + if (managingLayout()) { + managingLayout()->invalidate(); + } + } + + update(); +} + +void Widget::updateGeometry() +{ + if (managingLayout()) { + managingLayout()->invalidate(); + } else { + setGeometry(QRectF(pos(), sizeHint())); + } +} + +QSizeF Widget::sizeHint() const +{ + if (layout()) { + return layout()->sizeHint(); + } else { + return size(); + } +} + +QFont Widget::font() const +{ + return QApplication::font(); +} + +QRectF Widget::boundingRect() const +{ + return QRectF(QPointF(0,0), size()); +} + +void Widget::resize(const QSizeF& size) +{ + setGeometry(QRectF(pos(), size)); +} + +void Widget::resize(qreal w, qreal h) +{ + resize(QSizeF(w, h)); +} + +Widget *Widget::parent() const +{ + return parent(this); +} + +Widget *Widget::parent(const QGraphicsItem *item) +{ + Q_ASSERT(item); + QGraphicsItem *parent = item->parentItem(); + + while (parent) { + Widget *parentWidget = dynamic_cast(parent); + + if (parentWidget) { + return parentWidget; + } + + parent = parent->parentItem(); + } + return 0; +} + +void Widget::addChild(Widget *w) +{ + if (!w || QGraphicsItem::children().contains(w)) { + return; + } + + w->setParentItem(this); + + //kDebug() << "Added Child Widget" << (QObject*)w << "our geom is" << geometry(); + + if (layout()) { + layout()->addItem(w); + } + + updateGeometry(); + //kDebug() << "after the item is added our geom is now" << geometry(); +} + void Widget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { if (d->opacity < 1.0) { @@ -232,8 +410,7 @@ QVariant Widget::itemChange(GraphicsItemChange change, const QVariant &value) { if (change == QGraphicsItem::ItemChildRemovedChange) { if (layout()) { - //FIXME: Port -// layout()->removeItem(dynamic_cast(value.value())); + layout()->removeItem(dynamic_cast(value.value())); updateGeometry(); } } @@ -241,6 +418,18 @@ QVariant Widget::itemChange(GraphicsItemChange change, const QVariant &value) return QGraphicsItem::itemChange(change, value); } +void Widget::managingLayoutChanged() +{ + if (managingLayout()) { + d->wasMovable = flags() & ItemIsMovable; + if (!dynamic_cast(managingLayout())) { + setFlag(ItemIsMovable, false); + } + } else { + setFlag(ItemIsMovable, d->wasMovable); + } +} + QPoint Widget::popupPosition(const QSize &s) const { QGraphicsView *v = view(); @@ -294,6 +483,17 @@ QPoint Widget::popupPosition(const QSize &s) const return pos; } +void Widget::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) +{ + // HACK: QGraphicsItem's documentation says that the event will be passed + // to the parent if it's not handled, but it isn't passed. This can be + // removed when Qt4.4 becomes a requirement. See Qt bug #176902. + Widget *parentWidget = parent(); + if (parentWidget) { + parentWidget->contextMenuEvent(event); + } +} + bool Widget::sceneEvent(QEvent *event) { switch (event->type()) { @@ -337,13 +537,5 @@ bool Widget::sceneEvent(QEvent *event) return QGraphicsItem::sceneEvent(event); } -QSizeF Widget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const -{ - if (layout()) { - return layout()->effectiveSizeHint(which, constraint); - } - return size(); -} - } // Plasma namespace diff --git a/widgets/widget.h b/widgets/widget.h index 1162354db..09859f466 100644 --- a/widgets/widget.h +++ b/widgets/widget.h @@ -22,13 +22,14 @@ #ifndef WIDGET_H_ #define WIDGET_H_ -#include +#include #include #include #include #include +#include #include class QGraphicsView; @@ -62,9 +63,17 @@ class Layout; * To implement a Widget, just subclass Plasma::Widget and implement at minimum, * sizeHint() and paintWidget() */ -class PLASMA_EXPORT Widget : public QGraphicsWidget +class PLASMA_EXPORT Widget : public QObject, + public QGraphicsItem, + public LayoutItem { Q_OBJECT + Q_PROPERTY( Qt::Orientations expandingDirections READ expandingDirections ) + Q_PROPERTY( QSizeF minimumSize READ minimumSize WRITE setMinimumSize ) + Q_PROPERTY( QSizeF maximumSize READ maximumSize WRITE setMaximumSize ) + Q_PROPERTY( QRectF geometry READ geometry WRITE setGeometry ) + Q_PROPERTY( QSizeF sizeHint READ sizeHint ) + Q_PROPERTY( QSizeF size READ size WRITE resize ) Q_PROPERTY( qreal opacity READ opacity WRITE setOpacity ) public: @@ -79,13 +88,42 @@ public: * Creates a new Plasma::Widget. * @param parent the QGraphicsItem this icon is parented to. */ - explicit Widget(QGraphicsItem *parent = 0); + explicit Widget(QGraphicsItem *parent = 0 , QObject *parentObject = 0); /** * Destroys a Plasma::Widget. */ virtual ~Widget(); + /** + * This method is used by Plasma::Layout to determine which directions the + * widget naturally expands. + * @return bitmask with the directions that this Widget can be expanded. + */ + virtual Qt::Orientations expandingDirections() const; + + /** + * Sets the minimum size of the Widget. + * @param size the size to set as the minimum size. + */ + void setMinimumSize(const QSizeF& size); + + /** + * @return minimum size of the Widget. + */ + QSizeF minimumSize() const; + + /** + * Sets the maximum size of the Widget. + * @param size the size to set as the maximum size. + */ + void setMaximumSize(const QSizeF& size); + + /** + * @return maximum size of the Widget. + */ + QSizeF maximumSize() const; + /** * This method is used by Plasma::Layout to determine whether this widget * can provide a height value given a width value. @@ -116,6 +154,75 @@ public: */ virtual qreal widthForHeight(qreal h) const; + /** + * @return geometry of this widget. + */ + QRectF geometry() const; + + /** + * Sets the geometry of this Widget. + */ + /** + * Sets the geometry of this Plasma::Widget + * @param geometry the geometry to apply to this Plasma::Widget. + */ + virtual void setGeometry(const QRectF &geometry); + + /** + * This method is used to notify any containing Plasma::Layout that it should + * reset its geometry. + */ + // NOTE: this is a completely broken concept -MB + Q_INVOKABLE void updateGeometry(); + + /** + * Returns the recommended size for this widget. Note that this size is not + * necessarily only the size for the widget, but might also include margins etc. + * @return recommended size for this Plasma::Widget. + */ + virtual QSizeF sizeHint() const; + + /** + * @return the font currently set for this widget + **/ + QFont font() const; + + /** + * Reimplemented from QGraphicsItem + * @return the bounding rectangle for this Plasma::Widget + */ + virtual QRectF boundingRect() const; + + /** + * Resizes this Plasma::Widget. + * @param size the new size of this Plasma::Widget. + */ + Q_INVOKABLE void resize(const QSizeF &size); + + /** + * Convenience method for resizing this Plasma::Widget + * @param width the new width. + * @param height the new height. + */ + Q_INVOKABLE void resize(qreal width, qreal height); + + /** + * @return this Plasma::Widget's parent, returns a null pointer if + * none exist. + */ + Q_INVOKABLE Widget *parent() const; + + /** + * @return the Plasma::Widget parent for a given QGraphicsItem + */ + static Widget *parent(const QGraphicsItem *item); + + /** + * Add another Plasma::Widget as a child of this one. + * @param widget the widget to reparent to this Plasma::Widget. + */ + Q_INVOKABLE void addChild(Widget *widget); + void setOpacity(qreal opacity); qreal opacity() const; @@ -131,6 +238,14 @@ public: */ CachePaintMode cachePaintMode() const; + /** + * Invalidates the widget's cache paint mode for a given item rectangle. + * @param rect the optional invalidated rectangle; if null, defaults to boundingRect(). + */ + void update(const QRectF &rect = QRectF()); + inline void update(qreal _x, qreal _y, qreal w, qreal h) + { update(QRectF(_x, _y, w, h)); } + virtual QGraphicsItem* graphicsItem(); /** @@ -175,6 +290,7 @@ public: /** * Reimplemented from QGraphicsItem */ + virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); protected: /** @@ -186,8 +302,8 @@ protected: virtual void paintWidget(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); QVariant itemChange(GraphicsItemChange change, const QVariant &value); + void managingLayoutChanged(); virtual bool sceneEvent(QEvent *event); - QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; private: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);