Improved Extender support in popupApplet. Dialog resizes correctly, and even the last

item is removable. Implementation is still not perfect, but it's now a lot better then it 
was.


svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=853962
This commit is contained in:
Rob Scheepmaker 2008-08-28 14:32:48 +00:00
parent 20af95eee1
commit 1bae884531
7 changed files with 74 additions and 57 deletions

View File

@ -350,7 +350,6 @@ Containment* Corona::addContainmentDelayed(const QString& name, const QVariantLi
void Corona::addOffscreenWidget(QGraphicsWidget *widget) void Corona::addOffscreenWidget(QGraphicsWidget *widget)
{ {
kDebug() << "adding offscreen widget.";
widget->setParentItem(0); widget->setParentItem(0);
if (!d->offscreenLayout) { if (!d->offscreenLayout) {
kDebug() << "adding offscreen widget."; kDebug() << "adding offscreen widget.";
@ -362,6 +361,16 @@ void Corona::addOffscreenWidget(QGraphicsWidget *widget)
offscreenWidget->setLayout(d->offscreenLayout); offscreenWidget->setLayout(d->offscreenLayout);
} }
//check if the layout allready contains this widget.
//XXX: duplicated from removeOffscreenWidget()
for (int i = 0; i < d->offscreenLayout->count(); i++) {
QGraphicsWidget *foundWidget =
dynamic_cast<QGraphicsWidget*>(d->offscreenLayout->itemAt(i));
if (foundWidget == widget) {
return;
}
}
d->offscreenLayout->addItem(widget, d->offscreenLayout->rowCount() + 1, d->offscreenLayout->addItem(widget, d->offscreenLayout->rowCount() + 1,
d->offscreenLayout->columnCount() + 1); d->offscreenLayout->columnCount() + 1);
@ -381,6 +390,7 @@ void Corona::removeOffscreenWidget(QGraphicsWidget *widget)
dynamic_cast<QGraphicsWidget*>(d->offscreenLayout->itemAt(i)); dynamic_cast<QGraphicsWidget*>(d->offscreenLayout->itemAt(i));
if (foundWidget == widget) { if (foundWidget == widget) {
d->offscreenLayout->removeAt(i); d->offscreenLayout->removeAt(i);
d->offscreenLayout->invalidate();
} }
} }
} }

View File

@ -66,7 +66,6 @@ public:
void themeUpdated(); void themeUpdated();
void adjustView(); void adjustView();
Plasma::Dialog *q; Plasma::Dialog *q;
/** /**
* Holds the background SVG, to be re-rendered when the cache is invalidated, * Holds the background SVG, to be re-rendered when the cache is invalidated,
@ -89,9 +88,26 @@ void DialogPrivate::themeUpdated()
void DialogPrivate::adjustView() void DialogPrivate::adjustView()
{ {
if (view && widget) { if (view && widget) {
QSize prevSize = q->size();
//reposition and resize the view.
view->setSceneRect(widget->mapToScene(widget->boundingRect()).boundingRect()); view->setSceneRect(widget->mapToScene(widget->boundingRect()).boundingRect());
view->resize(widget->minimumSize().toSize()); view->resize(widget->preferredSize().toSize());
view->centerOn(widget); view->centerOn(widget);
//set the sizehints correctly:
int left, top, right, bottom;
q->getContentsMargins(&left, &top, &right, &bottom);
q->setMinimumSize(view->size().width() + left + right,
view->size().height() + top + bottom);
q->setMaximumSize(view->size().width() + left + right,
view->size().height() + top + bottom);
q->updateGeometry();
if (q->size() != prevSize) {
//the size of the dialog has changed, emit the signal:
emit q->dialogResized();
}
} }
} }
@ -171,12 +187,6 @@ QGraphicsWidget *Dialog::graphicsWidget()
return d->widget; return d->widget;
} }
void Dialog::adjustView()
{
d->adjustView();
adjustSize();
}
bool Dialog::eventFilter(QObject *watched, QEvent *event) bool Dialog::eventFilter(QObject *watched, QEvent *event)
{ {
if (watched == d->widget && (event->type() == QEvent::GraphicsSceneResize || if (watched == d->widget && (event->type() == QEvent::GraphicsSceneResize ||

View File

@ -61,12 +61,11 @@ class PLASMA_EXPORT Dialog : public QWidget
void setGraphicsWidget(QGraphicsWidget *widget); void setGraphicsWidget(QGraphicsWidget *widget);
QGraphicsWidget *graphicsWidget(); QGraphicsWidget *graphicsWidget();
public Q_SLOTS: Q_SIGNALS:
/** /**
* Call when the size of the graphicsWidget changes, to adjust the view and resize the * Fires when the dialog automatically resizes.
* dialog.
*/ */
void adjustView(); void dialogResized();
protected: protected:
/** /**
@ -78,6 +77,8 @@ class PLASMA_EXPORT Dialog : public QWidget
private: private:
DialogPrivate * const d; DialogPrivate * const d;
friend class DialogPrivate;
/** /**
* React to theme changes * React to theme changes
*/ */

View File

@ -162,8 +162,7 @@ void Extender::itemAddedEvent(ExtenderItem *item, const QPointF &pos)
//remove the empty extender message if needed. //remove the empty extender message if needed.
if (d->emptyExtenderLabel) { if (d->emptyExtenderLabel) {
d->layout->removeItem(d->emptyExtenderLabel); d->layout->removeItem(d->emptyExtenderLabel);
delete d->emptyExtenderLabel; d->emptyExtenderLabel->hide();
d->emptyExtenderLabel = 0;
} }
d->adjustSizeHints(); d->adjustSizeHints();
@ -176,9 +175,10 @@ void Extender::itemRemovedEvent(ExtenderItem *item)
d->layout->removeItem(item); d->layout->removeItem(item);
//add the empty extender message if needed. //add the empty extender message if needed.
if (!attachedItems().count() && !d->emptyExtenderLabel) { if (!attachedItems().count()) {
d->emptyExtenderLabel = new Label(this); d->emptyExtenderLabel->show();
d->emptyExtenderLabel->setText(d->emptyExtenderMessage); //just in case:
d->layout->removeItem(d->emptyExtenderLabel);
d->layout->addItem(d->emptyExtenderLabel); d->layout->addItem(d->emptyExtenderLabel);
} }
@ -187,7 +187,7 @@ void Extender::itemRemovedEvent(ExtenderItem *item)
void Extender::itemHoverEnterEvent(ExtenderItem *item) void Extender::itemHoverEnterEvent(ExtenderItem *item)
{ {
Q_UNUSED(item); itemHoverMoveEvent(item, QPointF(0, 0));
} }
void Extender::itemHoverMoveEvent(ExtenderItem *item, const QPointF &pos) void Extender::itemHoverMoveEvent(ExtenderItem *item, const QPointF &pos)
@ -215,8 +215,7 @@ void Extender::itemHoverMoveEvent(ExtenderItem *item, const QPointF &pos)
//XXX: duplicated from itemAttachedEvent. //XXX: duplicated from itemAttachedEvent.
if (d->emptyExtenderLabel) { if (d->emptyExtenderLabel) {
d->layout->removeItem(d->emptyExtenderLabel); d->layout->removeItem(d->emptyExtenderLabel);
delete d->emptyExtenderLabel; d->emptyExtenderLabel->hide();
d->emptyExtenderLabel = 0;
} }
d->adjustSizeHints(); d->adjustSizeHints();
@ -235,9 +234,9 @@ void Extender::itemHoverLeaveEvent(ExtenderItem *item)
d->currentSpacerIndex = -1; d->currentSpacerIndex = -1;
//Make sure we add a 'no detachables' label when the layout is empty. //Make sure we add a 'no detachables' label when the layout is empty.
if (!attachedItems().count() && !d->emptyExtenderLabel) { if (!attachedItems().count()) {
d->emptyExtenderLabel = new Label(this); d->emptyExtenderLabel->show();
d->emptyExtenderLabel->setText(d->emptyExtenderMessage); d->layout->removeItem(d->emptyExtenderLabel);
d->layout->addItem(d->emptyExtenderLabel); d->layout->addItem(d->emptyExtenderLabel);
} }

View File

@ -128,7 +128,6 @@ class ExtenderItemPrivate
void updateToolBox() { void updateToolBox() {
if (toolbox && dragger && toolboxLayout) { if (toolbox && dragger && toolboxLayout) {
kDebug() << "updating toolbox";
//clean the layout. //clean the layout.
uint iconHeight = dragger->elementSize("hint-preferred-icon-size").height(); uint iconHeight = dragger->elementSize("hint-preferred-icon-size").height();
@ -651,11 +650,9 @@ void ExtenderItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
parentApplet->raise(); parentApplet->raise();
setZValue(parentApplet->zValue()); setZValue(parentApplet->zValue());
d->extender->d->removeExtenderItem(this);
if (d->extender) { if (d->extender) {
d->extender->itemHoverEnterEvent(this); d->extender->itemHoverEnterEvent(this);
d->extender->itemHoverMoveEvent(this, d->extender->mapFromScene(event->scenePos())); //d->extender->itemHoverMoveEvent(this, d->extender->mapFromScene(event->scenePos()));
} }
//call the move event, since that spawns a toplevel view when this extender item is in a //call the move event, since that spawns a toplevel view when this extender item is in a
@ -663,13 +660,13 @@ void ExtenderItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
//able to receive any move events. //able to receive any move events.
mouseMoveEvent(event); mouseMoveEvent(event);
d->extender->d->removeExtenderItem(this);
QApplication::setOverrideCursor(Qt::ClosedHandCursor); QApplication::setOverrideCursor(Qt::ClosedHandCursor);
} }
void ExtenderItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) void ExtenderItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{ {
Q_UNUSED(event);
if (!d->mousePressed) { if (!d->mousePressed) {
return; return;
} }
@ -684,6 +681,8 @@ void ExtenderItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
screenRect.setTopLeft(event->screenPos() - d->mousePos); screenRect.setTopLeft(event->screenPos() - d->mousePos);
screenRect.setSize(d->screenRect().size()); screenRect.setSize(d->screenRect().size());
Corona *corona = d->hostApplet()->containment()->corona();
if (d->leaveCurrentView(screenRect)) { if (d->leaveCurrentView(screenRect)) {
//we're moving the applet to a toplevel view, so place it somewhere out of sight //we're moving the applet to a toplevel view, so place it somewhere out of sight
//first: in the topleft quadrant. //first: in the topleft quadrant.
@ -691,14 +690,9 @@ void ExtenderItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
if (!d->toplevel) { if (!d->toplevel) {
//XXX duplication from applethandle //XXX duplication from applethandle
//create a toplevel view and aim it at the applet. //create a toplevel view and aim it at the applet.
Corona *corona = d->hostApplet()->containment()->corona();
d->toplevel = new QGraphicsView(corona, 0); d->toplevel = new QGraphicsView(corona, 0);
//TODO: use addOffscreenWidget
if (sceneBoundingRect().left() > 0) { corona->addOffscreenWidget(this);
setParentItem(0);
//only move to topleft quadrant if it isn't there allready.
setPos(-12000, -12000);
}
d->toplevel->setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint d->toplevel->setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint
| Qt::WindowStaysOnTopHint); | Qt::WindowStaysOnTopHint);
@ -721,6 +715,7 @@ void ExtenderItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
d->toplevel->setSceneRect(sceneBoundingRect()); d->toplevel->setSceneRect(sceneBoundingRect());
d->toplevel->setGeometry(screenRect); d->toplevel->setGeometry(screenRect);
} else { } else {
corona->removeOffscreenWidget(this);
setParentItem(d->hostApplet()); setParentItem(d->hostApplet());
setPos(d->deltaScene); setPos(d->deltaScene);
@ -739,7 +734,6 @@ void ExtenderItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
//find the extender we're hovering over. //find the extender we're hovering over.
Extender *targetExtender = 0; Extender *targetExtender = 0;
Corona *corona = qobject_cast<Corona*>(scene());
foreach (Containment *containment, corona->containments()) { foreach (Containment *containment, corona->containments()) {
foreach (Applet *applet, containment->applets()) { foreach (Applet *applet, containment->applets()) {
if (applet->extender() && (applet->sceneBoundingRect().contains(mousePos) if (applet->extender() && (applet->sceneBoundingRect().contains(mousePos)
@ -813,6 +807,9 @@ void ExtenderItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
//find the extender we're hovering over. //find the extender we're hovering over.
Extender *targetExtender = 0; Extender *targetExtender = 0;
Corona *corona = qobject_cast<Corona*>(scene()); Corona *corona = qobject_cast<Corona*>(scene());
corona->removeOffscreenWidget(this);
foreach (Containment *containment, corona->containments()) { foreach (Containment *containment, corona->containments()) {
foreach (Applet *applet, containment->applets()) { foreach (Applet *applet, containment->applets()) {
if (applet->extender() && (applet->sceneBoundingRect().contains(mousePos) if (applet->extender() && (applet->sceneBoundingRect().contains(mousePos)

View File

@ -62,6 +62,7 @@ public:
void togglePopup(); void togglePopup();
void hideTimedPopup(); void hideTimedPopup();
void dialogSizeChanged();
PopupApplet *q; PopupApplet *q;
Plasma::Icon *icon; Plasma::Icon *icon;
@ -207,6 +208,7 @@ void PopupApplet::constraintsEvent(Plasma::Constraints constraints)
if (!d->dialog) { if (!d->dialog) {
d->dialog = new Plasma::Dialog(); d->dialog = new Plasma::Dialog();
d->dialog->setWindowFlags(Qt::Popup); d->dialog->setWindowFlags(Qt::Popup);
connect(d->dialog, SIGNAL(dialogResized()), this, SLOT(dialogSizeChanged()));
if (graphicsWidget()) { if (graphicsWidget()) {
Corona *corona = qobject_cast<Corona *>(graphicsWidget()->scene()); Corona *corona = qobject_cast<Corona *>(graphicsWidget()->scene());
@ -241,7 +243,6 @@ void PopupApplet::constraintsEvent(Plasma::Constraints constraints)
void PopupApplet::showPopup(uint popupDuration) void PopupApplet::showPopup(uint popupDuration)
{ {
if (d->dialog && (formFactor() == Horizontal || formFactor() == Vertical)) { if (d->dialog && (formFactor() == Horizontal || formFactor() == Vertical)) {
d->dialog->adjustView();
d->dialog->move(popupPosition(d->dialog->size())); d->dialog->move(popupPosition(d->dialog->size()));
d->dialog->show(); d->dialog->show();
@ -269,24 +270,13 @@ void PopupApplet::hidePopup()
void PopupApplet::widgetGeometryChanged() void PopupApplet::widgetGeometryChanged()
{ {
if (graphicsWidget()) { if (graphicsWidget() && layout()) {
//sizes are recalculated in the constraintsevent so let's just call that. //sizes are recalculated in the constraintsevent so let's just call that.
if (layout()) {
constraintsEvent(Plasma::FormFactorConstraint); constraintsEvent(Plasma::FormFactorConstraint);
//resize vertically if necesarry. //resize vertically if necesarry.
if (formFactor() == Plasma::MediaCenter || formFactor() == Plasma::Planar) { if (formFactor() == Plasma::MediaCenter || formFactor() == Plasma::Planar) {
resize(QSizeF(size().width(), minimumHeight())); resize(QSizeF(size().width(), minimumHeight()));
} else {
if (graphicsWidget()) {
graphicsWidget()->resize(graphicsWidget()->minimumSize());
graphicsWidget()->update();
}
if (d->dialog) {
d->dialog->adjustView();
d->dialog->move(popupPosition(d->dialog->size()));
}
}
} }
} }
} }
@ -297,7 +287,7 @@ void PopupAppletPrivate::togglePopup()
if (dialog->isVisible()) { if (dialog->isVisible()) {
dialog->hide(); dialog->hide();
} else { } else {
dialog->move(q->popupPosition(dialog->sizeHint())); dialog->move(q->popupPosition(dialog->size()));
dialog->show(); dialog->show();
} }
@ -311,6 +301,15 @@ void PopupAppletPrivate::hideTimedPopup()
q->hidePopup(); q->hidePopup();
} }
void PopupAppletPrivate::dialogSizeChanged()
{
//Reposition the dialog.
if (dialog) {
dialog->updateGeometry();
dialog->move(q->popupPosition(dialog->size()));
}
}
} // Plasma namespace } // Plasma namespace
#include "popupapplet.moc" #include "popupapplet.moc"

View File

@ -106,6 +106,7 @@ protected:
private: private:
Q_PRIVATE_SLOT(d, void togglePopup()) Q_PRIVATE_SLOT(d, void togglePopup())
Q_PRIVATE_SLOT(d, void hideTimedPopup()) Q_PRIVATE_SLOT(d, void hideTimedPopup())
Q_PRIVATE_SLOT(d, void dialogSizeChanged())
PopupAppletPrivate * const d; PopupAppletPrivate * const d;
}; };