Give extenders the 'stacked' look from Pinheiro's mockup. It still needs some minor tweaks, but it allready looks quite sexy.

svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=873867
This commit is contained in:
Rob Scheepmaker 2008-10-20 10:58:37 +00:00
parent 6ef3b851ac
commit a26b73b6bb
10 changed files with 595 additions and 360 deletions

View File

@ -38,8 +38,11 @@
#include <KDebug> #include <KDebug>
#include <NETRootInfo> #include <NETRootInfo>
#include <plasma/panelsvg.h> #include "plasma/applet.h"
#include <plasma/theme.h> #include "plasma/extender.h"
#include "plasma/private/extender_p.h"
#include "plasma/panelsvg.h"
#include "plasma/theme.h"
#ifdef Q_WS_X11 #ifdef Q_WS_X11
#include <X11/Xlib.h> #include <X11/Xlib.h>
@ -89,7 +92,39 @@ void DialogPrivate::themeUpdated()
const int leftWidth = background->marginSize(Plasma::LeftMargin); const int leftWidth = background->marginSize(Plasma::LeftMargin);
const int rightWidth = background->marginSize(Plasma::RightMargin); const int rightWidth = background->marginSize(Plasma::RightMargin);
const int bottomHeight = background->marginSize(Plasma::BottomMargin); const int bottomHeight = background->marginSize(Plasma::BottomMargin);
q->setContentsMargins(leftWidth, topHeight, rightWidth, bottomHeight);
//TODO: correct handling of the situation when having vertical panels.
Extender *extender = qobject_cast<Extender*>(widget);
if (extender) {
switch (extender->d->applet->location()) {
case BottomEdge:
background->setEnabledBorders(PanelSvg::LeftBorder | PanelSvg::TopBorder
| PanelSvg::RightBorder);
q->setContentsMargins(0, topHeight, 0, 0);
break;
case TopEdge:
background->setEnabledBorders(PanelSvg::LeftBorder | PanelSvg::BottomBorder
| PanelSvg::RightBorder);
q->setContentsMargins(0, 0, 0, bottomHeight);
break;
case LeftEdge:
background->setEnabledBorders(PanelSvg::TopBorder | PanelSvg::BottomBorder
| PanelSvg::RightBorder);
q->setContentsMargins(0, topHeight, 0, bottomHeight);
break;
case RightEdge:
background->setEnabledBorders(PanelSvg::TopBorder | PanelSvg::BottomBorder
| PanelSvg::LeftBorder);
q->setContentsMargins(0, topHeight, 0, bottomHeight);
break;
default:
background->setEnabledBorders(PanelSvg::AllBorders);
q->setContentsMargins(leftWidth, topHeight, rightWidth, bottomHeight);
}
} else {
q->setContentsMargins(leftWidth, topHeight, rightWidth, bottomHeight);
}
q->update();
} }
void DialogPrivate::adjustView() void DialogPrivate::adjustView()
@ -99,13 +134,15 @@ void DialogPrivate::adjustView()
kDebug() << "Widget size:" << widget->size() kDebug() << "Widget size:" << widget->size()
<< "| Widget size hint:" << widget->effectiveSizeHint(Qt::PreferredSize) << "| Widget size hint:" << widget->effectiveSizeHint(Qt::PreferredSize)
<< "| Widget minsize hint:" << widget->minimumSize()
<< "| Widget maxsize hint:" << widget->maximumSize()
<< "| Widget bounding rect:" << widget->boundingRect(); << "| Widget bounding rect:" << widget->boundingRect();
QRectF boundingRect = widget->boundingRect(); QRectF boundingRect = widget->boundingRect();
boundingRect.setSize(widget->effectiveSizeHint(Qt::PreferredSize)); boundingRect.setSize(widget->effectiveSizeHint(Qt::PreferredSize));
//reposition and resize the view. //reposition and resize the view.
view->setSceneRect(widget->mapToScene(boundingRect).boundingRect()); view->setSceneRect(widget->sceneBoundingRect());
view->resize(view->mapFromScene(view->sceneRect()).boundingRect().size()); view->resize(view->mapFromScene(view->sceneRect()).boundingRect().size());
view->centerOn(widget); view->centerOn(widget);
@ -115,10 +152,10 @@ void DialogPrivate::adjustView()
q->setMinimumSize(qMin(int(widget->minimumSize().width()) + left + right, QWIDGETSIZE_MAX), q->setMinimumSize(qMin(int(widget->minimumSize().width()) + left + right, QWIDGETSIZE_MAX),
qMin(int(widget->minimumSize().height()) + top + bottom, QWIDGETSIZE_MAX)); qMin(int(widget->minimumSize().height()) + top + bottom, QWIDGETSIZE_MAX));
q->resize(qMin(int(widget->minimumSize().width()) + left + right, QWIDGETSIZE_MAX),
qMin(int(widget->minimumSize().height()) + top + bottom, QWIDGETSIZE_MAX));
q->setMaximumSize(qMin(int(widget->maximumSize().width()) + left + right, QWIDGETSIZE_MAX), q->setMaximumSize(qMin(int(widget->maximumSize().width()) + left + right, QWIDGETSIZE_MAX),
qMin(int(widget->maximumSize().height()) + top + bottom, QWIDGETSIZE_MAX)); qMin(int(widget->maximumSize().height()) + top + bottom, QWIDGETSIZE_MAX));
q->resize(qMin(int(view->size().width()) + left + right, QWIDGETSIZE_MAX),
qMin(int(view->size().height()) + top + bottom, QWIDGETSIZE_MAX));
q->updateGeometry(); q->updateGeometry();
if (q->size() != prevSize) { if (q->size() != prevSize) {
@ -316,6 +353,8 @@ void Dialog::setGraphicsWidget(QGraphicsWidget *widget)
lay->setSpacing(0); lay->setSpacing(0);
} }
d->themeUpdated();
if (!d->view) { if (!d->view) {
d->view = new QGraphicsView(this); d->view = new QGraphicsView(this);
d->view->setFrameShape(QFrame::NoFrame); d->view->setFrameShape(QFrame::NoFrame);

View File

@ -27,12 +27,14 @@
#include "containment.h" #include "containment.h"
#include "corona.h" #include "corona.h"
#include "extenderitem.h" #include "extenderitem.h"
#include "panelsvg.h"
#include "popupapplet.h" #include "popupapplet.h"
#include "svg.h" #include "svg.h"
#include "widgets/label.h" #include "widgets/label.h"
#include "private/applet_p.h" #include "private/applet_p.h"
#include "private/extender_p.h" #include "private/extender_p.h"
#include "private/extenderitem_p.h"
namespace Plasma namespace Plasma
{ {
@ -42,12 +44,15 @@ Extender::Extender(Applet *applet)
d(new ExtenderPrivate(applet, this)) d(new ExtenderPrivate(applet, this))
{ {
applet->d->extender = this; applet->d->extender = this;
setContentsMargins(0, 0, 0, 0);
d->layout = new QGraphicsLinearLayout(this); d->layout = new QGraphicsLinearLayout(this);
d->layout->setOrientation(Qt::Vertical); d->layout->setOrientation(Qt::Vertical);
d->layout->setContentsMargins(0, 0, 0, 0); d->layout->setContentsMargins(0, 0, 0, 0);
d->layout->setSpacing(0); d->layout->setSpacing(0);
setLayout(d->layout); setLayout(d->layout);
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
d->emptyExtenderLabel = new Label(this); d->emptyExtenderLabel = new Label(this);
d->emptyExtenderLabel->setText(d->emptyExtenderMessage); d->emptyExtenderLabel->setText(d->emptyExtenderMessage);
d->emptyExtenderLabel->setMinimumSize(QSizeF(150, 64)); d->emptyExtenderLabel->setMinimumSize(QSizeF(150, 64));
@ -55,8 +60,6 @@ Extender::Extender(Applet *applet)
d->emptyExtenderLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); d->emptyExtenderLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
d->layout->addItem(d->emptyExtenderLabel); d->layout->addItem(d->emptyExtenderLabel);
d->adjustSizeHints();
d->loadExtenderItems(); d->loadExtenderItems();
} }
@ -130,6 +133,21 @@ ExtenderItem *Extender::item(const QString &name) const
return 0; return 0;
} }
void Extender::setExtenderAppearance(Appearance appearance)
{
if (d->appearance == appearance) {
return;
}
d->appearance = appearance;
d->updateBorders();
}
Extender::Appearance Extender::extenderAppearance() const
{
return d->appearance;
}
void Extender::saveState() void Extender::saveState()
{ {
foreach (ExtenderItem *item, attachedItems()) { foreach (ExtenderItem *item, attachedItems()) {
@ -140,7 +158,7 @@ void Extender::saveState()
QVariant Extender::itemChange(GraphicsItemChange change, const QVariant &value) QVariant Extender::itemChange(GraphicsItemChange change, const QVariant &value)
{ {
if (change == QGraphicsItem::ItemPositionHasChanged) { if (change == QGraphicsItem::ItemPositionHasChanged) {
emit geometryChanged(); d->adjustSize();
} }
return QGraphicsWidget::itemChange(change, value); return QGraphicsWidget::itemChange(change, value);
@ -169,7 +187,7 @@ void Extender::itemAddedEvent(ExtenderItem *item, const QPointF &pos)
d->emptyExtenderLabel->hide(); d->emptyExtenderLabel->hide();
} }
d->adjustSizeHints(); d->adjustSize();
} }
void Extender::itemRemovedEvent(ExtenderItem *item) void Extender::itemRemovedEvent(ExtenderItem *item)
@ -185,7 +203,7 @@ void Extender::itemRemovedEvent(ExtenderItem *item)
d->layout->addItem(d->emptyExtenderLabel); d->layout->addItem(d->emptyExtenderLabel);
} }
d->adjustSizeHints(); d->adjustSize();
} }
void Extender::itemHoverEnterEvent(ExtenderItem *item) void Extender::itemHoverEnterEvent(ExtenderItem *item)
@ -209,7 +227,7 @@ void Extender::itemHoverMoveEvent(ExtenderItem *item, const QPointF &pos)
//Create a widget that functions as spacer, and add that to the layout. //Create a widget that functions as spacer, and add that to the layout.
QGraphicsWidget *widget = new QGraphicsWidget(this); QGraphicsWidget *widget = new QGraphicsWidget(this);
widget->setPreferredSize(QSizeF(item->size().width(), item->size().height())); widget->setPreferredSize(QSizeF(item->minimumSize().width(), item->size().height()));
widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
d->spacerWidget = widget; d->spacerWidget = widget;
d->layout->insertItem(insertIndex, widget); d->layout->insertItem(insertIndex, widget);
@ -221,7 +239,7 @@ void Extender::itemHoverMoveEvent(ExtenderItem *item, const QPointF &pos)
d->emptyExtenderLabel->hide(); d->emptyExtenderLabel->hide();
} }
d->adjustSizeHints(); d->adjustSize();
} }
void Extender::itemHoverLeaveEvent(ExtenderItem *item) void Extender::itemHoverLeaveEvent(ExtenderItem *item)
@ -244,7 +262,22 @@ void Extender::itemHoverLeaveEvent(ExtenderItem *item)
d->layout->addItem(d->emptyExtenderLabel); d->layout->addItem(d->emptyExtenderLabel);
} }
d->adjustSizeHints(); d->adjustSize();
}
}
PanelSvg::EnabledBorders Extender::enabledBordersForItem(ExtenderItem *item) const
{
ExtenderItem *topItem = dynamic_cast<ExtenderItem*>(d->layout->itemAt(0));
ExtenderItem *bottomItem = dynamic_cast<ExtenderItem*>(d->layout->itemAt(d->layout->count() - 1));
if (d->appearance == TopDownStacked && bottomItem != item) {
return PanelSvg::LeftBorder | PanelSvg::BottomBorder | PanelSvg::RightBorder;
} else if (d->appearance == BottomUpStacked && topItem != item) {
return PanelSvg::LeftBorder | PanelSvg::TopBorder | PanelSvg::RightBorder;
} else if (d->appearance != NoBorders) {
return PanelSvg::LeftBorder | PanelSvg::RightBorder;
} else {
return 0;
} }
} }
@ -254,7 +287,8 @@ ExtenderPrivate::ExtenderPrivate(Applet *applet, Extender *extender) :
spacerWidget(0), spacerWidget(0),
emptyExtenderMessage(i18n("no items")), emptyExtenderMessage(i18n("no items")),
emptyExtenderLabel(0), emptyExtenderLabel(0),
popup(false) popup(false),
appearance(Extender::NoBorders)
{ {
} }
@ -265,32 +299,19 @@ ExtenderPrivate::~ExtenderPrivate()
void ExtenderPrivate::addExtenderItem(ExtenderItem *item, const QPointF &pos) void ExtenderPrivate::addExtenderItem(ExtenderItem *item, const QPointF &pos)
{ {
attachedExtenderItems.append(item); attachedExtenderItems.append(item);
q->itemAddedEvent(item, pos);
q->itemHoverLeaveEvent(item); q->itemHoverLeaveEvent(item);
q->itemAddedEvent(item, pos);
updateBorders();
emit q->itemAttached(item); emit q->itemAttached(item);
} }
void ExtenderPrivate::removeExtenderItem(ExtenderItem *item) void ExtenderPrivate::removeExtenderItem(ExtenderItem *item)
{ {
attachedExtenderItems.removeOne(item); attachedExtenderItems.removeOne(item);
updateBorders();
q->itemRemovedEvent(item); q->itemRemovedEvent(item);
} }
void ExtenderPrivate::adjustSizeHints()
{
if (!q->layout()) {
return;
}
q->layout()->updateGeometry();
q->setMinimumSize(q->layout()->minimumSize());
q->setPreferredSize(q->layout()->preferredSize());
q->setMaximumSize(q->layout()->maximumSize());
q->updateGeometry();
}
int ExtenderPrivate::insertIndexFromPos(const QPointF &pos) const int ExtenderPrivate::insertIndexFromPos(const QPointF &pos) const
{ {
int insertIndex = -1; int insertIndex = -1;
@ -376,7 +397,40 @@ void ExtenderPrivate::loadExtenderItems()
} }
} }
adjustSizeHints(); adjustSize();
}
void ExtenderPrivate::updateBorders()
{
foreach (ExtenderItem *item, q->attachedItems()) {
if (item && (item->d->background->enabledBorders() != q->enabledBordersForItem(item))) {
//call themeChanged to change the backgrounds enabled borders, and move all contained
//widgets according to it's changed margins.
item->d->themeChanged();
}
}
}
void ExtenderPrivate::adjustSize()
{
if (q->layout()) {
q->layout()->updateGeometry();
//FIXME: for some reason the preferred size hint get's set correctly,
//but the minimumSizeHint doesn't. Investigate why.
q->setMinimumSize(q->layout()->preferredSize());
}
//check if our parentItem is an applet, and set the applets correct minimumsize.
Applet *applet = qgraphicsitem_cast<Applet*>(q->parentItem());
if (applet) {
QSizeF marginSize = applet->size() - applet->contentsRect().size();
//FIXME: for some reason the preferred size hint get's set correctly,
//but the minimumSizeHint doesn't. Investigate why.
applet->setMinimumSize(q->minimumSize() + marginSize);
applet->adjustSize();
}
emit q->geometryChanged();
} }
} // Plasma namespace } // Plasma namespace

View File

@ -22,6 +22,7 @@
#include <QtGui/QGraphicsWidget> #include <QtGui/QGraphicsWidget>
#include "plasma/panelsvg.h"
#include "plasma/plasma_export.h" #include "plasma/plasma_export.h"
namespace Plasma namespace Plasma
@ -54,6 +55,27 @@ class PLASMA_EXPORT Extender : public QGraphicsWidget
Q_PROPERTY(QString emptyExtenderMessage READ emptyExtenderMessage WRITE setEmptyExtenderMessage) Q_PROPERTY(QString emptyExtenderMessage READ emptyExtenderMessage WRITE setEmptyExtenderMessage)
public: public:
/**
* Description on how to render the extender's items.
*/
enum Appearance {
NoBorders = 0, /** Draws no borders on the extender's items. When placed in an applet
on the desktop, use this setting and use the standard margins of
the applet containing this extender. */
BottomUpStacked = 1, /** Draws no borders on the topmost extenderitem, but draws the
left, top and right border on subsequent items. When margins
of the containing dialog are set to 0, except for the top
margin, this leads to the 'stacked' look, recommended for
extenders of applet's contained in a panel at the bottom of
the screen. */
TopDownStacked = 2 /** Draws no borders on the bottom extenderitem, but draws the
left, bottom and right border on subsequent items. When margins
of the containing dialog are set to 0, except for the bottom
margin, this leads to the 'stacked' look, recommended for
extenders of applet's contained in a panel at the top of
the screen. */
};
/** /**
* Creates an extender. Note that extender expects applet to have a config(), and needs a * Creates an extender. Note that extender expects applet to have a config(), and needs a
* scene because of that. So you should only instantiate an extender in init() or later, not * scene because of that. So you should only instantiate an extender in init() or later, not
@ -102,6 +124,18 @@ class PLASMA_EXPORT Extender : public QGraphicsWidget
*/ */
ExtenderItem *item(const QString &name) const; ExtenderItem *item(const QString &name) const;
/**
* Use this function to instruct the extender on how to render it's items. Usually you will
* want to call this function in your applet's constraintsEvent, allthough this is already
* done for you when using PopupApplet at base class for your applet. Defaults to NoBorders.
*/
void setExtenderAppearance(Appearance appearance);
/**
* @return the current way of rendering extender items that is used.
*/
Appearance extenderAppearance() const;
protected: protected:
/** /**
* Get's called after an item has been added to this extender. The bookkeeping has already * Get's called after an item has been added to this extender. The bookkeeping has already
@ -151,6 +185,14 @@ class PLASMA_EXPORT Extender : public QGraphicsWidget
*/ */
virtual void saveState(); virtual void saveState();
/**
* This function get's called on every item to determine which background border's to
* render.
* @param item the item for which it's position or extender has changed.
* @return the borders that have to be enabled on it's background.
*/
virtual PanelSvg::EnabledBorders enabledBordersForItem(ExtenderItem *item) const;
/** /**
* @reimplemented from QGraphicsWidget * @reimplemented from QGraphicsWidget
*/ */
@ -183,6 +225,8 @@ class PLASMA_EXPORT Extender : public QGraphicsWidget
friend class ExtenderPrivate; friend class ExtenderPrivate;
friend class ExtenderItem; friend class ExtenderItem;
friend class ExtenderItemPrivate; friend class ExtenderItemPrivate;
//dialog needs access to the extender's applet location.
friend class DialogPrivate;
//applet should be able to call saveState(); //applet should be able to call saveState();
friend class Applet; friend class Applet;

View File

@ -46,247 +46,11 @@
#include "private/applet_p.h" #include "private/applet_p.h"
#include "private/extender_p.h" #include "private/extender_p.h"
#include "private/extenderitem_p.h"
namespace Plasma namespace Plasma
{ {
class ExtenderItemPrivate
{
public:
ExtenderItemPrivate(ExtenderItem *extenderItem, Extender *hostExtender)
: q(extenderItem),
widget(0),
toplevel(0),
previousTargetExtender(0),
extender(hostExtender),
title(QString()),
sourceAppletId(hostExtender->d->applet->id()),
mousePressed(false),
expirationTimer(0)
{
}
~ExtenderItemPrivate()
{
delete toplevel;
}
/**
* @return a Rect containing the area of the detachable where the draghandle can be drawn.
*/
QRectF dragHandleRect()
{
QRectF rect(bgLeft, bgTop, q->size().width() - bgLeft - bgRight,
dragger->elementSize("hint-preferred-icon-size").height() +
dragTop + dragBottom);
return rect;
}
QRectF titleRect()
{
return dragHandleRect().adjusted(dragLeft + collapseIcon->size().width() + 1, dragTop,
-toolbox->size().width() - dragRight, -dragBottom);
}
//XXX kinda duplicated from applethandle.
//returns true if the applet overlaps with a different view then the current one.
bool leaveCurrentView(const QRect &rect)
{
if ((q->sceneBoundingRect().left() < 0)) {
//always leaveCurrentView when the item is in a Plasma::Dialog which can easy be
//seen by checking if it is in topleft quadrant and it's not just there because it's
//being viewed by the toplevel view.
return true;
}
foreach (QWidget *widget, QApplication::topLevelWidgets()) {
if (widget->geometry().intersects(rect) && widget->isVisible() && widget != toplevel) {
//is this widget a plasma view, a different view then our current one,
//AND not a dashboardview?
QGraphicsView *v = qobject_cast<QGraphicsView*>(widget);
QGraphicsView *currentV = 0;
if (hostApplet()) {
currentV = qobject_cast<QGraphicsView*>(hostApplet()->containment()->view());
}
if (v && v != currentV) {
return true;
}
}
}
return false;
}
QRect screenRect() {
return hostApplet()->containment()->view()
->mapFromScene(q->sceneBoundingRect()).boundingRect();
}
void toggleCollapse() {
q->setCollapsed(!q->isCollapsed());
}
void updateToolBox() {
if (toolbox && dragger && toolboxLayout) {
//clean the layout.
uint iconHeight = dragger->elementSize("hint-preferred-icon-size").height();
while (toolboxLayout->count()) {
QGraphicsLayoutItem *icon = toolboxLayout->itemAt(0);
QGraphicsWidget *widget = dynamic_cast<QGraphicsWidget*>(icon);
widget->deleteLater();
toolboxLayout->removeAt(0);
}
//add the actions that are actually set to visible.
foreach (QAction *action, actions) {
if (action->isVisible()) {
Icon *icon = new Icon(q);
icon->setAction(action);
QSizeF iconSize = icon->sizeFromIconSize(iconHeight);
icon->setMinimumSize(iconSize);
icon->setMaximumSize(iconSize);
toolboxLayout->addItem(icon);
}
}
if (q->isDetached() && sourceApplet) {
Icon *returnToSource = new Icon(q);
returnToSource->setSvg("widgets/configuration-icons", "return-to-source");
QSizeF iconSize = returnToSource->sizeFromIconSize(iconHeight);
returnToSource->setMinimumSize(iconSize);
returnToSource->setMaximumSize(iconSize);
toolboxLayout->addItem(returnToSource);
QObject::connect(returnToSource, SIGNAL(clicked()),
q, SLOT(moveBackToSource()));
}
toolboxLayout->updateGeometry();
//position the toolbox correctly.
QSizeF minimum = toolboxLayout->minimumSize();
toolbox->resize(minimum);
toolbox->setPos(q->size().width() - minimum.width() - bgRight,
((dragger->size().height() + dragTop + dragBottom) / 2) -
(minimum.height() / 2) + bgTop);
toolbox->update();
}
}
//TODO: something like this as static function in corona might be a good idea.
QPointF scenePosFromScreenPos(const QPoint &pos) const
{
//get the stacking order of the toplevel windows and remove the
//toplevel view that's only here while dragging, since we're not
//interested in finding that.
QList<WId> order = KWindowSystem::stackingOrder();
if (toplevel) {
order.removeOne(toplevel->winId());
}
QGraphicsView *found = 0;
foreach (QWidget *w, QApplication::topLevelWidgets()) {
QGraphicsView *v = 0;
//first check if we're over a Dialog.
Dialog *dialog = qobject_cast<Dialog*>(w);
if (dialog) {
if (dialog->isVisible() && dialog->geometry().contains(pos)) {
v = qobject_cast<QGraphicsView*>(dialog->layout()->itemAt(0)->widget());
if (v) {
return v->mapToScene(v->mapFromGlobal(pos));
}
}
} else {
v = qobject_cast<QGraphicsView *>(w);
}
//else check if it is a QGV:
if (v && w->isVisible() && w->geometry().contains(pos)) {
if (found && order.contains(found->winId())) {
if (order.indexOf(found->winId()) < order.indexOf(v->winId())) {
found = v;
}
} else {
found = v;
}
}
}
if (!found) {
return QPointF();
}
return found->mapToScene(found->mapFromGlobal(pos));
}
Applet *hostApplet() const
{
if (extender) {
return extender->d->applet;
} else {
return 0;
}
}
void themeChanged()
{
dragger->setImagePath("widgets/extender-dragger");
background->setImagePath("widgets/extender-background");
dragger->getMargins(dragLeft, dragTop, dragRight, dragBottom);
background->getMargins(bgLeft, bgTop, bgRight, bgBottom);
//setCollapsed recalculates size hints.
q->setCollapsed(q->isCollapsed());
q->update();
}
ExtenderItem *q;
QGraphicsItem *widget;
QGraphicsWidget *toolbox;
QGraphicsLinearLayout *toolboxLayout;
QGraphicsView *toplevel;
Extender *previousTargetExtender;
Extender *extender;
Applet *sourceApplet;
KConfigGroup config;
PanelSvg *dragger;
PanelSvg *background;
Icon *collapseIcon;
QMap<QString, QAction*> actions;
QString title;
QString name;
uint sourceAppletId;
uint extenderItemId;
qreal dragLeft, dragTop, dragRight, dragBottom;
qreal bgLeft, bgTop, bgRight, bgBottom;
QPointF deltaScene;
QPoint mousePos;
bool mousePressed;
bool mouseOver;
QTimer *expirationTimer;
static uint s_maxExtenderItemId;
};
uint ExtenderItemPrivate::s_maxExtenderItemId = 0;
ExtenderItem::ExtenderItem(Extender *hostExtender, uint extenderItemId) ExtenderItem::ExtenderItem(Extender *hostExtender, uint extenderItemId)
: QGraphicsWidget(hostExtender), : QGraphicsWidget(hostExtender),
d(new ExtenderItemPrivate(this, hostExtender)) d(new ExtenderItemPrivate(this, hostExtender))
@ -302,12 +66,15 @@ ExtenderItem::ExtenderItem(Extender *hostExtender, uint extenderItemId)
d->extenderItemId = ++ExtenderItemPrivate::s_maxExtenderItemId; d->extenderItemId = ++ExtenderItemPrivate::s_maxExtenderItemId;
} }
//TODO: make sourceApplet a function so stuff doesn't break when the source applet has been
//removed.
d->sourceApplet = hostExtender->d->applet; d->sourceApplet = hostExtender->d->applet;
//create items's configgroup //create items's configgroup
KConfigGroup cg = hostExtender->d->applet->config("ExtenderItems"); KConfigGroup cg = hostExtender->d->applet->config("ExtenderItems");
KConfigGroup dg = KConfigGroup(&cg, QString::number(d->extenderItemId)); KConfigGroup dg = KConfigGroup(&cg, QString::number(d->extenderItemId));
//TODO: automatically load title and icon.
if (!dg.readEntry("sourceAppletId", 0)) { if (!dg.readEntry("sourceAppletId", 0)) {
//The item is new //The item is new
dg.writeEntry("sourceAppletPluginName", hostExtender->d->applet->pluginName()); dg.writeEntry("sourceAppletPluginName", hostExtender->d->applet->pluginName());
@ -330,33 +97,22 @@ ExtenderItem::ExtenderItem(Extender *hostExtender, uint extenderItemId)
} }
} }
//create the dragger and standard applet background.
d->dragger = new PanelSvg(this);
d->background = new PanelSvg(this);
d->themeChanged();
//create the toolbox. //create the toolbox.
d->toolbox = new QGraphicsWidget(this); d->toolbox = new QGraphicsWidget(this);
d->toolboxLayout = new QGraphicsLinearLayout(d->toolbox); d->toolboxLayout = new QGraphicsLinearLayout(d->toolbox);
d->toolbox->setLayout(d->toolboxLayout); d->toolbox->setLayout(d->toolboxLayout);
//allow the theme to set the size of the icon.
QSizeF iconSize = d->dragger->elementSize("hint-preferred-icon-size");
//create the collapse/applet icon. //create the collapse/applet icon.
d->collapseIcon = new Icon(KIcon(hostExtender->d->applet->icon()), "", this); d->collapseIcon = new Icon(KIcon(hostExtender->d->applet->icon()), "", this);
d->collapseIcon->resize(d->collapseIcon->sizeFromIconSize(iconSize.height()));
d->collapseIcon->setPos(d->bgLeft + d->dragLeft,
(d->dragger->size().height() + d->dragTop + d->dragBottom) / 2 - d->collapseIcon->size().height() / 2 + d->bgTop);
connect(d->collapseIcon, SIGNAL(clicked()), this, SLOT(toggleCollapse())); connect(d->collapseIcon, SIGNAL(clicked()), this, SLOT(toggleCollapse()));
//set the extender we want to move to. //set the extender we want to move to.
setExtender(hostExtender); setExtender(hostExtender);
setAcceptHoverEvents(true); //set the image paths, image sizes and collapseIcon position.
d->themeChanged();
d->updateToolBox(); setAcceptsHoverEvents(true);
updateGeometry();
connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), this, SLOT(themeChanged())); connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), this, SLOT(themeChanged()));
} }
@ -397,7 +153,11 @@ QString ExtenderItem::name() const
void ExtenderItem::setWidget(QGraphicsItem *widget) void ExtenderItem::setWidget(QGraphicsItem *widget)
{ {
widget->setParentItem(this); widget->setParentItem(this);
widget->setPos(QPointF(d->bgLeft + d->dragLeft, d->dragHandleRect().height() +
QSizeF iconSize = d->dragger->elementSize("hint-preferred-icon-size");
QSizeF panelSize(QSizeF(size().width() - d->bgLeft - d->bgRight,
iconSize.height() + d->dragTop + d->dragBottom));
widget->setPos(QPointF(d->bgLeft + d->dragLeft, panelSize.height() +
d->bgTop + d->dragTop)); d->bgTop + d->dragTop));
d->widget = widget; d->widget = widget;
setCollapsed(isCollapsed()); //updates the size hints. setCollapsed(isCollapsed()); //updates the size hints.
@ -466,6 +226,9 @@ void ExtenderItem::setExtender(Extender *extender, const QPointF &pos)
d->expirationTimer = 0; d->expirationTimer = 0;
} }
//set the background svg to that of the extender we're moving to.
d->themeChanged();
//we might have to enable or disable the returnToSource button. //we might have to enable or disable the returnToSource button.
d->updateToolBox(); d->updateToolBox();
} }
@ -578,27 +341,27 @@ void ExtenderItem::setCollapsed(bool collapsed)
d->widget->setVisible(!collapsed); d->widget->setVisible(!collapsed);
QSizeF minimumSize; QSizeF min;
QSizeF preferredSize; QSizeF pref;
QSizeF maximumSize; QSizeF max;
if (d->widget->isWidget()) { if (d->widget->isWidget()) {
QGraphicsWidget *graphicsWidget = static_cast<QGraphicsWidget*>(d->widget); QGraphicsWidget *graphicsWidget = static_cast<QGraphicsWidget*>(d->widget);
minimumSize = graphicsWidget->minimumSize(); min = graphicsWidget->minimumSize();
preferredSize = graphicsWidget->preferredSize(); pref = graphicsWidget->preferredSize();
maximumSize = graphicsWidget->maximumSize(); max = graphicsWidget->maximumSize();
} else { } else {
minimumSize = d->widget->boundingRect().size(); min = d->widget->boundingRect().size();
preferredSize = d->widget->boundingRect().size(); pref = d->widget->boundingRect().size();
maximumSize = d->widget->boundingRect().size(); max = d->widget->boundingRect().size();
} }
if (collapsed) { if (collapsed) {
setPreferredSize(QSizeF(preferredSize.width() + marginWidth, setPreferredSize(QSizeF(pref.width() + marginWidth,
d->dragHandleRect().height() + marginHeight)); d->dragHandleRect().height() + marginHeight));
setMinimumSize(QSizeF(minimumSize.width() + marginWidth, setMinimumSize(QSizeF(min.width() + marginWidth,
d->dragHandleRect().height() + marginHeight)); d->dragHandleRect().height() + marginHeight));
setMaximumSize(QSizeF(maximumSize.width() + marginWidth, setMaximumSize(QSizeF(max.width() + marginWidth,
d->dragHandleRect().height() + marginHeight)); d->dragHandleRect().height() + marginHeight));
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
@ -606,16 +369,15 @@ void ExtenderItem::setCollapsed(bool collapsed)
d->collapseIcon->setToolTip(i18n("Expand this widget")); d->collapseIcon->setToolTip(i18n("Expand this widget"));
} }
} else { } else {
setPreferredSize(QSizeF(preferredSize.width() + marginWidth, setPreferredSize(QSizeF(pref.width() + marginWidth,
preferredSize.height() + d->dragHandleRect().height() + marginHeight)); pref.height() + d->dragHandleRect().height() + marginHeight));
setMinimumSize(QSizeF(minimumSize.width() + marginWidth, setMinimumSize(QSizeF(min.width() + marginWidth,
minimumSize.height() + d->dragHandleRect().height() + marginHeight)); min.height() + d->dragHandleRect().height() + marginHeight));
setMaximumSize(QSizeF(maximumSize.width() + marginWidth, setMaximumSize(QSizeF(max.width() + marginWidth,
maximumSize.height() + d->dragHandleRect().height() + marginHeight)); max.height() + d->dragHandleRect().height() + marginHeight));
if (d->widget->isWidget()) { if (d->widget->isWidget()) {
QGraphicsWidget *graphicsWidget = static_cast<QGraphicsWidget*>(d->widget); setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
setSizePolicy(graphicsWidget->sizePolicy());
} else { } else {
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
} }
@ -626,8 +388,7 @@ void ExtenderItem::setCollapsed(bool collapsed)
} }
updateGeometry(); updateGeometry();
d->extender->d->adjustSize();
d->extender->d->adjustSizeHints();
} }
void ExtenderItem::moveBackToSource() void ExtenderItem::moveBackToSource()
@ -647,17 +408,21 @@ void ExtenderItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
painter->setRenderHint(QPainter::TextAntialiasing, true); painter->setRenderHint(QPainter::TextAntialiasing, true);
painter->setRenderHint(QPainter::Antialiasing, true); painter->setRenderHint(QPainter::Antialiasing, true);
d->background->paintPanel(painter); if (d->background->enabledBorders() != (PanelSvg::LeftBorder | PanelSvg::RightBorder)) {
//Don't paint if only the left and right borders are enabled, we only use the left and right
//border in this situation to set the correct margins on this item.
d->background->paintPanel(painter, QPointF(0, 0));
}
d->dragger->paintPanel(painter, QPointF(d->bgLeft, d->bgTop)); d->dragger->paintPanel(painter, QPointF(d->bgLeft, d->bgTop));
//draw the title. //set the font for the title.
Plasma::Theme *theme = Plasma::Theme::defaultTheme(); Plasma::Theme *theme = Plasma::Theme::defaultTheme();
QFont font = theme->font(Plasma::Theme::DefaultFont); QFont font = theme->font(Plasma::Theme::DefaultFont);
font.setPointSize(KGlobalSettings::smallestReadableFont().pointSize()); font.setPointSize(KGlobalSettings::smallestReadableFont().pointSize());
font.setWeight(QFont::Bold); font.setWeight(QFont::Bold);
//XXX: duplicated from windowtaskitem. //create a pixmap with the title that is faded out at the right side of the titleRect.
//TODO: hmm, create something generic for this... there's probably more stuff that wants to have //TODO: hmm, create something generic for this... there's probably more stuff that wants to have
//this functionality //this functionality
QRectF rect = QRectF(d->titleRect().width() - 30, 0, 30, d->titleRect().height()); QRectF rect = QRectF(d->titleRect().width() - 30, 0, 30, d->titleRect().height());
@ -693,10 +458,9 @@ void ExtenderItem::resizeEvent(QGraphicsSceneResizeEvent *event)
qreal height = event->newSize().height(); qreal height = event->newSize().height();
//resize the dragger //resize the dragger
QSizeF newDraggerSize(width - d->bgLeft - d->bgRight, d->dragger->resizePanel(QSizeF(width - d->bgLeft - d->bgRight,
d->dragger->elementSize("hint-preferred-icon-size").height() + d->dragger->elementSize("hint-preferred-icon-size").height() +
d->dragTop + d->dragBottom); d->dragTop + d->dragBottom));
d->dragger->resizePanel(newDraggerSize);
//resize the applet background //resize the applet background
d->background->resizePanel(event->newSize()); d->background->resizePanel(event->newSize());
@ -704,13 +468,17 @@ void ExtenderItem::resizeEvent(QGraphicsSceneResizeEvent *event)
//resize the widget //resize the widget
if (d->widget && d->widget->isWidget()) { if (d->widget && d->widget->isWidget()) {
QSizeF newWidgetSize(width - d->bgLeft - d->bgRight - d->dragLeft - d->dragRight, QSizeF newWidgetSize(width - d->bgLeft - d->bgRight - d->dragLeft - d->dragRight,
height - d->dragger->size().height() - d->bgTop - d->bgBottom - 2 * d->dragTop - 2 * d->dragBottom); height - d->dragHandleRect().height() - d->bgTop - d->bgBottom -
2 * d->dragTop - 2 * d->dragBottom);
QGraphicsWidget *graphicsWidget = static_cast<QGraphicsWidget*>(d->widget); QGraphicsWidget *graphicsWidget = static_cast<QGraphicsWidget*>(d->widget);
graphicsWidget->resize(newWidgetSize); graphicsWidget->resize(newWidgetSize);
} }
d->updateToolBox(); //reposition the toolbox.
d->repositionToolbox();
update();
} }
void ExtenderItem::mousePressEvent(QGraphicsSceneMouseEvent *event) void ExtenderItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
@ -722,13 +490,9 @@ void ExtenderItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
d->mousePressed = true; d->mousePressed = true;
d->deltaScene = pos(); d->deltaScene = pos();
Applet *parentApplet = d->hostApplet();
d->mousePos = event->pos().toPoint(); d->mousePos = event->pos().toPoint();
d->hostApplet()->raise();
parentApplet->raise(); setZValue(d->hostApplet()->zValue());
setZValue(parentApplet->zValue());
QPointF mousePos = d->scenePosFromScreenPos(event->screenPos()); QPointF mousePos = d->scenePosFromScreenPos(event->screenPos());
@ -746,6 +510,10 @@ void ExtenderItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
return; return;
} }
if (d->background->enabledBorders() != PanelSvg::AllBorders) {
d->themeChanged();
}
//keep track of the movement in scene coordinates. we use this to set the position of the //keep track of the movement in scene coordinates. we use this to set the position of the
//applet when remaining in the current view. //applet when remaining in the current view.
d->deltaScene += event->scenePos() - event->lastScenePos(); d->deltaScene += event->scenePos() - event->lastScenePos();
@ -940,6 +708,236 @@ void ExtenderItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
} }
} }
ExtenderItemPrivate::ExtenderItemPrivate(ExtenderItem *extenderItem, Extender *hostExtender)
: q(extenderItem),
widget(0),
toplevel(0),
previousTargetExtender(0),
extender(hostExtender),
dragger(new PanelSvg(extenderItem)),
background(new PanelSvg(extenderItem)),
title(QString()),
sourceAppletId(hostExtender->d->applet->id()),
mousePressed(false),
expirationTimer(0)
{
}
ExtenderItemPrivate::~ExtenderItemPrivate()
{
delete toplevel;
}
//returns a Rect containing the area of the detachable where the draghandle will be drawn.
QRectF ExtenderItemPrivate::dragHandleRect()
{
QSizeF iconSize = dragger->elementSize("hint-preferred-icon-size");
QSizeF panelSize(QSizeF(q->size().width() - bgLeft - bgRight,
iconSize.height() + dragTop + dragBottom));
return QRectF(QPointF(bgLeft, bgTop), panelSize);
}
QRectF ExtenderItemPrivate::titleRect()
{
return dragHandleRect().adjusted(dragLeft + collapseIcon->size().width() + 1, dragTop,
-toolbox->size().width() - dragRight, -dragBottom);
}
bool ExtenderItemPrivate::leaveCurrentView(const QRect &rect)
{
if ((q->sceneBoundingRect().left() < 0)) {
//always leaveCurrentView when the item is in a Plasma::Dialog which can easy be
//seen by checking if it is in topleft quadrant and it's not just there because it's
//being viewed by the toplevel view.
return true;
}
foreach (QWidget *widget, QApplication::topLevelWidgets()) {
if (widget->geometry().intersects(rect) && widget->isVisible() && widget != toplevel) {
//is this widget a plasma view, a different view then our current one,
//AND not a dashboardview?
QGraphicsView *v = qobject_cast<QGraphicsView*>(widget);
QGraphicsView *currentV = 0;
if (hostApplet()) {
currentV = qobject_cast<QGraphicsView*>(hostApplet()->containment()->view());
}
if (v && v != currentV) {
return true;
}
}
}
return false;
}
QRect ExtenderItemPrivate::screenRect()
{
return hostApplet()->containment()->view()
->mapFromScene(q->sceneBoundingRect()).boundingRect();
}
void ExtenderItemPrivate::toggleCollapse()
{
q->setCollapsed(!q->isCollapsed());
}
void ExtenderItemPrivate::updateToolBox()
{
Q_ASSERT(toolbox);
Q_ASSERT(dragger);
Q_ASSERT(toolboxLayout);
uint iconHeight = dragger->elementSize("hint-preferred-icon-size").height();
//TODO: only delete items that actually have to be deleted, current performance is horrible.
//clean the layout.
while (toolboxLayout->count()) {
QGraphicsLayoutItem *icon = toolboxLayout->itemAt(0);
QGraphicsWidget *widget = dynamic_cast<QGraphicsWidget*>(icon);
widget->deleteLater();
toolboxLayout->removeAt(0);
}
//add the actions that are actually set to visible.
foreach (QAction *action, actions) {
if (action->isVisible()) {
Icon *icon = new Icon(q);
icon->setAction(action);
QSizeF iconSize = icon->sizeFromIconSize(iconHeight);
icon->setMinimumSize(iconSize);
icon->setMaximumSize(iconSize);
toolboxLayout->addItem(icon);
}
}
//add the returntosource icon if we are detached, and have a source applet.
if (q->isDetached() && sourceApplet) {
Icon *returnToSource = new Icon(q);
returnToSource->setSvg("widgets/configuration-icons", "return-to-source");
QSizeF iconSize = returnToSource->sizeFromIconSize(iconHeight);
returnToSource->setMinimumSize(iconSize);
returnToSource->setMaximumSize(iconSize);
toolboxLayout->addItem(returnToSource);
QObject::connect(returnToSource, SIGNAL(clicked()), q, SLOT(moveBackToSource()));
}
toolboxLayout->updateGeometry();
//position the toolbox correctly.
QSizeF minimum = toolboxLayout->minimumSize();
toolbox->resize(minimum);
repositionToolbox();
}
void ExtenderItemPrivate::repositionToolbox()
{
QSizeF minimum = toolboxLayout->minimumSize();
toolbox->setPos(q->size().width() - minimum.width() - bgRight,
((dragHandleRect().height() + dragTop + dragBottom)/2) -
(minimum.height()/2) + bgTop);
}
//TODO: something like this as static function in corona might be a good idea.
QPointF ExtenderItemPrivate::scenePosFromScreenPos(const QPoint &pos) const
{
//get the stacking order of the toplevel windows and remove the toplevel view that's
//only here while dragging, since we're not interested in finding that.
QList<WId> order = KWindowSystem::stackingOrder();
if (toplevel) {
order.removeOne(toplevel->winId());
}
QGraphicsView *found = 0;
foreach (QWidget *w, QApplication::topLevelWidgets()) {
QGraphicsView *v = 0;
//first check if we're over a Dialog.
Dialog *dialog = qobject_cast<Dialog*>(w);
if (dialog) {
if (dialog->isVisible() && dialog->geometry().contains(pos)) {
v = qobject_cast<QGraphicsView*>(dialog->layout()->itemAt(0)->widget());
if (v) {
return v->mapToScene(v->mapFromGlobal(pos));
}
}
} else {
v = qobject_cast<QGraphicsView *>(w);
}
//else check if it is a QGV:
if (v && w->isVisible() && w->geometry().contains(pos)) {
if (found && order.contains(found->winId())) {
if (order.indexOf(found->winId()) < order.indexOf(v->winId())) {
found = v;
}
} else {
found = v;
}
}
}
if (!found) {
return QPointF();
}
return found->mapToScene(found->mapFromGlobal(pos));
}
Applet *ExtenderItemPrivate::hostApplet() const
{
if (extender) {
return extender->d->applet;
} else {
return 0;
}
}
void ExtenderItemPrivate::themeChanged()
{
QSizeF iconSize = dragger->elementSize("hint-preferred-icon-size");
background->setImagePath("widgets/extender-background");
if (mousePressed) {
background->setEnabledBorders(PanelSvg::AllBorders);
} else {
background->setEnabledBorders(extender->enabledBordersForItem(q));
}
background->getMargins(bgLeft, bgTop, bgRight, bgBottom);
dragger->setImagePath("widgets/extender-dragger");
dragger->getMargins(dragLeft, dragTop, dragRight, dragBottom);
QSizeF panelSize(QSizeF(q->size().width() - bgLeft - bgRight,
iconSize.height() + dragTop + dragBottom));
//resize the collapse icon.
collapseIcon->resize(collapseIcon->sizeFromIconSize(iconSize.height()));
//reposition the collapse icon based on the new margins and size.
collapseIcon->setPos(bgLeft + dragLeft,
(panelSize.height() + dragTop + dragBottom)/2 -
collapseIcon->size().height()/2 + bgTop);
//reposition the widget based on the new margins.
if (widget) {
widget->setPos(QPointF(bgLeft + dragLeft, panelSize.height() +
bgTop + dragTop));
}
//reposition the toolbox.
repositionToolbox();
//setCollapsed recalculates size hints.
q->setCollapsed(q->isCollapsed());
q->update();
}
uint ExtenderItemPrivate::s_maxExtenderItemId = 0;
} // namespace Plasma } // namespace Plasma
#include "extenderitem.moc" #include "extenderitem.moc"

View File

@ -213,6 +213,7 @@ class PLASMA_EXPORT ExtenderItem : public QGraphicsWidget
ExtenderItemPrivate * const d; ExtenderItemPrivate * const d;
friend class Extender; friend class Extender;
friend class ExtenderPrivate;
}; };
} // namespace Plasma } // namespace Plasma
#endif // PLASMA_EXTENDERITEM_H #endif // PLASMA_EXTENDERITEM_H

View File

@ -185,6 +185,11 @@ void PopupAppletPrivate::popupConstraintsEvent(Plasma::Constraints constraints)
q->setLayout(lay); q->setLayout(lay);
} }
Extender *extender = qobject_cast<Extender*>(gWidget);
if (extender) {
extender->setExtenderAppearance(Extender::NoBorders);
}
q->setMinimumSize(gWidget->minimumSize() + marginSize); q->setMinimumSize(gWidget->minimumSize() + marginSize);
lay->addItem(gWidget); lay->addItem(gWidget);
//gWidget->installEventFilter(q); //gWidget->installEventFilter(q);
@ -235,6 +240,15 @@ void PopupAppletPrivate::popupConstraintsEvent(Plasma::Constraints constraints)
if (gWidget) { if (gWidget) {
Corona *corona = qobject_cast<Corona *>(gWidget->scene()); Corona *corona = qobject_cast<Corona *>(gWidget->scene());
Extender *extender = qobject_cast<Extender*>(gWidget);
if (extender) {
if (q->location() == TopEdge) {
extender->setExtenderAppearance(Extender::TopDownStacked);
} else {
extender->setExtenderAppearance(Extender::BottomUpStacked);
}
}
//could that cast ever fail?? //could that cast ever fail??
if (corona) { if (corona) {
corona->addOffscreenWidget(gWidget); corona->addOffscreenWidget(gWidget);
@ -289,9 +303,8 @@ bool PopupApplet::eventFilter(QObject *watched, QEvent *event)
QTimer::singleShot(100, this, SLOT(clearPopupLostFocus())); QTimer::singleShot(100, this, SLOT(clearPopupLostFocus()));
} }
/* /**
if (watched == graphicsWidget() && (event->type() == QEvent::GraphicsSceneResize)) { if (layout() && watched == graphicsWidget() && (event->type() == QEvent::GraphicsSceneResize)) {
kDebug() << "do the resize!";
//sizes are recalculated in the constraintsevent so let's just call that. //sizes are recalculated in the constraintsevent so let's just call that.
d->popupConstraintsEvent(Plasma::FormFactorConstraint); d->popupConstraintsEvent(Plasma::FormFactorConstraint);

View File

@ -23,6 +23,7 @@
#include <QString> #include <QString>
#include <QList> #include <QList>
#include <QPointF> #include <QPointF>
#include "../extender.h"
class QGraphicsGridLayout; class QGraphicsGridLayout;
class QGraphicsLinearLayout; class QGraphicsLinearLayout;
@ -45,9 +46,10 @@ class ExtenderPrivate
void addExtenderItem(ExtenderItem *item, const QPointF &pos = QPointF(-1, -1)); void addExtenderItem(ExtenderItem *item, const QPointF &pos = QPointF(-1, -1));
void removeExtenderItem(ExtenderItem *item); void removeExtenderItem(ExtenderItem *item);
void adjustSizeHints();
int insertIndexFromPos(const QPointF &pos) const; int insertIndexFromPos(const QPointF &pos) const;
void loadExtenderItems(); void loadExtenderItems();
void updateBorders();
void adjustSize();
Extender *q; Extender *q;
@ -67,6 +69,8 @@ class ExtenderPrivate
bool popup; bool popup;
Extender::Appearance appearance;
static QGraphicsGridLayout *s_popupLayout; static QGraphicsGridLayout *s_popupLayout;
}; };

View File

@ -19,18 +19,15 @@
#include "extenderapplet_p.h" #include "extenderapplet_p.h"
#include "extender.h" #include "../extender.h"
#include "extenderitem.h" #include "../extenderitem.h"
#include <KDebug>
#include <KIcon>
#include <QGraphicsLinearLayout> #include <QGraphicsLinearLayout>
ExtenderApplet::ExtenderApplet(QObject *parent, const QVariantList &args) ExtenderApplet::ExtenderApplet(QObject *parent, const QVariantList &args)
: Plasma::Applet(parent, args) : Plasma::Applet(parent, args)
{ {
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
} }
ExtenderApplet::~ExtenderApplet() ExtenderApplet::~ExtenderApplet()
@ -39,44 +36,28 @@ ExtenderApplet::~ExtenderApplet()
void ExtenderApplet::init() void ExtenderApplet::init()
{ {
new Plasma::Extender(this); QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(this);
QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(); layout->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
setLayout(layout); setLayout(layout);
extender()->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
connect(extender(), SIGNAL(geometryChanged()), this, SLOT(adjustSize()));
connect(extender(), SIGNAL(itemDetached(Plasma::ExtenderItem*)),
this, SLOT(itemDetached(Plasma::ExtenderItem*)));
layout->addItem(extender());
adjustSize();
}
void ExtenderApplet::adjustSize()
{
layout()->updateGeometry();
qreal left, top, right, bottom; qreal left, top, right, bottom;
getContentsMargins(&left, &top, &right, &bottom); getContentsMargins(&left, &top, &right, &bottom);
extender()->setExtenderAppearance(Plasma::Extender::NoBorders);
extender()->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
setPreferredSize(QSizeF(left + right + layout()->preferredWidth(), connect(extender(), SIGNAL(itemDetached(Plasma::ExtenderItem*)),
top + bottom + layout()->preferredHeight())); this, SLOT(itemDetached(Plasma::ExtenderItem*)));
setMinimumSize(QSizeF(left + right + layout()->minimumWidth(),
top + bottom + layout()->minimumHeight()));
setMaximumSize(QSizeF(left + right + layout()->maximumWidth(),
top + bottom + layout()->maximumHeight()));
layout->addItem(extender());
updateGeometry(); updateGeometry();
//This wasn't necesarry before... but it is now. weirdness.
resize(size().width(), preferredHeight());
layout()->invalidate();
} }
void ExtenderApplet::itemDetached(Plasma::ExtenderItem *) void ExtenderApplet::itemDetached(Plasma::ExtenderItem *)
{ {
kDebug() << "item detached: " << extender()->attachedItems().count();
if (!extender()->attachedItems().count()) { if (!extender()->attachedItems().count()) {
destroy(); destroy();
//FIXME: only fire the signal when the item is really detached, not just being dragged away.
kDebug() << "delete the extender applet...";
} }
} }

View File

@ -22,6 +22,11 @@
#include "applet.h" #include "applet.h"
/**
* This class is used as a 'host' for detached extender items. When an extender item is dropped
* somewhere, this applet is added at the location where the item is dropped, and the item is added
* to it's extender.
*/
class ExtenderApplet : public Plasma::Applet class ExtenderApplet : public Plasma::Applet
{ {
Q_OBJECT Q_OBJECT
@ -33,7 +38,6 @@ class ExtenderApplet : public Plasma::Applet
public Q_SLOTS: public Q_SLOTS:
void itemDetached(Plasma::ExtenderItem *); void itemDetached(Plasma::ExtenderItem *);
void adjustSize();
}; };
#endif #endif

View File

@ -1,4 +1,101 @@
#ifndef WIDGETS_EXTENDERITEM_P_H /*
#define WIDGETS_EXTENDERITEM_P_H * Copyright 2008 by Rob Scheepmaker <r.scheepmaker@student.utwente.nl>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
#endif // WIDGETS_EXTENDERITEM_P_H #ifndef LIBS_PLASMA_EXTENDERITEM_P_H
#define LIBS_PLASMA_EXTENDERITEM_P_H
#include <QPointF>
#include <QPoint>
#include <QRect>
#include <QString>
class QGraphicsItem;
class QGraphicsWidget;
class QGraphicsLinearLayout;
class QGraphicsView;
class QTimer;
namespace Plasma
{
class Applet;
class ExtenderItem;
class Extender;
class Icon;
class PanelSvg;
class ExtenderItemPrivate
{
public:
ExtenderItemPrivate(ExtenderItem *extenderItem, Extender *hostExtender);
~ExtenderItemPrivate();
QRectF dragHandleRect();
QRectF titleRect();
bool leaveCurrentView(const QRect &rect);
QRect screenRect();
void toggleCollapse();
void updateToolBox();
void repositionToolbox();
QPointF scenePosFromScreenPos(const QPoint &pos) const;
Applet *hostApplet() const;
void themeChanged();
ExtenderItem *q;
QGraphicsItem *widget;
QGraphicsWidget *toolbox;
QGraphicsLinearLayout *toolboxLayout;
QGraphicsView *toplevel;
Extender *previousTargetExtender;
Extender *extender;
Applet *sourceApplet;
KConfigGroup config;
PanelSvg *dragger;
PanelSvg *background;
Icon *collapseIcon;
QMap<QString, QAction*> actions;
QString title;
QString name;
uint sourceAppletId;
uint extenderItemId;
qreal dragLeft, dragTop, dragRight, dragBottom;
qreal bgLeft, bgTop, bgRight, bgBottom;
QPointF deltaScene;
QPoint mousePos;
bool mousePressed;
bool mouseOver;
QTimer *expirationTimer;
static uint s_maxExtenderItemId;
};
}
#endif // LIB_PLASMA_EXTENDERITEM_P_H