- add Contaiment to the build

- put applets in the center of the screen not the top left (i really wish people wouldn't commit obvious regressions like that? the code was ifdef 0'd out!)
- create a Containment per-screen (in the xinerama sense)
- new loading/saving code; not overly comfortable with it yet but it works and maintains the single-pass semantics as well as the option for us to delay calling init() if we decide to do so in the future
- misc fixes here and there

svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=714175
This commit is contained in:
Aaron J. Seigo 2007-09-18 21:25:15 +00:00
parent 2c63daad12
commit f0cb7e662c
3 changed files with 180 additions and 173 deletions

View File

@ -18,6 +18,7 @@ set(plasma_LIB_SRCS
animator.cpp animator.cpp
applet.cpp applet.cpp
configxml.cpp configxml.cpp
containment.cpp
corona.cpp corona.cpp
datacontainer.cpp datacontainer.cpp
dataengine.cpp dataengine.cpp
@ -52,6 +53,10 @@ set(plasma_LIB_SRCS
widgets/signalplotter.cpp widgets/signalplotter.cpp
) )
set(krunner_xml ${KDEBASE_WORKSPACE_SOURCE_DIR}/krunner/org.kde.krunner.Interface.xml)
QT4_ADD_DBUS_INTERFACE(plasma_LIB_SRCS ${krunner_xml} krunner_interface)
if(QT_QTOPENGL_FOUND AND OPENGL_FOUND) if(QT_QTOPENGL_FOUND AND OPENGL_FOUND)
MESSAGE(STATUS "Adding support for OpenGL applets to libplasma") MESSAGE(STATUS "Adding support for OpenGL applets to libplasma")
set(plasma_LIB_SRCS set(plasma_LIB_SRCS
@ -82,6 +87,7 @@ set(plasma_LIB_INCLUDES
animator.h animator.h
applet.h applet.h
configxml.h configxml.h
containment.h
corona.h corona.h
datacontainer.h datacontainer.h
dataengine.h dataengine.h

View File

@ -34,7 +34,7 @@
#include <KMimeType> #include <KMimeType>
#include <KWindowSystem> #include <KWindowSystem>
#include "applet.h" #include "containment.h"
#include "dataengine.h" #include "dataengine.h"
#include "karambamanager.h" #include "karambamanager.h"
#include "phase.h" #include "phase.h"
@ -52,31 +52,24 @@ class Corona::Private
public: public:
Private() Private()
: immutable(false), : immutable(false),
formFactor(Planar),
location(Floating),
layout(new FreeLayout),
mimetype("text/x-plasmoidservicename") mimetype("text/x-plasmoidservicename")
{ {
} }
~Private() ~Private()
{ {
qDeleteAll(applets);
delete layout;
} }
bool immutable; bool immutable;
Applet::List applets;
FormFactor formFactor;
Location location;
Layout* layout;
QString mimetype; QString mimetype;
QList<Containment*> containments;
}; };
Corona::Corona(QObject *parent) Corona::Corona(QObject *parent)
: QGraphicsScene(parent), : QGraphicsScene(parent),
d(new Private) d(new Private)
{ {
//d->init(this);
//setViewport(new QGLWidget(QGLFormat(QGL::StencilBuffer | QGL::AlphaChannel))); //setViewport(new QGLWidget(QGLFormat(QGL::StencilBuffer | QGL::AlphaChannel)));
} }
@ -84,6 +77,7 @@ Corona::Corona(const QRectF & sceneRect, QObject * parent )
: QGraphicsScene(sceneRect, parent), : QGraphicsScene(sceneRect, parent),
d(new Private) d(new Private)
{ {
//d->init(this);
//setViewport(new QGLWidget(QGLFormat(QGL::StencilBuffer | QGL::AlphaChannel))); //setViewport(new QGLWidget(QGLFormat(QGL::StencilBuffer | QGL::AlphaChannel)));
} }
@ -91,6 +85,7 @@ Corona::Corona(qreal x, qreal y, qreal width, qreal height, QObject * parent)
: QGraphicsScene(x, y, width, height, parent), : QGraphicsScene(x, y, width, height, parent),
d(new Private) d(new Private)
{ {
//d->init(this);
//setViewport(new QGLWidget(QGLFormat(QGL::StencilBuffer | QGL::AlphaChannel))); //setViewport(new QGLWidget(QGLFormat(QGL::StencilBuffer | QGL::AlphaChannel)));
} }
@ -99,62 +94,6 @@ Corona::~Corona()
delete d; delete d;
} }
Location Corona::location() const
{
return d->location;
}
void Corona::setLocation(Location location)
{
if (d->location == location) {
return;
}
d->location = location;
foreach (Applet* applet, d->applets) {
applet->updateConstraints();
}
}
FormFactor Corona::formFactor() const
{
return d->formFactor;
}
void Corona::setFormFactor(FormFactor formFactor)
{
if (d->formFactor == formFactor) {
return;
}
//kDebug() << "switching FF to " << formFactor;
d->formFactor = formFactor;
delete d->layout;
d->layout = 0;
switch (d->formFactor) {
case Planar:
d->layout = new FreeLayout;
break;
case Horizontal:
d->layout = new BoxLayout(BoxLayout::LeftToRight);
break;
case Vertical:
d->layout = new BoxLayout(BoxLayout::TopToBottom);
break;
case MediaCenter:
break;
default:
kDebug() << "This can't be happening!";
break;
}
foreach (Applet* applet, d->applets) {
applet->updateConstraints();
}
}
QRectF Corona::maxSizeHint() const QRectF Corona::maxSizeHint() const
{ {
//FIXME: this is a bit of a naive implementation, do you think? =) //FIXME: this is a bit of a naive implementation, do you think? =)
@ -174,16 +113,21 @@ QString Corona::appletMimeType()
void Corona::saveApplets(const QString &config) const void Corona::saveApplets(const QString &config) const
{ {
KConfig appletConfig(config); KConfig cg(config);
foreach (const QString& group, appletConfig.groupList()) { foreach (const QString& group, cg.groupList()) {
appletConfig.deleteGroup(group); cg.deleteGroup(group);
} }
foreach (Applet *applet, d->applets) { QStringList containmentIds;
KConfigGroup cg(&appletConfig, QString::number(applet->id())); foreach (const Containment *containment, d->containments) {
//kDebug() << "saving applet " << applet->name(); QString cid = QString::number(containment->id());
cg.writeEntry("plugin", applet->pluginName()); KConfigGroup containmentConfig(&cg, cid.append("-containment"));
cg.writeEntry("geometry", QRect(applet->pos().toPoint(), applet->boundingRect().size().toSize())); containment->saveConstraints(&containmentConfig);
containment->save(&containmentConfig);
foreach (const Applet* applet, containment->applets()) {
KConfigGroup appletConfig(&cg, QString::number(applet->id()).append("-applet"));
applet->save(&appletConfig);
}
} }
} }
@ -196,85 +140,151 @@ void Corona::loadApplets(const QString& config)
{ {
clearApplets(); clearApplets();
KConfig appletConfig(config, KConfig::OnlyLocal); KConfig cg(config, KConfig::OnlyLocal);
foreach (const QString& group, appletConfig.groupList()) {
KConfigGroup cg(&appletConfig, group); QList<KConfigGroup> applets;
addApplet(cg.readEntry("plugin", QString()), QVariantList(), QHash<int, Containment*> containments;
group.toUInt(), cg.readEntry("geometry", QRectF()), true); foreach (const QString& group, cg.groupList()) {
KConfigGroup appletConfig(&cg, group);
if (group.contains("containment")) {
int cid = group.left(group.indexOf('-')).toUInt();
Containment *c = addContainment(appletConfig.readEntry("plugin", QString()), QVariantList(),
cid, true);
if (c) {
containments.insert(c->id(), c);
c->initConstraints(&appletConfig);
}
} else {
// it's an applet, let's grab the containment association
kDebug() << "insert multi " << group;
applets.append(appletConfig);
}
} }
foreach (Applet* applet, d->applets) { //int maxContainment = containments.size();
//kDebug() << "number of applets?" << applets.count();
foreach (KConfigGroup cg, applets) {
int cid = cg.readEntry("containment", 0);
kDebug() << "trying to load applet" << cg.group() << cid;
Containment* c = containments.value(cid, 0);
if (!c) {
continue;
}
kDebug() << "loading containment " << cid;
kDebug() << "creating applet " << cg.group();
int appId = cg.group().left(cg.group().indexOf('-')).toUInt();
c->addApplet(cg.readEntry("plugin", QString()), QVariantList(),
appId, cg.readEntry("geometry", QRectF()), true);
}
foreach (Containment* c, containments) {
QString cid = QString::number(c->id());
KConfigGroup containmentConfig(&cg, cid.append("-containment"));
c->setImmutable(containmentConfig.isImmutable());
}
if (d->containments.count() < 1) {
loadDefaultSetup();
}
foreach (Containment* containment, d->containments) {
containment->init();
foreach(Applet* applet, containment->applets()) {
applet->init(); applet->init();
} }
} }
setImmutable(cg.isImmutable());
}
void Corona::loadApplets() void Corona::loadApplets()
{ {
loadApplets("plasma-appletsrc"); loadApplets("plasma-appletsrc");
} }
void Corona::loadDefaultSetup()
{
//FIXME: implement support for system-wide defaults
QDesktopWidget desktop;
int numScreens = desktop.numScreens();
// create a containment for each screen
for (int i = 0; i < numScreens; ++i) {
Containment* c = addContainment("default");
c->setScreen(i);
c->setFormFactor(Plasma::Planar);
}
}
Containment* Corona::containmentForScreen(int screen) const
{
foreach (Containment* containment, d->containments) {
if (containment->screen() == screen) {
return containment;
}
}
return 0;
}
void Corona::clearApplets() void Corona::clearApplets()
{ {
qDeleteAll(d->applets); foreach (Containment* containment, d->containments) {
d->applets.clear(); containment->clearApplets();
}
} }
Applet* Corona::addApplet(const QString& name, const QVariantList& args, uint id, const QRectF& geometry, bool delayInit) Containment* Corona::addContainment(const QString& name, const QVariantList& args, uint id, bool delayedInit)
{ {
Applet* applet = Applet::loadApplet(name, id, args); Containment* containment = 0;
if (!applet) { Applet* applet = 0;
kDebug() << "Applet " << name << " could not be loaded.";
applet = new Applet; if (!name.isEmpty()) {
applet->setFailedToLaunch(true); applet = Applet::loadApplet(name, id, args);
containment = dynamic_cast<Containment*>(applet);
} }
//qreal appWidth = applet->boundingRect().width(); if (!containment) {
//qreal appHeight = applet->boundingRect().height(); delete applet; // in case we got a non-Containment from Applet::loadApplet
containment = new Containment;
if (geometry.isValid()) { containment->setFailedToLaunch(false); // we want to provide something and don't care about the failure to launch
applet->setGeometry(geometry);
} else {
applet->setGeometry( QRectF(geometry.topLeft(),applet->sizeHint()) );
} }
#if 0 addItem(containment);
if (!geometry.size().isValid()) {
if (!delayedInit) {
containment->init();
} }
if (geometry.isValid()) { // in case it was set in the Containment (or Applet), we don't want this
applet->setGeometry(geometry); containment->setDrawStandardBackground(false);
} else if (geometry.x() != -1 && geometry.y() != -1) {
// yes, this means we can't have items start -1, -1
applet->setPos(geometry.topLeft() - QPointF(applet->boundingRect().width()/2,
applet->boundingRect().height()/2));
} else {
//TODO: Make sure new applets don't overlap with existing ones
// Center exactly:
applet->setPos((width() / 2) - (appWidth / 2), (height() / 2) - (appHeight / 2));
}
#endif
if ( d->layout ) d->containments.append(containment);
d->layout->addItem(applet); connect(containment, SIGNAL(destroyed(QObject*)),
addItem(applet); this, SLOT(containmentDestroyed(QObject*)));
applet->updateConstraints();
if (!delayInit) { return containment;
applet->init();
} }
//applet->constraintsUpdated(); Applet* Corona::addApplet(const QString& name, const QVariantList& args, uint id, const QRectF& geometry)
d->applets << applet; {
connect(applet, SIGNAL(destroyed(QObject*)), if (d->containments.size() < 1) {
this, SLOT(appletDestroyed(QObject*))); kDebug() << "No containments to add an applet to!" << endl;
Phase::self()->animateItem(applet, Phase::Appear); //FIXME create a containment if one doesn't exist ... ?
return 0;
}
return applet; return d->containments[0]->addApplet(name, args, id, geometry);
} }
void Corona::addKaramba(const KUrl& path) void Corona::addKaramba(const KUrl& path)
{ {
//FIXME: i think this is slightly broken now that we have containments?
// it should go into a containment...
QGraphicsItemGroup* karamba = KarambaManager::loadKaramba(path, this); QGraphicsItemGroup* karamba = KarambaManager::loadKaramba(path, this);
if (karamba) { if (karamba) {
addItem(karamba); addItem(karamba);
@ -286,7 +296,7 @@ void Corona::addKaramba(const KUrl& path)
void Corona::dragEnterEvent( QGraphicsSceneDragDropEvent *event) void Corona::dragEnterEvent( QGraphicsSceneDragDropEvent *event)
{ {
kDebug() << "Corona::dragEnterEvent(QGraphicsSceneDragDropEvent* event)"; // kDebug() << "Corona::dragEnterEvent(QGraphicsSceneDragDropEvent* event)";
if (event->mimeData()->hasFormat(d->mimetype) || if (event->mimeData()->hasFormat(d->mimetype) ||
KUrl::List::canDecode(event->mimeData())) { KUrl::List::canDecode(event->mimeData())) {
event->acceptProposedAction(); event->acceptProposedAction();
@ -358,21 +368,17 @@ void Corona::dropEvent(QGraphicsSceneDragDropEvent *event)
} }
} }
// void Corona::contextMenuEvent(QGraphicsSceneContextMenuEvent *contextMenuEvent) void Corona::containmentDestroyed(QObject* obj)
// {
// }
void Corona::appletDestroyed(QObject* object)
{ {
// we do a static_cast here since it really isn't an Applet by this // we do a static_cast here since it really isn't an Containment by this
// point anymore since we are in the qobject dtor. we don't actually // point anymore since we are in the qobject dtor. we don't actually
// try and do anything with it, we just need the value of the pointer // try and do anything with it, we just need the value of the pointer
// so this unsafe looking code is actually just fine. // so this unsafe looking code is actually just fine.
Applet* applet = static_cast<Plasma::Applet*>(object); Containment* containment = static_cast<Plasma::Containment*>(obj);
int index = d->applets.indexOf(applet); int index = d->containments.indexOf(containment);
if (index > -1) { if (index > -1) {
d->applets.removeAt(index); d->containments.removeAt(index);
} }
} }
@ -389,13 +395,7 @@ void Corona::setImmutable(bool immutable)
d->immutable = immutable; d->immutable = immutable;
foreach (QGraphicsItem* item, items()) { foreach (QGraphicsItem* item, items()) {
QGraphicsItem::GraphicsItemFlags flags = item->flags(); item->setFlag(QGraphicsItem::ItemIsMovable, immutable);
if (immutable) {
flags ^= QGraphicsItem::ItemIsMovable;
} else {
flags |= QGraphicsItem::ItemIsMovable;
}
item->setFlags(flags);
} }
} }

View File

@ -29,6 +29,7 @@
namespace Plasma namespace Plasma
{ {
class Containment;
/** /**
* @short A QGraphicsScene for Plasma::Applets * @short A QGraphicsScene for Plasma::Applets
@ -50,16 +51,6 @@ public:
**/ **/
bool isImmutable() const; bool isImmutable() const;
/**
* The location of the Corona. @see Plasma::Location
*/
Plasma::Location location() const;
/**
* The current form factor for this Corona. @see Plasma::FormFactor
**/
Plasma::FormFactor formFactor() const;
/** /**
* A rect containing the maximum size a plasmoid on this corona should * A rect containing the maximum size a plasmoid on this corona should
* consider being. * consider being.
@ -91,6 +82,11 @@ public:
*/ */
void loadApplets(const QString &config); void loadApplets(const QString &config);
/**
* Loads the default (system wide) layout for this user
**/
virtual void loadDefaultSetup();
/** /**
* Clear the Corona from all applets. * Clear the Corona from all applets.
*/ */
@ -108,23 +104,7 @@ public Q_SLOTS:
void saveApplets() const; void saveApplets() const;
/** /**
* Informs the Corona as to what position it is in. This is informational * Adds an applet to the default Containment
* only, as the Corona doesn't change it's actual location. This is,
* however, passed on to Applets that may be managed by this Corona.
*
* @param location the new location of this Corona
*/
void setLocation(Plasma::Location location);
/**
* Sets the form factor for this Corona. This may cause changes in both
* the arrangement of Applets as well as the display choices of individual
* Applets.
*/
void setFormFactor(Plasma::FormFactor formFactor);
/**
* Adds an applet to the Corona
* *
* @param name the plugin name for the applet, as given by * @param name the plugin name for the applet, as given by
* KPluginInfo::pluginName() * KPluginInfo::pluginName()
@ -136,8 +116,29 @@ public Q_SLOTS:
* @return a pointer to the applet on success, or 0 on failure * @return a pointer to the applet on success, or 0 on failure
*/ */
Applet* addApplet(const QString& name, const QVariantList& args = QVariantList(), Applet* addApplet(const QString& name, const QVariantList& args = QVariantList(),
uint id = 0, const QRectF &geometry = QRectF(-1, -1, -1, -1), uint id = 0, const QRectF &geometry = QRectF(-1, -1, -1, -1));
bool delayInit = false);
/**
* Adds a Containment to the Corona
*
* @param name the plugin name for the containment, as given by
* KPluginInfo::pluginName()
* @param args argument list to pass to the containment
* @param id to assign to this containment, or 0 to auto-assign it a new id
* @param geometry where to place the containment, or to auto-place it if an invalid
* is provided
*
* @return a pointer to the containment on success, or 0 on failure
*/
Containment* addContainment(const QString& name, const QVariantList& args = QVariantList(),
uint id = 0, bool delayInit = false);
/**
* Returns the Containment, if any, for a given physical screen
*
* @param screen number of the physical screen to locate
*/
Containment* containmentForScreen(int screen) const;
/** /**
* Adds a SuperKaramba theme to the scene * Adds a SuperKaramba theme to the scene
@ -159,7 +160,7 @@ protected:
//void contextMenuEvent(QGraphicsSceneContextMenuEvent *contextMenuEvent); //void contextMenuEvent(QGraphicsSceneContextMenuEvent *contextMenuEvent);
protected Q_SLOTS: protected Q_SLOTS:
void appletDestroyed(QObject*); void containmentDestroyed(QObject*);
private: private:
class Private; class Private;