Let corona layout the containments

Now corona will layout it's containments instead of letting
them do this task. This was created as a slot so we could preserve
BC. Subclasses of Plasma::Corona must be sure to skip containments
of Panel type during layouting if they wish to reimplement it to
have their own layout.

If subclasses doesn't care about it, just leave it alone and
everything will work just as before. :)

Reviewed-by: aseigo, notmart

svn path=/trunk/KDE/kdelibs/; revision=1095549
This commit is contained in:
Artur Duque de Souza 2010-02-24 14:24:52 +00:00
parent 7fb501467a
commit 060bf4148f
4 changed files with 108 additions and 91 deletions

View File

@ -73,7 +73,7 @@
namespace Plasma
{
bool ContainmentPrivate::s_positioning = false;
bool ContainmentPrivate::s_positioningPanels = false;
static const char defaultWallpaper[] = "image";
static const char defaultWallpaperMode[] = "SingleImage";
@ -1588,16 +1588,16 @@ void Containment::resizeEvent(QGraphicsSceneResizeEvent *event)
{
Applet::resizeEvent(event);
if (!ContainmentPrivate::s_positioning) {
switch (d->type) {
case Containment::PanelContainment:
case Containment::CustomPanelContainment:
d->positionPanel();
break;
default:
d->positionContainments();
break;
}
switch (d->type) {
case Containment::PanelContainment:
case Containment::CustomPanelContainment:
d->positionPanel();
break;
default:
if (corona()) {
corona()->layoutContainments();
}
break;
}
if (d->wallpaper) {
@ -1704,15 +1704,18 @@ QVariant Containment::itemChange(GraphicsItemChange change, const QVariant &valu
{
//FIXME if the applet is moved to another containment we need to unfocus it
if (isContainment() && !ContainmentPrivate::s_positioning &&
(change == QGraphicsItem::ItemSceneHasChanged || change == QGraphicsItem::ItemPositionHasChanged)) {
if (isContainment() &&
(change == QGraphicsItem::ItemSceneHasChanged ||
change == QGraphicsItem::ItemPositionHasChanged)) {
switch (d->type) {
case PanelContainment:
case CustomPanelContainment:
d->positionPanel();
break;
default:
d->positionContainments();
if (corona()) {
corona()->layoutContainments();
}
break;
}
}
@ -2310,80 +2313,6 @@ void ContainmentPrivate::appletAppearAnimationComplete()
}
}
bool containmentSortByPosition(const Containment *c1, const Containment *c2)
{
return c1->id() < c2->id();
}
void ContainmentPrivate::positionContainments()
{
Corona *c = q->corona();
if (!c || ContainmentPrivate::s_positioning) {
return;
}
ContainmentPrivate::s_positioning = true;
//TODO: we should avoid running this too often; consider compressing requests
// with a timer.
QList<Containment*> containments = c->containments();
QMutableListIterator<Containment*> it(containments);
while (it.hasNext()) {
Containment *containment = it.next();
if (containment->d->type == Containment::PanelContainment ||
containment->d->type == Containment::CustomPanelContainment ||
q->corona()->offscreenWidgets().contains(containment)) {
// weed out all containments we don't care about at all
// e.g. Panels and ourself
it.remove();
continue;
}
}
if (containments.isEmpty()) {
ContainmentPrivate::s_positioning = false;
return;
}
qSort(containments.begin(), containments.end(), containmentSortByPosition);
it.toFront();
int column = 0;
int x = 0;
int y = 0;
int rowHeight = 0;
//int count = 0;
//kDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++" << containments.count();
while (it.hasNext()) {
Containment *containment = it.next();
containment->setPos(x, y);
//kDebug() << ++count << "setting to" << x << y;
int height = containment->size().height();
if (height > rowHeight) {
rowHeight = height;
}
++column;
if (column == CONTAINMENT_COLUMNS) {
column = 0;
x = 0;
y += rowHeight + INTER_CONTAINMENT_MARGIN + TOOLBOX_MARGIN;
rowHeight = 0;
} else {
x += containment->size().width() + INTER_CONTAINMENT_MARGIN;
}
//kDebug() << "column: " << column << "; x " << x << "; y" << y << "; width was"
// << containment->size().width();
}
//kDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++";
ContainmentPrivate::s_positioning = false;
}
void ContainmentPrivate::positionPanel(bool force)
{
if (!q->scene()) {
@ -2391,6 +2320,11 @@ void ContainmentPrivate::positionPanel(bool force)
return;
}
// already positioning the panel - avoid infinite loops
if (ContainmentPrivate::s_positioningPanels) {
return;
}
// we position panels in negative coordinates, and stack all horizontal
// and all vertical panels with each other.
@ -2454,9 +2388,9 @@ void ContainmentPrivate::positionPanel(bool force)
}
if (p != newPos) {
ContainmentPrivate::s_positioning = true;
ContainmentPrivate::s_positioningPanels = true;
q->setPos(newPos);
ContainmentPrivate::s_positioning = false;
ContainmentPrivate::s_positioningPanels = false;
}
}

View File

@ -253,6 +253,8 @@ public:
void offscreenWidgetDestroyed(QObject *);
static bool s_positioningContainments;
Corona *q;
ImmutabilityType immutability;
QString mimetype;
@ -266,6 +268,8 @@ public:
QMap<Containment::Type, ContainmentActionsPluginsConfig> containmentActionsDefaults;
};
bool CoronaPrivate::s_positioningContainments = false;
Corona::Corona(QObject *parent)
: QGraphicsScene(parent),
d(new CoronaPrivate(this))
@ -350,6 +354,77 @@ void Corona::initializeLayout(const QString &configName)
setImmutability((ImmutabilityType)coronaConfig.readEntry("immutability", (int)Mutable));
}
bool containmentSortByPosition(const Containment *c1, const Containment *c2)
{
return c1->id() < c2->id();
}
void Corona::layoutContainments()
{
if (CoronaPrivate::s_positioningContainments) {
return;
}
CoronaPrivate::s_positioningContainments = true;
//TODO: we should avoid running this too often; consider compressing requests
// with a timer.
QList<Containment*> c = containments();
QMutableListIterator<Containment*> it(c);
while (it.hasNext()) {
Containment *containment = it.next();
if (containment->containmentType() == Containment::PanelContainment ||
containment->containmentType() == Containment::CustomPanelContainment ||
offscreenWidgets().contains(containment)) {
// weed out all containments we don't care about at all
// e.g. Panels and ourself
it.remove();
continue;
}
}
qSort(c.begin(), c.end(), containmentSortByPosition);
if (c.isEmpty()) {
CoronaPrivate::s_positioningContainments = false;
return;
}
int column = 0;
int x = 0;
int y = 0;
int rowHeight = 0;
it.toFront();
while (it.hasNext()) {
Containment *containment = it.next();
containment->setPos(x, y);
//kDebug() << ++count << "setting to" << x << y;
int height = containment->size().height();
if (height > rowHeight) {
rowHeight = height;
}
++column;
if (column == CONTAINMENT_COLUMNS) {
column = 0;
x = 0;
y += rowHeight + INTER_CONTAINMENT_MARGIN + TOOLBOX_MARGIN;
rowHeight = 0;
} else {
x += containment->size().width() + INTER_CONTAINMENT_MARGIN;
}
//kDebug() << "column: " << column << "; x " << x << "; y" << y << "; width was"
// << containment->size().width();
}
CoronaPrivate::s_positioningContainments = false;
}
void Corona::loadLayout(const QString &configName)
{
KSharedConfigPtr c;

View File

@ -289,6 +289,14 @@ public Q_SLOTS:
*/
void requireConfigSync();
/**
* @since 4.5
* Layout the containments on this corona. The default implementation
* organizes them in a grid-like view, but subclasses can reimplement
* this slot to provide their own layout.
*/
void layoutContainments();
Q_SIGNALS:
/**
* This signal indicates a new containment has been added to

View File

@ -143,7 +143,7 @@ public:
*/
void showDropZoneDelayed();
static bool s_positioning;
static bool s_positioningPanels;
Containment *q;
FormFactor formFactor;