• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

libplasma

corona.cpp

Go to the documentation of this file.
00001 /*
00002  *   Copyright 2007 Matt Broadstone <mbroadst@gmail.com>
00003  *   Copyright 2007 Aaron Seigo <aseigo@kde.org>
00004  *   Copyright 2007 Riccardo Iaconelli <riccardo@kde.org>
00005  *
00006  *   This program is free software; you can redistribute it and/or modify
00007  *   it under the terms of the GNU Library General Public License as
00008  *   published by the Free Software Foundation; either version 2, or
00009  *   (at your option) any later version.
00010  *
00011  *   This program is distributed in the hope that it will be useful,
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *   GNU General Public License for more details
00015  *
00016  *   You should have received a copy of the GNU Library General Public
00017  *   License along with this program; if not, write to the
00018  *   Free Software Foundation, Inc.,
00019  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00020  */
00021 
00022 #include "corona.h"
00023 
00024 #include <QApplication>
00025 #include <QGraphicsSceneDragDropEvent>
00026 #include <QMimeData>
00027 #include <QPainter>
00028 #include <QTimer>
00029 
00030 #include <KDebug>
00031 #include <KGlobal>
00032 #include <KLocale>
00033 #include <KMimeType>
00034 
00035 #include "containment.h"
00036 
00037 using namespace Plasma;
00038 
00039 namespace Plasma
00040 {
00041 
00042 // constant controlling how long between requesting a configuration sync
00043 // and one happening should occur. currently 30 seconds
00044 const int CONFIG_SYNC_TIMEOUT = 30000;
00045 
00046 class CoronaPrivate
00047 {
00048 public:
00049     CoronaPrivate(Corona *corona)
00050         : q(corona),
00051           immutability(Mutable),
00052           mimetype("text/x-plasmoidservicename"),
00053           config(0)
00054     {
00055         if (KGlobal::hasMainComponent()) {
00056             configName = KGlobal::mainComponent().componentName() + "-appletsrc";
00057         } else {
00058             configName = "plasma-appletsrc";
00059         }
00060     }
00061 
00062     ~CoronaPrivate()
00063     {
00064         qDeleteAll(containments);
00065     }
00066 
00067     void init()
00068     {
00069         configSyncTimer.setSingleShot(true);
00070         QObject::connect(&configSyncTimer, SIGNAL(timeout()), q, SLOT(syncConfig()));
00071     }
00072 
00073     void saveLayout(KSharedConfigPtr cg) const
00074     {
00075         KConfigGroup containmentsGroup(cg, "Containments");
00076         foreach (const Containment *containment, containments) {
00077             QString cid = QString::number(containment->id());
00078             KConfigGroup containmentConfig(&containmentsGroup, cid);
00079             containment->save(containmentConfig);
00080         }
00081     }
00082 
00083     void updateContainmentImmutability()
00084     {
00085         foreach (Containment *c, containments) {
00086             // we need to tell each containment that immutability has been altered
00087             c->updateConstraints(ImmutableConstraint);
00088         }
00089     }
00090 
00091     void containmentDestroyed(QObject* obj)
00092     {
00093         // we do a static_cast here since it really isn't an Containment by this
00094         // point anymore since we are in the qobject dtor. we don't actually
00095         // try and do anything with it, we just need the value of the pointer
00096         // so this unsafe looking code is actually just fine.
00097         Containment* containment = static_cast<Plasma::Containment*>(obj);
00098         int index = containments.indexOf(containment);
00099 
00100         if (index > -1) {
00101             containments.removeAt(index);
00102             q->requestConfigSync();
00103         }
00104     }
00105 
00106     void syncConfig()
00107     {
00108         q->config()->sync();
00109         emit q->configSynced();
00110     }
00111 
00112     Containment* addContainment(const QString& name, const QVariantList& args, uint id, bool delayedInit)
00113     {
00114         QString pluginName = name;
00115         Containment* containment = 0;
00116         Applet* applet = 0;
00117 
00118         //kDebug() << "Loading" << name << args << id;
00119 
00120         if (pluginName.isEmpty()) {
00121             // default to the desktop containment
00122             pluginName = "desktop";
00123         }
00124 
00125         if (pluginName != "null") {
00126             applet = Applet::load(pluginName, id, args);
00127             containment = dynamic_cast<Containment*>(applet);
00128         }
00129 
00130         if (!containment) {
00131             kDebug() << "loading of containment" << name << "failed.";
00132 
00133             // in case we got a non-Containment from Applet::loadApplet or a null containment was requested
00134             delete applet;
00135             containment = new Containment(0, 0, id);
00136 
00137             // we want to provide something and don't care about the failure to launch
00138             containment->setFailedToLaunch(false);
00139             containment->setFormFactor(Plasma::Planar);
00140         }
00141 
00142         containment->setIsContainment(true);
00143         q->addItem(containment);
00144 
00145         if (!delayedInit) {
00146             containment->init();
00147             containment->updateConstraints(Plasma::StartupCompletedConstraint);
00148             KConfigGroup cg = containment->config();
00149             containment->save(cg);
00150             q->requestConfigSync();
00151         }
00152 
00153         containments.append(containment);
00154         QObject::connect(containment, SIGNAL(destroyed(QObject*)), q, SLOT(containmentDestroyed(QObject*)));
00155         QObject::connect(containment, SIGNAL(configNeedsSaving()), q, SLOT(requestConfigSync()));
00156         QObject::connect(containment, SIGNAL(releaseVisualFocus()), q, SIGNAL(releaseVisualFocus()));
00157         QObject::connect(containment, SIGNAL(screenChanged(int,int,Plasma::Containment*)),
00158                          q, SIGNAL(screenOwnerChanged(int,int,Plasma::Containment*)));
00159 
00160         if (!delayedInit) {
00161             emit q->containmentAdded(containment);
00162         }
00163 
00164         return containment;
00165     }
00166 
00167     Corona *q;
00168     ImmutabilityType immutability;
00169     QString mimetype;
00170     QString configName;
00171     KSharedConfigPtr config;
00172     QTimer configSyncTimer;
00173     QList<Containment*> containments;
00174 };
00175 
00176 Corona::Corona(QObject *parent)
00177     : QGraphicsScene(parent),
00178       d(new CoronaPrivate(this))
00179 {
00180     d->init();
00181     //setViewport(new QGLWidget(QGLFormat(QGL::StencilBuffer | QGL::AlphaChannel)));
00182 }
00183 
00184 Corona::~Corona()
00185 {
00186     KConfigGroup cg(config(), "General");
00187 
00188     // we call the dptr member directly for locked since isImmutable()
00189     // also checks kiosk and parent containers
00190     cg.writeEntry("immutability", (int)d->immutability);
00191     delete d;
00192 }
00193 
00194 void Corona::setAppletMimeType(const QString& type)
00195 {
00196     d->mimetype = type;
00197 }
00198 
00199 QString Corona::appletMimeType()
00200 {
00201     return d->mimetype;
00202 }
00203 
00204 void Corona::saveLayout(const QString &configName) const
00205 {
00206     KSharedConfigPtr c;
00207 
00208     if (configName.isEmpty() || configName == d->configName) {
00209         c = config();
00210     } else {
00211         c = KSharedConfig::openConfig(configName);
00212     }
00213 
00214     d->saveLayout(c);
00215 }
00216 
00217 void Corona::requestConfigSync()
00218 {
00219     // TODO: should we check into our immutability before doing this?
00220 
00221     //NOTE: this is a pretty simplistic model: we simply save no more than CONFIG_SYNC_TIMEOUT
00222     //      after the first time this is called. not much of a heuristic for save points, but
00223     //      it should at least compress these activities a bit and provide a way for applet
00224     //      authors to ween themselves from the sync() disease. A more interesting/dynamic
00225     //      algorithm for determining when to actually sync() to disk might be better, though.
00226     if (!d->configSyncTimer.isActive()) {
00227         d->configSyncTimer.start(CONFIG_SYNC_TIMEOUT);
00228     }
00229 }
00230 
00231 void Corona::initializeLayout(const QString &configName)
00232 {
00233     clearContainments();
00234     loadLayout(configName);
00235 
00236     if (d->containments.isEmpty()) {
00237         loadDefaultLayout();
00238         if (!d->containments.isEmpty()) {
00239             requestConfigSync();
00240         }
00241     }
00242 
00243     if (config()->isImmutable()) {
00244         d->updateContainmentImmutability();
00245     }
00246 
00247     KConfigGroup coronaConfig(config(), "General");
00248     setImmutability((ImmutabilityType)coronaConfig.readEntry("immutability", (int)Mutable));
00249 }
00250 
00251 void Corona::loadLayout(const QString& configName)
00252 {
00253     KSharedConfigPtr c;
00254 
00255     if (configName.isEmpty() || configName == d->configName) {
00256         c = config();
00257     } else {
00258         c = KSharedConfig::openConfig(configName);
00259     }
00260 
00261     KConfigGroup containments(config(), "Containments");
00262 
00263     foreach (const QString& group, containments.groupList()) {
00264         KConfigGroup containmentConfig(&containments, group);
00265 
00266         if (containmentConfig.entryMap().isEmpty()) {
00267             continue;
00268         }
00269 
00270         int cid = group.toUInt();
00271         //kDebug() << "got a containment in the config, trying to make a" << containmentConfig.readEntry("plugin", QString()) << "from" << group;
00272         Containment *c = d->addContainment(containmentConfig.readEntry("plugin", QString()), QVariantList(),
00273                                            cid, true);
00274         if (!c) {
00275             continue;
00276         }
00277 
00278         //addItem(c);
00279         c->init();
00280         c->restore(containmentConfig);
00281     }
00282 
00283     foreach (Containment* containment, d->containments) {
00284         QString cid = QString::number(containment->id());
00285         KConfigGroup containmentConfig(&containments, cid);
00286 
00287         foreach(Applet* applet, containment->applets()) {
00288             applet->init();
00289         }
00290 
00291         containment->updateConstraints(Plasma::StartupCompletedConstraint);
00292         containment->flushPendingConstraintsEvents();
00293         emit containmentAdded(containment);
00294     }
00295 }
00296 
00297 Containment* Corona::containmentForScreen(int screen) const
00298 {
00299     foreach (Containment* containment, d->containments) {
00300         if (containment->screen() == screen &&
00301             (containment->containmentType() == Containment::DesktopContainment ||
00302              containment->containmentType() >= Containment::CustomContainment)) {
00303             return containment;
00304         }
00305     }
00306 
00307     return 0;
00308 }
00309 
00310 QList<Containment*> Corona::containments() const
00311 {
00312     return d->containments;
00313 }
00314 
00315 void Corona::clearContainments()
00316 {
00317     foreach (Containment* containment, d->containments) {
00318         containment->clearApplets();
00319     }
00320 }
00321 
00322 KSharedConfigPtr Corona::config() const
00323 {
00324     if (!d->config) {
00325         d->config = KSharedConfig::openConfig(d->configName);
00326     }
00327 
00328     return d->config;
00329 }
00330 
00331 Containment* Corona::addContainment(const QString& name, const QVariantList& args)
00332 {
00333     return d->addContainment(name, args, 0, false);
00334 }
00335 
00336 Containment* Corona::addContainmentDelayed(const QString& name, const QVariantList& args)
00337 {
00338     return d->addContainment(name, args, 0, true);
00339 }
00340 
00341 void Corona::loadDefaultLayout()
00342 {
00343 }
00344 
00345 void Corona::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
00346 {
00347     QGraphicsScene::dragEnterEvent(event);
00348 }
00349 
00350 void Corona::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
00351 {
00352     QGraphicsScene::dragLeaveEvent(event);
00353 }
00354 
00355 void Corona::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
00356 {
00357     QGraphicsScene::dragMoveEvent(event);
00358 }
00359 
00360 ImmutabilityType Corona::immutability() const
00361 {
00362     return d->immutability;
00363 }
00364 
00365 void Corona::setImmutability(const ImmutabilityType immutable)
00366 {
00367     if (d->immutability == immutable ||
00368         d->immutability == SystemImmutable) {
00369         return;
00370     }
00371 
00372     kDebug() << "setting immutability to" << immutable;
00373     d->immutability = immutable;
00374     d->updateContainmentImmutability();
00375 }
00376 
00377 } // namespace Plasma
00378 
00379 #include "corona.moc"
00380 

libplasma

Skip menu "libplasma"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libplasma
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal