No longer use a QGraphicsGridLayout to manage offscreen widgets in corona. Instead position them manually and give each one a spot where they can grow up to QWIDGETSIZEMAX. This has the advantage of not requiring hacks to work around QGL problems, and it avoids having to move all views when one item resizes. It feels snappier and the code looks cleaner.

svn path=/trunk/KDE/kdelibs/; revision=895118
This commit is contained in:
Rob Scheepmaker 2008-12-10 00:57:42 +00:00
parent a6140d5a27
commit 72eaf8c5f7
5 changed files with 70 additions and 106 deletions

View File

@ -55,8 +55,7 @@ public:
: q(corona),
immutability(Mutable),
mimetype("text/x-plasmoidservicename"),
config(0),
offscreenLayout(0)
config(0)
{
if (KGlobal::hasMainComponent()) {
configName = KGlobal::mainComponent().componentName() + "-appletsrc";
@ -189,7 +188,7 @@ public:
KSharedConfigPtr config;
QTimer configSyncTimer;
QList<Containment*> containments;
QGraphicsGridLayout *offscreenLayout;
QHash<uint, QGraphicsWidget*> offscreenWidgets;
};
Corona::Corona(QObject *parent)
@ -368,73 +367,47 @@ Containment *Corona::addContainmentDelayed(const QString &name, const QVariantLi
void Corona::addOffscreenWidget(QGraphicsWidget *widget)
{
widget->setParentItem(0);
if (!d->offscreenLayout) {
kDebug() << "adding offscreen widget.";
QGraphicsWidget *offscreenWidget = new QGraphicsWidget(0);
addItem(offscreenWidget);
d->offscreenLayout = new QGraphicsGridLayout(offscreenWidget);
//FIXME: do this a nice way.
offscreenWidget->setPos(-10000, -10000);
offscreenWidget->setLayout(d->offscreenLayout);
}
//check if the layout already 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->columnCount() + 1);
// this is lame: adding a widget to a layout and then deleting it
// doesn't automatically remove it from the layout, so we have to watch for that ourselves
connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(offscreenWidgetDestroyed(QObject*)));
widget->update();
}
//FIXME: remove the offscreenWidgetDestroyed method when QGraphicsLayout no longer
// craps up when an item in the layout is deleted!
void CoronaPrivate::offscreenWidgetDestroyed(QObject *o)
{
if (!offscreenLayout) {
if (d->offscreenWidgets.values().contains(widget)) {
return;
}
// at this point, it's just a QObject, not a QGraphicsWidget, but we still need
// a pointer of the appropriate type.
// WARNING: DO NOT USE THE WIDGET POINTER FOR ANYTHING OTHER THAN POINTER COMPARISONS
QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(o);
for (int i = 0; i < offscreenLayout->count(); i++) {
// we have to static_cast here as well, even though that's not overly correct
// or wonderful; but it's the best we can do as the item is no longer a
// QGraphicsWidget at this point, just a QObject
QGraphicsWidget *foundWidget = static_cast<QGraphicsWidget *>(offscreenLayout->itemAt(i));
if (foundWidget == widget) {
offscreenLayout->removeAt(i);
}
widget->setParentItem(0);
//search for an empty spot in the topleft quadrant of the scene. each 'slot' is QWIDGETSIZE_MAX
//x QWIDGETSIZE_MAX, so we're guaranteed to never have to move widgets once they're placed here.
int i = 0;
while (d->offscreenWidgets.contains(i)) {
i++;
}
d->offscreenWidgets[i] = widget;
widget->setPos((-i - 1) * QWIDGETSIZE_MAX, -QWIDGETSIZE_MAX);
kDebug() << "adding offscreen widget at slot " << i;
connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(offscreenWidgetDestroyed(QObject*)));
}
void Corona::removeOffscreenWidget(QGraphicsWidget *widget)
{
if (!d->offscreenLayout) {
return;
}
QMutableHashIterator<uint, QGraphicsWidget *> it(d->offscreenWidgets);
for (int i = 0; i < d->offscreenLayout->count(); i++) {
QGraphicsWidget *foundWidget = dynamic_cast<QGraphicsWidget*>(d->offscreenLayout->itemAt(i));
if (foundWidget == widget) {
d->offscreenLayout->removeAt(i);
disconnect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(offscreenWidgetDestroyed(QObject*)));
break;
while (it.hasNext()) {
if (it.next().value() == widget) {
it.remove();
return;
}
}
}
void CoronaPrivate::offscreenWidgetDestroyed(QObject *o)
{
// at this point, it's just a QObject, not a QGraphicsWidget, but we still need
// a pointer of the appropriate type.
// WARNING: DO NOT USE THE WIDGET POINTER FOR ANYTHING OTHER THAN POINTER COMPARISONS
QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(o);
q->removeOffscreenWidget(widget);
}
int Corona::numScreens() const
{
return 1;

View File

@ -486,6 +486,8 @@ void ExtenderPrivate::adjustSizeHints()
applet->adjustSize();
}
q->adjustSize();
emit q->geometryChanged();
}

View File

@ -488,42 +488,17 @@ void ExtenderItem::moveEvent(QGraphicsSceneMoveEvent *event)
if (d->toplevel) {
d->toplevel->setSceneRect(sceneBoundingRect());
update();
d->toplevel->setMask(d->background->mask());
}
}
void ExtenderItem::resizeEvent(QGraphicsSceneResizeEvent *event)
{
qreal width = event->newSize().width();
qreal height = event->newSize().height();
//resize the dragger
d->dragger->resizeFrame(QSizeF(width - d->bgLeft - d->bgRight,
d->iconSize() +
d->dragTop + d->dragBottom));
//resize the applet background
d->background->resizeFrame(event->newSize());
//resize the widget
if (d->widget && d->widget->isWidget()) {
QSizeF newWidgetSize(width - d->bgLeft - d->bgRight - d->dragLeft - d->dragRight,
height - d->dragHandleRect().height() - d->bgTop - d->bgBottom -
2 * d->dragTop - 2 * d->dragBottom);
QGraphicsWidget *graphicsWidget = static_cast<QGraphicsWidget*>(d->widget);
graphicsWidget->resize(newWidgetSize);
}
//reposition the toolbox.
d->repositionToolbox();
update();
d->resizeContent(event->newSize());
if (d->toplevel) {
d->toplevel->setSceneRect(sceneBoundingRect());
d->toplevel->setMask(d->background->mask());
update();
}
}
@ -543,8 +518,8 @@ void ExtenderItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
void ExtenderItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (!d->dragStarted && (d->mousePos - event->pos().toPoint()).manhattanLength()
>= QApplication::startDragDistance()) {
if (d->mousePressed && !d->dragStarted &&
(d->mousePos - event->pos().toPoint()).manhattanLength() >= QApplication::startDragDistance()) {
//start the drag:
d->dragStarted = true;
@ -588,26 +563,20 @@ void ExtenderItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
d->toplevel->setWindowFlags(
Qt::ToolTip | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
d->toplevel->setFrameShape(QFrame::NoFrame);
d->toplevel->resize(screenRect.size());
d->toplevel->setSceneRect(sceneBoundingRect());
d->toplevel->centerOn(this);
//We might have to scale the view, because we might be zoomed out.
qreal scale = screenRect.width() / size().width();
d->toplevel->scale(scale, scale);
d->toplevel->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
d->toplevel->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
d->toplevel->setFrameShape(QFrame::NoFrame);
d->toplevel->setSceneRect(sceneBoundingRect());
d->toplevel->setGeometry(screenRect);
d->toplevel->setMask(d->background->mask());
d->toplevel->update();
d->toplevel->show();
}
d->toplevel->setSceneRect(sceneBoundingRect());
d->toplevel->setGeometry(screenRect);
d->toplevel->setMask(d->background->mask());
} else {
corona->removeOffscreenWidget(this);
setParentItem(d->hostApplet());
@ -1032,7 +1001,7 @@ void ExtenderItemPrivate::themeChanged()
//setCollapsed recalculates size hints.
q->setCollapsed(q->isCollapsed());
q->update();
resizeContent(q->size());
}
void ExtenderItemPrivate::sourceAppletRemoved()
@ -1057,6 +1026,34 @@ qreal ExtenderItemPrivate::iconSize()
return qMax(size.height(), (qreal) fm.height());
}
void ExtenderItemPrivate::resizeContent(const QSizeF &newSize)
{
qreal width = newSize.width();
qreal height = newSize.height();
//resize the dragger
dragger->resizeFrame(QSizeF(width - bgLeft - bgRight,
iconSize() + dragTop + dragBottom));
//resize the applet background
background->resizeFrame(newSize);
//resize the widget
if (widget && widget->isWidget()) {
QSizeF newWidgetSize(width - bgLeft - bgRight - dragLeft - dragRight,
height - dragHandleRect().height() - bgTop - bgBottom -
2 * dragTop - 2 * dragBottom);
QGraphicsWidget *graphicsWidget = static_cast<QGraphicsWidget*>(widget);
graphicsWidget->resize(newWidgetSize);
}
//reposition the toolbox.
repositionToolbox();
q->update();
}
uint ExtenderItemPrivate::s_maxExtenderItemId = 0;
} // namespace Plasma

View File

@ -289,15 +289,6 @@ void PopupAppletPrivate::popupConstraintsEvent(Plasma::Constraints constraints)
//could that cast ever fail??
if (corona) {
corona->addOffscreenWidget(gWidget);
//necessary to mess around with the offscreen widget
QGraphicsLayoutItem *layout = gWidget->parentLayoutItem();
QGraphicsWidget *parentWidget = gWidget->parentWidget();
if (layout && parentWidget) {
layout->updateGeometry();
parentWidget->resize(layout->preferredSize());
}
dialog->setGraphicsWidget(gWidget);
}
} else if (qWidget) {

View File

@ -57,6 +57,7 @@ class ExtenderItemPrivate
void themeChanged();
void sourceAppletRemoved();
qreal iconSize();
void resizeContent(const QSizeF &newSize);
ExtenderItem *q;