ok, this is a much, much easier way to approach the grouping and doesn't require QDesktopWidget either

svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=873703
This commit is contained in:
Aaron J. Seigo 2008-10-20 00:42:50 +00:00
parent 8005bf4a73
commit b31b4da0ba
2 changed files with 42 additions and 76 deletions

View File

@ -59,6 +59,7 @@
namespace Plasma namespace Plasma
{ {
bool ContainmentPrivate::s_positioning = false;
static const char defaultWallpaper[] = "image"; static const char defaultWallpaper[] = "image";
static const char defaultWallpaperMode[] = "SingleImage"; static const char defaultWallpaperMode[] = "SingleImage";
@ -1086,7 +1087,7 @@ QVariant Containment::itemChange(GraphicsItemChange change, const QVariant &valu
if (isContainment() && if (isContainment() &&
(change == QGraphicsItem::ItemSceneHasChanged || (change == QGraphicsItem::ItemSceneHasChanged ||
change == QGraphicsItem::ItemPositionHasChanged) && !d->positioning) { change == QGraphicsItem::ItemPositionHasChanged) && !ContainmentPrivate::s_positioning) {
switch (containmentType()) { switch (containmentType()) {
case PanelContainment: case PanelContainment:
case CustomPanelContainment: case CustomPanelContainment:
@ -1609,7 +1610,7 @@ void ContainmentPrivate::containmentConstraintsEvent(Plasma::Constraints constra
} }
} }
if (constraints & Plasma::SizeConstraint) { if (constraints & Plasma::SizeConstraint && !ContainmentPrivate::s_positioning) {
switch (q->containmentType()) { switch (q->containmentType()) {
case Containment::PanelContainment: case Containment::PanelContainment:
case Containment::CustomPanelContainment: case Containment::CustomPanelContainment:
@ -1708,6 +1709,11 @@ void ContainmentPrivate::containmentAppletAnimationComplete(QGraphicsItem *item,
} }
} }
bool containmentSortByPosition(const Containment *c1, const Containment *c2)
{
return c1->id() < c2->id();
}
void ContainmentPrivate::positionContainment() void ContainmentPrivate::positionContainment()
{ {
Corona *c = q->corona(); Corona *c = q->corona();
@ -1715,102 +1721,63 @@ void ContainmentPrivate::positionContainment()
return; return;
} }
//TODO: we should avoid running this too often; consider compressing requests
// with a timer.
QList<Containment*> containments = c->containments(); QList<Containment*> containments = c->containments();
QMutableListIterator<Containment*> it(containments); QMutableListIterator<Containment*> it(containments);
bool noCollissions = true;
while (it.hasNext()) { while (it.hasNext()) {
Containment *containment = it.next(); Containment *containment = it.next();
if (containment == q || if (containment->containmentType() == Containment::PanelContainment ||
containment->containmentType() == Containment::PanelContainment ||
containment->containmentType() == Containment::CustomPanelContainment) { containment->containmentType() == Containment::CustomPanelContainment) {
// weed out all containments we don't care about at all // weed out all containments we don't care about at all
// e.g. Panels and ourself // e.g. Panels and ourself
it.remove(); it.remove();
continue; continue;
} }
if (noCollissions && q->collidesWithItem(containment)) {
noCollissions = false;
}
} }
if (noCollissions) { if (containments.isEmpty()) {
// we made it all the way through the list, we have no
// collisions
return; return;
} }
int width = 0; qSort(containments.begin(), containments.end(), containmentSortByPosition);
int height = 0;
QDesktopWidget *desktop = QApplication::desktop();
int numScreens = desktop->numScreens();
for (int i = 0; i < numScreens; ++i) {
QRect otherScreen = desktop->screenGeometry(i);
if (width < otherScreen.width()) {
width = otherScreen.width();
}
if (height < otherScreen.height()) {
height = otherScreen.height();
}
}
width = (width + INTER_CONTAINMENT_MARGIN) * CONTAINMENT_COLUMNS;
height += INTER_CONTAINMENT_MARGIN;
// a mildly naive "find the first slot" approach
QRectF r = q->boundingRect();
QPointF topLeft(0, 0);
q->setPos(topLeft);
positioning = true;
while (true) {
it.toFront(); it.toFront();
int shift = 0;
int column = 0;
int x = 0;
int y = 0;
int rowHeight = 0;
//int count = 0;
ContainmentPrivate::s_positioning = true;
//kDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++" << containments.count();
while (it.hasNext()) { while (it.hasNext()) {
Containment *containment = it.next(); Containment *containment = it.next();
containment->setPos(x, y);
//kDebug() << ++count << "setting to" << x << y;
if (q->collidesWithItem(containment)) { int height = containment->size().height();
shift = containment->geometry().right(); if (height > rowHeight) {
/*kDebug() << (QObject*)q << "collides with" << (QObject*)containment rowHeight = height;
<< containment->geometry() << "so shift to: " << shift;*/
//TODO: is it safe to remove a containment once we've
// collided with it?
break;
} }
QPointF pos = containment->pos(); ++column;
if (pos.x() <= topLeft.x() && pos.y() <= topLeft.y()) {
// we don't colid with this containment, and it's above
// and to the left of us, so let's not bother checking
// it again if we go through this loop again
it.remove();
}
}
if (shift == 0) { if (column == CONTAINMENT_COLUMNS) {
// success! no collisions! column = 0;
break; x = 0;
} y += rowHeight + INTER_CONTAINMENT_MARGIN;
rowHeight = 0;
if (shift + r.width() + INTER_CONTAINMENT_MARGIN > width) {
// we ran out of width room, try another row
topLeft = QPoint(0, topLeft.y() + height);
} else { } else {
topLeft.setX(shift + INTER_CONTAINMENT_MARGIN); x += containment->size().width() + INTER_CONTAINMENT_MARGIN;
} }
//kDebug() << "column: " << column << "; x " << x << "; y" << y << "; width was"
q->setPos(topLeft); // << containment->size().width();
//kDebug() << "trying at" << topLeft << q->geometry();
//kDebug() << collidingItems().count() << collidingItems()[0] << (QGraphicsItem*)this;
} }
//kDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++";
positioning = false; ContainmentPrivate::s_positioning = false;
} }
void ContainmentPrivate::positionPanel(bool force) void ContainmentPrivate::positionPanel(bool force)
@ -1881,12 +1848,12 @@ void ContainmentPrivate::positionPanel(bool force)
newPos = QPointF(bottom + q->size().width(), -INTER_CONTAINMENT_MARGIN - q->size().height()); newPos = QPointF(bottom + q->size().width(), -INTER_CONTAINMENT_MARGIN - q->size().height());
} }
positioning = true; ContainmentPrivate::s_positioning = true;
if (p != newPos) { if (p != newPos) {
q->setPos(newPos); q->setPos(newPos);
emit q->geometryChanged(); emit q->geometryChanged();
} }
positioning = false; ContainmentPrivate::s_positioning = false;
} }
} // Plasma namespace } // Plasma namespace

View File

@ -44,7 +44,6 @@ public:
toolBox(0), toolBox(0),
con(0), con(0),
type(Containment::NoContainmentType), type(Containment::NoContainmentType),
positioning(false),
drawWallpaper(true) drawWallpaper(true)
{ {
} }
@ -111,7 +110,7 @@ public:
ToolBox *toolBox; ToolBox *toolBox;
Context *con; Context *con;
Containment::Type type; Containment::Type type;
bool positioning; static bool s_positioning;
bool drawWallpaper; bool drawWallpaper;
}; };