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

Plasma

applet.cpp

Go to the documentation of this file.
00001 /*
00002  *   Copyright 2005 by Aaron Seigo <aseigo@kde.org>
00003  *   Copyright 2007 by Riccardo Iaconelli <riccardo@kde.org>
00004  *   Copyright 2008 by Ménard Alexis <darktears31@gmail.com>
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 "applet.h"
00023 #include "private/applet_p.h"
00024 
00025 #include <cmath>
00026 #include <limits>
00027 
00028 #include <QAction>
00029 #include <QApplication>
00030 #include <QEvent>
00031 #include <QFile>
00032 #include <QGraphicsGridLayout>
00033 #include <QGraphicsSceneMouseEvent>
00034 #include <QGraphicsView>
00035 #include <QLabel>
00036 #include <QList>
00037 #include <QGraphicsLinearLayout>
00038 #include <QPainter>
00039 #include <QSize>
00040 #include <QStyleOptionGraphicsItem>
00041 #include <QTextDocument>
00042 #include <QUiLoader>
00043 #include <QVBoxLayout>
00044 #include <QWidget>
00045 
00046 #include <kaction.h>
00047 #include <kactioncollection.h>
00048 #include <kauthorized.h>
00049 #include <kcolorscheme.h>
00050 #include <kconfigdialog.h>
00051 #include <kdialog.h>
00052 #include <kicon.h>
00053 #include <kiconloader.h>
00054 #include <kkeysequencewidget.h>
00055 #include <kplugininfo.h>
00056 #include <kstandarddirs.h>
00057 #include <kservice.h>
00058 #include <kservicetypetrader.h>
00059 #include <kshortcut.h>
00060 #include <kwindowsystem.h>
00061 #include <kpushbutton.h>
00062 
00063 #include <solid/powermanagement.h>
00064 
00065 #include "configloader.h"
00066 #include "containment.h"
00067 #include "corona.h"
00068 #include "dataenginemanager.h"
00069 #include "extender.h"
00070 #include "extenderitem.h"
00071 #include "package.h"
00072 #include "plasma.h"
00073 #include "scripting/appletscript.h"
00074 #include "svg.h"
00075 #include "framesvg.h"
00076 #include "private/framesvg_p.h"
00077 #include "popupapplet.h"
00078 #include "theme.h"
00079 #include "view.h"
00080 #include "widgets/iconwidget.h"
00081 #include "widgets/label.h"
00082 #include "widgets/pushbutton.h"
00083 #include "widgets/busywidget.h"
00084 #include "tooltipmanager.h"
00085 #include "wallpaper.h"
00086 
00087 #include "private/containment_p.h"
00088 #include "private/extenderapplet_p.h"
00089 #include "private/packages_p.h"
00090 #include "private/popupapplet_p.h"
00091 #include "private/toolbox_p.h"
00092 
00093 //#define DYNAMIC_SHADOWS
00094 namespace Plasma
00095 {
00096 
00097 Applet::Applet(QGraphicsItem *parent,
00098                const QString &serviceID,
00099                uint appletId)
00100     :  QGraphicsWidget(parent),
00101        d(new AppletPrivate(KService::serviceByStorageId(serviceID), appletId, this))
00102 {
00103     // WARNING: do not access config() OR globalConfig() in this method!
00104     //          that requires a scene, which is not available at this point
00105     d->init();
00106 }
00107 
00108 Applet::Applet(QObject *parentObject, const QVariantList &args)
00109     :  QGraphicsWidget(0),
00110        d(new AppletPrivate(
00111              KService::serviceByStorageId(args.count() > 0 ? args[0].toString() : QString()),
00112              args.count() > 1 ? args[1].toInt() : 0, this))
00113 {
00114     // now remove those first two items since those are managed by Applet and subclasses shouldn't
00115     // need to worry about them. yes, it violates the constness of this var, but it lets us add
00116     // or remove items later while applets can just pretend that their args always start at 0
00117     QVariantList &mutableArgs = const_cast<QVariantList &>(args);
00118     if (!mutableArgs.isEmpty()) {
00119         mutableArgs.removeFirst();
00120 
00121         if (!mutableArgs.isEmpty()) {
00122             mutableArgs.removeFirst();
00123         }
00124     }
00125 
00126     setParent(parentObject);
00127 
00128     // WARNING: do not access config() OR globalConfig() in this method!
00129     //          that requires a scene, which is not available at this point
00130     d->init();
00131 
00132     // the brain damage seen in the initialization list is due to the
00133     // inflexibility of KService::createInstance
00134 }
00135 
00136 Applet::~Applet()
00137 {
00138     if (d->transient) {
00139         d->resetConfigurationObject();
00140     } else if (d->extender) {
00141         //This would probably be nicer if it was located in extender. But in it's dtor, this won't
00142         //work since when that get's called, the applet's config() isn't accessible anymore. (same
00143         //problem with calling saveState(). Doing this in saveState() might be a possibility, but
00144         //that would require every extender savestate implementation to call it's parent function,
00145         //which isn't very nice.
00146         d->extender->saveState();
00147 
00148         foreach (ExtenderItem *item, d->extender->attachedItems()) {
00149             if (item->autoExpireDelay()) {
00150                 //destroy temporary extender items, or items that aren't detached, so their
00151                 //configuration won't linger after a plasma restart.
00152                 item->destroy();
00153             }
00154         }
00155     }
00156 
00157     delete d;
00158 }
00159 
00160 PackageStructure::Ptr Applet::packageStructure()
00161 {
00162     if (!AppletPrivate::packageStructure) {
00163         AppletPrivate::packageStructure = new PlasmoidPackage();
00164     }
00165 
00166     return AppletPrivate::packageStructure;
00167 }
00168 
00169 void Applet::init()
00170 {
00171     if (d->script && !d->script->init()) {
00172         setFailedToLaunch(true, i18n("Script initialization failed"));
00173     }
00174 }
00175 
00176 uint Applet::id() const
00177 {
00178     return d->appletId;
00179 }
00180 
00181 void Applet::save(KConfigGroup &g) const
00182 {
00183     if (d->transient) {
00184         return;
00185     }
00186 
00187     KConfigGroup group = g;
00188     if (!group.isValid()) {
00189         group = *d->mainConfigGroup();
00190     }
00191 
00192     //kDebug() << "saving to" << group.name();
00193     // we call the dptr member directly for locked since isImmutable()
00194     // also checks kiosk and parent containers
00195     group.writeEntry("immutability", (int)d->immutability);
00196     group.writeEntry("plugin", pluginName());
00197 
00198     group.writeEntry("geometry", geometry());
00199     group.writeEntry("zvalue", zValue());
00200 
00201     if (!d->started) {
00202         return;
00203     }
00204 
00205     //FIXME: for containments, we need to have some special values here w/regards to
00206     //       screen affinity (e.g. "bottom of screen 0")
00207     //kDebug() << pluginName() << "geometry is" << geometry()
00208     //         << "pos is" << pos() << "bounding rect is" << boundingRect();
00209     if (transform() == QTransform()) {
00210         group.deleteEntry("transform");
00211     } else {
00212         QList<qreal> m;
00213         QTransform t = transform();
00214         m << t.m11() << t.m12() << t.m13() << t.m21() << t.m22() << t.m23() << t.m31() << t.m32() << t.m33();
00215         group.writeEntry("transform", m);
00216         //group.writeEntry("transform", transformToString(transform()));
00217     }
00218 
00219     KConfigGroup appletConfigGroup(&group, "Configuration");
00220 
00221     //FIXME: we need a global save state too
00222     saveState(appletConfigGroup);
00223 
00224     if (d->activationAction) {
00225         KConfigGroup shortcutConfig(&group, "Shortcuts");
00226         shortcutConfig.writeEntry("global", d->activationAction->globalShortcut().toString());
00227     }
00228 
00229     if (d->configLoader) {
00230         d->configLoader->writeConfig();
00231     }
00232 }
00233 
00234 void Applet::restore(KConfigGroup &group)
00235 {
00236     QList<qreal> m = group.readEntry("transform", QList<qreal>());
00237     if (m.count() == 9) {
00238         QTransform t(m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8]);
00239         setTransform(t);
00240     }
00241 
00242     qreal z = group.readEntry("zvalue", 0);
00243 
00244     if (z >= AppletPrivate::s_maxZValue) {
00245         AppletPrivate::s_maxZValue = z;
00246     }
00247 
00248     if (z > 0) {
00249         setZValue(z);
00250     }
00251 
00252     setImmutability((ImmutabilityType)group.readEntry("immutability", (int)Mutable));
00253 
00254     QRectF geom = group.readEntry("geometry", QRectF());
00255     if (geom.isValid()) {
00256         setGeometry(geom);
00257     }
00258 
00259     KConfigGroup shortcutConfig(&group, "Shortcuts");
00260     QString shortcutText = shortcutConfig.readEntryUntranslated("global", QString());
00261     if (!shortcutText.isEmpty()) {
00262         setGlobalShortcut(KShortcut(shortcutText));
00263         kDebug() << "got global shortcut for" << name() << "of" << QKeySequence(shortcutText);
00264         kDebug() << "set to" << d->activationAction->objectName()
00265                  << d->activationAction->globalShortcut().primary();
00266     }
00267 
00268     // local shortcut, if any
00269     //TODO: implement; the shortcut will need to be registered with the containment
00270     /*
00271     shortcutText = shortcutConfig.readEntryUntranslated("local", QString());
00272     if (!shortcutText.isEmpty()) {
00273         //TODO: implement; the shortcut
00274     }
00275     */
00276 }
00277 
00278 void AppletPrivate::setFocus()
00279 {
00280     //kDebug() << "setting focus";
00281     q->setFocus(Qt::ShortcutFocusReason);
00282 }
00283 
00284 void Applet::setFailedToLaunch(bool failed, const QString &reason)
00285 {
00286     if (d->failed == failed) {
00287         if (failed && !reason.isEmpty()) {
00288             foreach (QGraphicsItem *item, QGraphicsItem::children()) {
00289                 Label *l = dynamic_cast<Label *>(item);
00290                 if (l) {
00291                     l->setText(d->visibleFailureText(reason));
00292                 }
00293             }
00294         }
00295         return;
00296     }
00297 
00298     d->failed = failed;
00299     prepareGeometryChange();
00300 
00301     qDeleteAll(QGraphicsItem::children());
00302     setLayout(0);
00303 
00304     if (failed) {
00305         setBackgroundHints(d->backgroundHints|StandardBackground);
00306 
00307         QGraphicsLinearLayout *failureLayout = new QGraphicsLinearLayout(this);
00308         failureLayout->setContentsMargins(0, 0, 0, 0);
00309 
00310         IconWidget *failureIcon = new IconWidget(this);
00311         failureIcon->setIcon(KIcon("dialog-error"));
00312         failureLayout->addItem(failureIcon);
00313 
00314         Label *failureWidget = new Plasma::Label(this);
00315         failureWidget->setText(d->visibleFailureText(reason));
00316         QLabel *label = failureWidget->nativeWidget();
00317         label->setWordWrap(true);
00318         failureLayout->addItem(failureWidget);
00319 
00320         Plasma::ToolTipManager::self()->registerWidget(failureIcon);
00321         Plasma::ToolTipContent data(i18n("Unable to load the widget"), reason,
00322                                     KIcon("dialog-error"));
00323         Plasma::ToolTipManager::self()->setContent(failureIcon, data);
00324 
00325         setLayout(failureLayout);
00326         resize(300, 250);
00327         setMinimumSize(failureLayout->minimumSize());
00328         d->background->resizeFrame(geometry().size());
00329     }
00330 
00331     update();
00332 }
00333 
00334 void Applet::saveState(KConfigGroup &group) const
00335 {
00336     if (group.config()->name() != config().config()->name()) {
00337         // we're being saved to a different file!
00338         // let's just copy the current values in our configuration over
00339         KConfigGroup c = config();
00340         c.copyTo(&group);
00341     }
00342 }
00343 
00344 KConfigGroup Applet::config(const QString &group) const
00345 {
00346     KConfigGroup cg = config();
00347     return KConfigGroup(&cg, group);
00348 }
00349 
00350 KConfigGroup Applet::config() const
00351 {
00352     if (d->isContainment) {
00353         return *(d->mainConfigGroup());
00354     }
00355 
00356     return KConfigGroup(d->mainConfigGroup(), "Configuration");
00357 }
00358 
00359 KConfigGroup Applet::globalConfig() const
00360 {
00361     KConfigGroup globalAppletConfig;
00362     QString group = isContainment() ? "ContainmentGlobals" : "AppletGlobals";
00363 
00364     Corona *corona = qobject_cast<Corona*>(scene());
00365     if (corona) {
00366         KSharedConfig::Ptr coronaConfig = corona->config();
00367         globalAppletConfig = KConfigGroup(coronaConfig, group);
00368     } else {
00369         globalAppletConfig = KConfigGroup(KGlobal::config(), group);
00370     }
00371 
00372     return KConfigGroup(&globalAppletConfig, d->globalName());
00373 }
00374 
00375 void Applet::destroy()
00376 {
00377     if (immutability() != Mutable || d->transient) {
00378         return; //don't double delete
00379     }
00380 
00381     d->transient = true;
00382 
00383     if (isContainment()) {
00384         d->cleanUpAndDelete();
00385     } else {
00386         d->resetConfigurationObject();
00387         connect(Animator::self(), SIGNAL(animationFinished(QGraphicsItem*,Plasma::Animator::Animation)),
00388                 this, SLOT(appletAnimationComplete(QGraphicsItem*,Plasma::Animator::Animation)));
00389         Animator::self()->animateItem(this, Animator::DisappearAnimation);
00390     }
00391 
00392     Corona * corona = qobject_cast<Corona*>(scene());
00393     if (corona) {
00394         corona->requireConfigSync();
00395     }
00396 }
00397 
00398 bool Applet::destroyed() const
00399 {
00400     return d->transient;
00401 }
00402 
00403 void AppletPrivate::appletAnimationComplete(QGraphicsItem *item, Plasma::Animator::Animation anim)
00404 {
00405     if (anim != Animator::DisappearAnimation || item != q) {
00406         return; //it's not our time yet
00407     }
00408 
00409     cleanUpAndDelete();
00410 }
00411 
00412 void AppletPrivate::selectItemToDestroy()
00413 {
00414     //FIXME: this will not work nicely with multiple screens and being zoomed out!
00415     if (q->isContainment()) {
00416         QGraphicsView *view = q->view();
00417         if (view && view->transform().isScaling() &&
00418             q->scene()->focusItem() != q) {
00419             QGraphicsItem *focus = q->scene()->focusItem();
00420 
00421             if (focus) {
00422                 Containment *toDestroy = dynamic_cast<Containment*>(focus->topLevelItem());
00423 
00424                 if (toDestroy) {
00425                     toDestroy->destroy();
00426                     return;
00427                 }
00428             }
00429         }
00430     }
00431 
00432     q->destroy();
00433 }
00434 
00435 void AppletPrivate::updateRect(const QRectF &rect)
00436 {
00437     q->update(rect);
00438 }
00439 
00440 void AppletPrivate::cleanUpAndDelete()
00441 {
00442     //kDebug() << "???????????????? DESTROYING APPLET" << name() << " ???????????????????????????";
00443     QGraphicsWidget *parent = dynamic_cast<QGraphicsWidget *>(q->parentItem());
00444     //it probably won't matter, but right now if there are applethandles, *they* are the parent.
00445     //not the containment.
00446 
00447     //is the applet in a containment and is the containment have a layout?
00448     //if yes, we remove the applet in the layout
00449     if (parent && parent->layout()) {
00450         QGraphicsLayout *l = parent->layout();
00451         for (int i = 0; i < l->count(); ++i) {
00452             if (q == l->itemAt(i)) {
00453                 l->removeAt(i);
00454                 break;
00455             }
00456         }
00457     }
00458 
00459     if (configLoader) {
00460         configLoader->setDefaults();
00461     }
00462 
00463     q->scene()->removeItem(q);
00464     q->deleteLater();
00465 }
00466 
00467 void AppletPrivate::createMessageOverlay()
00468 {
00469     if (!messageOverlay) {
00470         messageOverlay = new AppletOverlayWidget(q);
00471     } else {
00472         qDeleteAll(messageOverlay->children());
00473         messageOverlay->setLayout(0);
00474     }
00475 
00476     messageOverlay->resize(q->contentsRect().size());
00477     messageOverlay->setPos(q->contentsRect().topLeft());
00478 
00479     // raise the overlay above all the other children!
00480     int zValue = 100;
00481     foreach (QGraphicsItem *child, q->QGraphicsItem::children()) {
00482         if (child->zValue() > zValue) {
00483             zValue = child->zValue() + 1;
00484         }
00485     }
00486 
00487     messageOverlay->setZValue(zValue);
00488 }
00489 
00490 void AppletPrivate::destroyMessageOverlay()
00491 {
00492     //TODO: fade out? =)
00493     QGraphicsWidget *w = messageOverlay;
00494     messageOverlay = 0;
00495     w->hide();
00496     w->deleteLater();
00497 }
00498 
00499 ConfigLoader *Applet::configScheme() const
00500 {
00501     return d->configLoader;
00502 }
00503 
00504 DataEngine *Applet::dataEngine(const QString &name) const
00505 {
00506     int index = d->loadedEngines.indexOf(name);
00507     if (index != -1) {
00508         return DataEngineManager::self()->engine(name);
00509     }
00510 
00511     DataEngine *engine = DataEngineManager::self()->loadEngine(name);
00512     if (engine->isValid()) {
00513         d->loadedEngines.append(name);
00514     }
00515 
00516     return engine;
00517 }
00518 
00519 const Package *Applet::package() const
00520 {
00521     return d->package;
00522 }
00523 
00524 QGraphicsView *Applet::view() const
00525 {
00526     // It's assumed that we won't be visible on more than one view here.
00527     // Anything that actually needs view() should only really care about
00528     // one of them anyway though.
00529     if (!scene()) {
00530         return 0;
00531     }
00532 
00533     QGraphicsView *found = 0;
00534     QGraphicsView *possibleFind = 0;
00535     //kDebug() << "looking through" << scene()->views().count() << "views";
00536     foreach (QGraphicsView *view, scene()->views()) {
00537         //kDebug() << "     checking" << view << view->sceneRect()
00538         //         << "against" << sceneBoundingRect() << scenePos();
00539         if (view->sceneRect().intersects(sceneBoundingRect()) ||
00540             view->sceneRect().contains(scenePos())) {
00541             //kDebug() << "     found something!" << view->isActiveWindow();
00542             if (view->isActiveWindow()) {
00543                 found = view;
00544             } else {
00545                 possibleFind = view;
00546             }
00547         }
00548     }
00549 
00550     return found ? found : possibleFind;
00551 }
00552 
00553 QRectF Applet::mapFromView(const QGraphicsView *view, const QRect &rect) const
00554 {
00555     // Why is this adjustment needed? Qt calculation error?
00556     return mapFromScene(view->mapToScene(rect)).boundingRect().adjusted(0, 0, 1, 1);
00557 }
00558 
00559 QRect Applet::mapToView(const QGraphicsView *view, const QRectF &rect) const
00560 {
00561     // Why is this adjustment needed? Qt calculation error?
00562     return view->mapFromScene(mapToScene(rect)).boundingRect().adjusted(0, 0, -1, -1);
00563 }
00564 
00565 QPoint Applet::popupPosition(const QSize &s) const
00566 {
00567     Corona * corona = qobject_cast<Corona*>(scene());
00568     Q_ASSERT(corona);
00569     return corona->popupPosition(this, s);
00570 }
00571 
00572 void Applet::updateConstraints(Plasma::Constraints constraints)
00573 {
00574     d->scheduleConstraintsUpdate(constraints);
00575 }
00576 
00577 void Applet::constraintsEvent(Plasma::Constraints constraints)
00578 {
00579     //NOTE: do NOT put any code in here that reacts to constraints updates
00580     //      as it will not get called for any applet that reimplements constraintsEvent
00581     //      without calling the Applet:: version as well, which it shouldn't need to.
00582     //      INSTEAD put such code into flushPendingConstraintsEvents
00583     Q_UNUSED(constraints)
00584     //kDebug() << constraints << "constraints are FormFactor: " << formFactor()
00585     //         << ", Location: " << location();
00586     if (d->script) {
00587         d->script->constraintsEvent(constraints);
00588     }
00589 }
00590 
00591 void Applet::initExtenderItem(ExtenderItem *item)
00592 {
00593     kWarning() << "Missing implementation of initExtenderItem in the applet "
00594                << item->config().readEntry("SourceAppletPluginName", "")
00595                << "!\n Any applet that uses extenders should implement initExtenderItem to "
00596                << "instantiate a widget. Destroying the item...";
00597     item->destroy();
00598 }
00599 
00600 Extender *Applet::extender() const
00601 {
00602     if (!d->extender) {
00603         new Extender(const_cast<Applet*>(this));
00604     }
00605 
00606     return d->extender;
00607 }
00608 
00609 void Applet::setBusy(bool busy)
00610 {
00611     if (busy) {
00612         if (!d->busyWidget) {
00613             d->busyWidget = new Plasma::BusyWidget(this);
00614         } else {
00615             d->busyWidget->show();
00616         }
00617         int busySize = qMin(size().width(), size().height())/3;
00618         QRect busyRect(0, 0, busySize, busySize);
00619         busyRect.moveCenter(boundingRect().center().toPoint());
00620         d->busyWidget->setGeometry(busyRect);
00621     } else if (d->busyWidget) {
00622         d->busyWidget->hide();
00623         d->busyWidget->deleteLater();
00624         d->busyWidget = 0;
00625     }
00626 }
00627 
00628 bool Applet::isBusy() const
00629 {
00630     return d->busyWidget && d->busyWidget->isVisible();
00631 }
00632 
00633 QString Applet::name() const
00634 {
00635     if (isContainment()) {
00636         if (!d->appletDescription.isValid()) {
00637             return i18n("Unknown Activity");
00638         }
00639 
00640         const Containment *c = qobject_cast<const Containment*>(this);
00641         if (c && !c->activity().isNull()) {
00642             return i18n("%1 Activity", c->activity());
00643         }
00644     } else if (!d->appletDescription.isValid()) {
00645         return i18n("Unknown Widget");
00646     }
00647 
00648     return d->appletDescription.name();
00649 }
00650 
00651 QFont Applet::font() const
00652 {
00653     return QApplication::font();
00654 }
00655 
00656 QString Applet::icon() const
00657 {
00658     if (!d->appletDescription.isValid()) {
00659         return QString();
00660     }
00661 
00662     return d->appletDescription.icon();
00663 }
00664 
00665 QString Applet::pluginName() const
00666 {
00667     if (!d->appletDescription.isValid()) {
00668         return QString();
00669     }
00670 
00671     return d->appletDescription.pluginName();
00672 }
00673 
00674 bool Applet::shouldConserveResources() const
00675 {
00676     return Solid::PowerManagement::appShouldConserveResources();
00677 }
00678 
00679 QString Applet::category() const
00680 {
00681     if (!d->appletDescription.isValid()) {
00682         return i18nc("misc category", "Miscellaneous");
00683     }
00684 
00685     return d->appletDescription.category();
00686 }
00687 
00688 QString Applet::category(const KPluginInfo &applet)
00689 {
00690     return applet.property("X-KDE-PluginInfo-Category").toString();
00691 }
00692 
00693 QString Applet::category(const QString &appletName)
00694 {
00695     if (appletName.isEmpty()) {
00696         return QString();
00697     }
00698 
00699     QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(appletName);
00700     KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
00701 
00702     if (offers.isEmpty()) {
00703         return QString();
00704     }
00705 
00706     return offers.first()->property("X-KDE-PluginInfo-Category").toString();
00707 }
00708 
00709 ImmutabilityType Applet::immutability() const
00710 {
00711     //Returning the more strict immutability between the applet immutability and Corona one
00712     ImmutabilityType coronaImmutability = Mutable;
00713 
00714     if (qobject_cast<Corona*>(scene())) {
00715         coronaImmutability = static_cast<Corona*>(scene())->immutability();
00716     }
00717 
00718     if (coronaImmutability == SystemImmutable) {
00719         return SystemImmutable;
00720     } else if (coronaImmutability == UserImmutable && d->immutability != SystemImmutable) {
00721         return UserImmutable;
00722     } else {
00723         return d->immutability;
00724     }
00725 }
00726 
00727 void Applet::setImmutability(const ImmutabilityType immutable)
00728 {
00729     if (d->immutability == immutable) {
00730         return;
00731     }
00732 
00733     d->immutability = immutable;
00734     updateConstraints(ImmutableConstraint);
00735 }
00736 
00737 Applet::BackgroundHints Applet::backgroundHints() const
00738 {
00739     return d->backgroundHints;
00740 }
00741 
00742 void Applet::setBackgroundHints(const BackgroundHints hints)
00743 {
00744     d->backgroundHints = hints;
00745 
00746     //Draw the standard background?
00747     if ((hints & StandardBackground) || (hints & TranslucentBackground)) {
00748         if (!d->background) {
00749             d->background = new Plasma::FrameSvg(this);
00750         }
00751 
00752         if ((hints & TranslucentBackground) &&
00753             Plasma::Theme::defaultTheme()->currentThemeHasImage("widgets/translucentbackground")) {
00754             d->background->setImagePath("widgets/translucentbackground");
00755         } else {
00756             d->background->setImagePath("widgets/background");
00757         }
00758 
00759         d->background->setEnabledBorders(Plasma::FrameSvg::AllBorders);
00760         qreal left, top, right, bottom;
00761         d->background->getMargins(left, top, right, bottom);
00762         setContentsMargins(left, right, top, bottom);
00763         QSizeF fitSize(left + right, top + bottom);
00764         if (minimumSize().expandedTo(fitSize) != minimumSize()) {
00765             setMinimumSize(minimumSize().expandedTo(fitSize));
00766         }
00767         d->background->resizeFrame(boundingRect().size());
00768 
00769         //if the background has an "overlay" element decide a random position for it and then save it so it's consistent across plasma starts
00770         if (d->background->hasElement("overlay")) {
00771             QSize overlaySize = d->background->elementSize("overlay");
00772 
00773             d->background->d->overlayPos = config().readEntry("overlayposition", QPoint(overlaySize.width()*2, overlaySize.height()*2));
00774 
00775             //position can never be overlaySize.width()*2, overlaySize.height()*2, if it is means we didn't found the position in the config file, or the theme is changed and the overlay size is smaller now
00776             if (d->background->d->overlayPos.x() >= overlaySize.width()*2 ||
00777                 d->background->d->overlayPos.y() >= overlaySize.height()*2) {
00778                 qsrand(id() + QDateTime::currentDateTime().toTime_t());
00779 
00780                 d->background->d->overlayPos.rx() = - (overlaySize.width() /4) + (overlaySize.width() /4) * (qrand() % (4 + 1));
00781 
00782                 d->background->d->overlayPos.ry() = - (overlaySize.height() /4) + (overlaySize.height() /4) * (qrand() % (4 + 1));
00783 
00784                 config().writeEntry("overlayposition", d->background->d->overlayPos);
00785             }
00786         }
00787 
00788     } else if (d->background) {
00789         qreal left, top, right, bottom;
00790         d->background->getMargins(left, top, right, bottom);
00791         //Setting a minimum size of 0,0 would result in the panel to be only
00792         //on the first virtual desktop
00793         setMinimumSize(qMax(minimumSize().width() - left - right, qreal(1.0)),
00794                        qMax(minimumSize().height() - top - bottom, qreal(1.0)));
00795 
00796         delete d->background;
00797         d->background = 0;
00798         setContentsMargins(0, 0, 0, 0);
00799     }
00800 }
00801 
00802 bool Applet::hasFailedToLaunch() const
00803 {
00804     return d->failed;
00805 }
00806 
00807 void Applet::paintWindowFrame(QPainter *painter,
00808                               const QStyleOptionGraphicsItem *option, QWidget *widget)
00809 {
00810     Q_UNUSED(painter)
00811     Q_UNUSED(option)
00812     Q_UNUSED(widget)
00813     //Here come the code for the window frame
00814     //kDebug() << windowFrameGeometry();
00815     //painter->drawRoundedRect(windowFrameGeometry(), 5, 5);
00816 }
00817 
00818 bool Applet::configurationRequired() const
00819 {
00820     return d->needsConfig;
00821 }
00822 
00823 void Applet::setConfigurationRequired(bool needsConfig, const QString &reason)
00824 {
00825     if (d->needsConfig == needsConfig) {
00826         return;
00827     }
00828 
00829     d->needsConfig = needsConfig;
00830 
00831     if (!needsConfig) {
00832         d->destroyMessageOverlay();
00833         return;
00834     }
00835 
00836     d->createMessageOverlay();
00837 
00838     QGraphicsGridLayout *configLayout = new QGraphicsGridLayout(d->messageOverlay);
00839     configLayout->setContentsMargins(0, 0, 0, 0);
00840 
00841   //  configLayout->addStretch();
00842     configLayout->setColumnStretchFactor(0, 10);
00843     configLayout->setColumnStretchFactor(2, 10);
00844     configLayout->setRowStretchFactor(0, 10);
00845     configLayout->setRowStretchFactor(3, 10);
00846 
00847     int row = 1;
00848     if (!reason.isEmpty()) {
00849         Label *explanation = new Label(d->messageOverlay);
00850         explanation->setText(reason);
00851         configLayout->addItem(explanation, row, 1);
00852         configLayout->setColumnStretchFactor(1, 10);
00853         ++row;
00854         //configLayout->setAlignment(explanation, Qt::AlignBottom | Qt::AlignCenter);
00855     }
00856 
00857     //popupapplets in panels just show an icon, otherwise the button is too large
00858     Plasma::FormFactor f = formFactor();
00859     if (f == Plasma::Horizontal || f == Plasma::Vertical) {
00860         IconWidget *configWidget = new IconWidget(d->messageOverlay);
00861         configWidget->setSvg("widgets/configuration-icons", "configure");
00862         configWidget->setDrawBackground(true);
00863         connect(configWidget, SIGNAL(clicked()), this, SLOT(showConfigurationInterface()));
00864         configLayout->addItem(configWidget, row, 1);
00865         // raise the overlay above all the other children!
00866         int zValue = 100;
00867         foreach (QGraphicsItem *child, QGraphicsItem::children()) {
00868             if (child->zValue() > zValue) {
00869                 zValue = child->zValue() + 1;
00870             }
00871         }
00872         configWidget->setZValue(zValue);
00873     } else {
00874         PushButton *configWidget = new PushButton(d->messageOverlay);
00875         configWidget->setText(i18n("Configure..."));
00876         connect(configWidget, SIGNAL(clicked()), this, SLOT(showConfigurationInterface()));
00877         configLayout->addItem(configWidget, row, 1);
00878     }
00879 
00880     //configLayout->setAlignment(configWidget, Qt::AlignTop | Qt::AlignCenter);
00881     //configLayout->addStretch();
00882 
00883     d->messageOverlay->show();
00884 }
00885 
00886 void Applet::flushPendingConstraintsEvents()
00887 {
00888     if (d->pendingConstraints == NoConstraint) {
00889         return;
00890     }
00891 
00892     if (d->constraintsTimerId) {
00893         killTimer(d->constraintsTimerId);
00894         d->constraintsTimerId = 0;
00895     }
00896 
00897     //kDebug() << "fushing constraints: " << d->pendingConstraints << "!!!!!!!!!!!!!!!!!!!!!!!!!!!";
00898     Plasma::Constraints c = d->pendingConstraints;
00899     d->pendingConstraints = NoConstraint;
00900 
00901     if (c & Plasma::StartupCompletedConstraint) {
00902         //common actions
00903         bool unlocked = immutability() == Mutable;
00904         //FIXME desktop containments can't be removed while in use.
00905         //it's kinda silly to have a keyboard shortcut for something that can only be used when the
00906         //shortcut isn't active.
00907         QAction *closeApplet = new QAction(this);
00908         closeApplet->setIcon(KIcon("edit-delete"));
00909         closeApplet->setEnabled(unlocked);
00910         closeApplet->setVisible(unlocked);
00911         closeApplet->setShortcutContext(Qt::WidgetShortcut); //don't clash with other views
00912         closeApplet->setText(i18nc("%1 is the name of the applet", "Remove this %1", name()));
00913         if (isContainment()) {
00914             closeApplet->setShortcut(QKeySequence("ctrl+shift+r"));
00915         } else {
00916             closeApplet->setShortcut(QKeySequence("ctrl+r"));
00917         }
00918         connect(closeApplet, SIGNAL(triggered(bool)), this, SLOT(selectItemToDestroy()));
00919         d->actions.addAction("remove", closeApplet);
00920     }
00921 
00922     if (c & Plasma::ImmutableConstraint) {
00923         bool unlocked = immutability() == Mutable;
00924         QAction *action = d->actions.action("remove");
00925         if (action) {
00926             action->setVisible(unlocked);
00927             action->setEnabled(unlocked);
00928         }
00929 
00930         bool canConfig = unlocked || KAuthorized::authorize("PlasmaAllowConfigureWhenLocked");
00931         if (canConfig) {
00932             action = d->actions.action("configure");
00933             if (action) {
00934                 action->setVisible(canConfig);
00935                 action->setEnabled(canConfig);
00936             }
00937         }
00938     }
00939 
00940     if (c & Plasma::SizeConstraint) {
00941         if (d->messageOverlay) {
00942             d->messageOverlay->setGeometry(QRectF(QPointF(0, 0), geometry().size()));
00943 
00944             QGraphicsItem *button = 0;
00945             QList<QGraphicsItem*> children = d->messageOverlay->QGraphicsItem::children();
00946 
00947             if (!children.isEmpty()) {
00948                 button = children.first();
00949             }
00950 
00951             if (button) {
00952                 QSizeF s = button->boundingRect().size();
00953                 button->setPos(d->messageOverlay->boundingRect().width() / 2 - s.width() / 2,
00954                         d->messageOverlay->boundingRect().height() / 2 - s.height() / 2);
00955             }
00956         }
00957 
00958         if (d->busyWidget && d->busyWidget->isVisible()) {
00959             int busySize = qMin(size().width(), size().height())/3;
00960             QRect busyRect(0, 0, busySize, busySize);
00961             busyRect.moveCenter(boundingRect().center().toPoint());
00962             d->busyWidget->setGeometry(busyRect);
00963         }
00964 
00965         if (d->started && layout()) {
00966             layout()->updateGeometry();
00967         }
00968     }
00969 
00970     if (c & Plasma::FormFactorConstraint) {
00971         FormFactor f = formFactor();
00972         if (!isContainment() && f != Vertical && f != Horizontal) {
00973             setBackgroundHints(d->backgroundHints | StandardBackground);
00974         } else if(d->backgroundHints & StandardBackground) {
00975             setBackgroundHints(d->backgroundHints ^ StandardBackground);
00976         } else if(d->backgroundHints & TranslucentBackground) {
00977             setBackgroundHints(d->backgroundHints ^ TranslucentBackground);
00978         }
00979 
00980         if (d->failed) {
00981             if (f == Vertical || f == Horizontal) {
00982                 setMinimumSize(0, 0);
00983                 QGraphicsLayoutItem *item = layout()->itemAt(1);
00984                 layout()->removeAt(1);
00985                 delete item;
00986             }
00987         }
00988     }
00989 
00990     if (c & Plasma::SizeConstraint || c & Plasma::FormFactorConstraint) {
00991         if (aspectRatioMode() == Plasma::Square) {
00992             // enforce square size in panels
00993             if (formFactor() == Horizontal) {
00994                 setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding));
00995             } else if (formFactor() == Vertical) {
00996                 setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
00997             }
00998 
00999             updateGeometry();
01000         } else if (aspectRatioMode() == Plasma::ConstrainedSquare) {
01001             // enforce a constrained square size in panels
01002             if (formFactor() == Horizontal) {
01003                 setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding));
01004             } else if (formFactor() == Vertical) {
01005                 setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed));
01006             }
01007 
01008             updateGeometry();
01009         }
01010     }
01011 
01012     // now take care of constraints in special subclasses: Contaiment and PopupApplet
01013     Containment* containment = qobject_cast<Plasma::Containment*>(this);
01014     if (isContainment() && containment) {
01015         containment->d->containmentConstraintsEvent(c);
01016     }
01017 
01018     PopupApplet* popup = qobject_cast<Plasma::PopupApplet*>(this);
01019     if (popup) {
01020         popup->d->popupConstraintsEvent(c);
01021     }
01022 
01023     // pass the constraint on to the actual subclass
01024     constraintsEvent(c);
01025 
01026     if (c & StartupCompletedConstraint) {
01027         // start up is done, we can now go do a mod timer
01028         if (d->modificationsTimerId > 0) {
01029             killTimer(d->modificationsTimerId);
01030         }
01031         d->modificationsTimerId = 0;
01032 
01033         if (!isContainment()) {
01034             setHasConfigurationInterface(true);
01035         }
01036     }
01037 }
01038 
01039 int Applet::type() const
01040 {
01041     return Type;
01042 }
01043 
01044 QList<QAction*> Applet::contextualActions()
01045 {
01046     //kDebug() << "empty context actions";
01047     return d->script ? d->script->contextualActions() : QList<QAction*>();
01048 }
01049 
01050 QAction *Applet::action(QString name) const
01051 {
01052     return d->actions.action(name);
01053 }
01054 
01055 void Applet::addAction(QString name, QAction *action)
01056 {
01057     d->actions.addAction(name, action);
01058 }
01059 
01060 void Applet::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
01061 {
01062     if (!d->started) {
01063         kDebug() << "not started";
01064         return;
01065     }
01066 
01067     if (transform().isRotating()) {
01068         painter->setRenderHint(QPainter::SmoothPixmapTransform);
01069         painter->setRenderHint(QPainter::Antialiasing);
01070     }
01071 
01072     if (d->background &&
01073         formFactor() != Plasma::Vertical &&
01074         formFactor() != Plasma::Horizontal) {
01075         //kDebug() << "option rect is" << option->rect;
01076         d->background->paintFrame(painter);
01077     }
01078 
01079     if (d->failed) {
01080         kDebug() << "failed!";
01081         return;
01082     }
01083 
01084     qreal left, top, right, bottom;
01085     getContentsMargins(&left, &top, &right, &bottom);
01086     QRect contentsRect = QRectF(QPointF(0, 0),
01087                                 boundingRect().size()).adjusted(left, top, -right, -bottom).toRect();
01088 
01089     if (widget && isContainment()) {
01090         // note that the widget we get is actually the viewport of the view, not the view itself
01091         View* v = qobject_cast<Plasma::View*>(widget->parent());
01092         Containment* c = qobject_cast<Plasma::Containment*>(this);
01093 
01094         //update the view transform of the toolbox, since it ignores transforms
01095         if (c && c->d->toolBox) {
01096             if (c->d->toolBox->viewTransform().isScaling() && !v->transform().isScaling()) {
01097                 c->d->positionToolBox();
01098             }
01099             if (v) {
01100                 c->d->toolBox->setViewTransform(v->transform());
01101             }
01102         }
01103 
01104         if (!v || v->isWallpaperEnabled()) {
01105 
01106             // paint the wallpaper
01107             if (c && c->drawWallpaper() && c->wallpaper()) {
01108                 Wallpaper *w = c->wallpaper();
01109                 if (!w->isInitialized()) {
01110                     // delayed paper initialization
01111                     KConfigGroup wallpaperConfig = c->config();
01112                     wallpaperConfig = KConfigGroup(&wallpaperConfig, "Wallpaper");
01113                     wallpaperConfig = KConfigGroup(&wallpaperConfig, w->pluginName());
01114                     w->restore(wallpaperConfig);
01115                 }
01116 
01117                 painter->save();
01118                 c->wallpaper()->paint(painter, option->exposedRect);
01119                 painter->restore();
01120             }
01121 
01122             // .. and now paint the actual containment interface, but with
01123             //  a Containment style option based on the one we get
01124             Containment::StyleOption coption(*option);
01125             coption.view = v;
01126             paintInterface(painter, &coption, contentsRect);
01127         }
01128     } else {
01129         //kDebug() << "paint interface of" << (QObject*) this;
01130         // paint the applet's interface
01131         paintInterface(painter, option, contentsRect);
01132     }
01133 }
01134 
01135 void Applet::paintInterface(QPainter *painter, const QStyleOptionGraphicsItem *option, const QRect &contentsRect)
01136 {
01137     if (d->script) {
01138         d->script->paintInterface(painter, option, contentsRect);
01139     } else {
01140         //kDebug() << "Applet::paintInterface() default impl";
01141     }
01142 }
01143 
01144 FormFactor Applet::formFactor() const
01145 {
01146     Containment *c = containment();
01147     return c ? c->d->formFactor : Plasma::Planar;
01148 }
01149 
01150 Containment *Applet::containment() const
01151 {
01152     if (isContainment()) {
01153         Containment *c = qobject_cast<Containment*>(const_cast<Applet*>(this));
01154         if (c) {
01155             return c;
01156         }
01157     }
01158 
01159     QGraphicsItem *parent = parentItem();
01160     Containment *c = 0;
01161 
01162     while (parent) {
01163         Containment *possibleC = dynamic_cast<Containment*>(parent);
01164         if (possibleC && possibleC->isContainment()) {
01165             c = possibleC;
01166             break;
01167         }
01168         parent = parent->parentItem();
01169     }
01170 
01171     return c;
01172 }
01173 
01174 void Applet::setGlobalShortcut(const KShortcut &shortcut)
01175 {
01176     if (!d->activationAction) {
01177         d->activationAction = new KAction(this);
01178         d->activationAction->setText(i18n("Activate %1 Widget", name()));
01179         d->activationAction->setObjectName(QString("activate widget %1").arg(id())); // NO I18N
01180         connect(d->activationAction, SIGNAL(triggered()), this, SIGNAL(activate()));
01181         connect(this, SIGNAL(activate()), this, SLOT(setFocus()));
01182 
01183         QList<QWidget *> widgets = d->actions.associatedWidgets();
01184         foreach (QWidget *w, widgets) {
01185             w->addAction(d->activationAction);
01186         }
01187     }
01188 
01189     //kDebug() << "before" << shortcut.primary() << d->activationAction->globalShortcut().primary();
01190     d->activationAction->setGlobalShortcut(
01191         shortcut,
01192         KAction::ShortcutTypes(KAction::ActiveShortcut | KAction::DefaultShortcut),
01193         KAction::NoAutoloading);
01194     //kDebug() << "after" << shortcut.primary() << d->activationAction->globalShortcut().primary();
01195 }
01196 
01197 KShortcut Applet::globalShortcut() const
01198 {
01199     if (d->activationAction) {
01200         return d->activationAction->globalShortcut();
01201     }
01202 
01203     return KShortcut();
01204 }
01205 
01206 bool Applet::isPopupShowing() const
01207 {
01208     return false;
01209 }
01210 
01211 void Applet::addAssociatedWidget(QWidget *widget)
01212 {
01213     d->actions.addAssociatedWidget(widget);
01214 }
01215 
01216 void Applet::removeAssociatedWidget(QWidget *widget)
01217 {
01218     d->actions.removeAssociatedWidget(widget);
01219 }
01220 
01221 Location Applet::location() const
01222 {
01223     Containment *c = containment();
01224     return c ? c->d->location : Plasma::Desktop;
01225 }
01226 
01227 Context *Applet::context() const
01228 {
01229     Containment *c = containment();
01230     Q_ASSERT(c);
01231     return c->d->context();
01232 }
01233 
01234 Plasma::AspectRatioMode Applet::aspectRatioMode() const
01235 {
01236     return d->aspectRatioMode;
01237 }
01238 
01239 void Applet::setAspectRatioMode(Plasma::AspectRatioMode mode)
01240 {
01241     d->aspectRatioMode = mode;
01242 }
01243 
01244 void Applet::registerAsDragHandle(QGraphicsItem *item)
01245 {
01246     if (!item || d->registeredAsDragHandle.contains(item)) {
01247         return;
01248     }
01249 
01250     d->registeredAsDragHandle.insert(item);
01251     item->installSceneEventFilter(this);
01252 }
01253 
01254 void Applet::unregisterAsDragHandle(QGraphicsItem *item)
01255 {
01256     if (!item) {
01257         return;
01258     }
01259 
01260     if (d->registeredAsDragHandle.remove(item)) {
01261         item->removeSceneEventFilter(this);
01262     }
01263 }
01264 
01265 bool Applet::isRegisteredAsDragHandle(QGraphicsItem *item)
01266 {
01267     return d->registeredAsDragHandle.contains(item);
01268 }
01269 
01270 bool Applet::hasConfigurationInterface() const
01271 {
01272     return d->hasConfigurationInterface;
01273 }
01274 
01275 void Applet::setHasConfigurationInterface(bool hasInterface)
01276 {
01277     if (d->hasConfigurationInterface == hasInterface) {
01278         return;
01279     }
01280 
01281     d->hasConfigurationInterface = hasInterface;
01282     //config action
01283     //TODO respect security when it's implemented (4.2)
01284     QAction *configAction = d->actions.action("configure");
01285     if (hasInterface) {
01286         if (!configAction) { //should be always true
01287             configAction = new QAction(i18n("%1 Settings", name()), this);
01288             configAction->setIcon(KIcon("configure"));
01289             configAction->setShortcutContext(Qt::WidgetShortcut); //don't clash with other views
01290             bool unlocked = immutability() == Mutable;
01291             bool canConfig = unlocked || KAuthorized::authorize("PlasmaAllowConfigureWhenLocked");
01292             configAction->setVisible(canConfig);
01293             configAction->setEnabled(canConfig);
01294             if (isContainment()) {
01295                 //kDebug() << "I am a containment";
01296                 configAction->setShortcut(QKeySequence("ctrl+shift+s"));
01297             } else {
01298                 configAction->setShortcut(QKeySequence("ctrl+s"));
01299             }
01300             connect(configAction, SIGNAL(triggered(bool)),
01301                     this, SLOT(showConfigurationInterface()));
01302             d->actions.addAction("configure", configAction);
01303         }
01304     } else {
01305         d->actions.removeAction(configAction);
01306     }
01307 }
01308 
01309 bool Applet::eventFilter(QObject *o, QEvent *e)
01310 {
01311     return QObject::eventFilter(o, e);
01312 }
01313 
01314 bool Applet::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
01315 {
01316     switch (event->type()) {
01317     case QEvent::GraphicsSceneMouseMove:
01318     {
01319         // don't move when the containment is not mutable,
01320         // in the rare case the containment doesn't exists consider it as mutable
01321         if (d->registeredAsDragHandle.contains(watched)) {
01322             Containment *c = containment();
01323             if (!c || c->immutability() == Mutable) {
01324                 mouseMoveEvent(static_cast<QGraphicsSceneMouseEvent*>(event));
01325                 return true;
01326             }
01327         }
01328         break;
01329     }
01330 
01331     default:
01332         break;
01333     }
01334 
01335     return QGraphicsItem::sceneEventFilter(watched, event);
01336 }
01337 
01338 void Applet::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
01339 {
01340     if (immutability() == Mutable && formFactor() == Plasma::Planar) {
01341         QGraphicsItem *parent = parentItem();
01342         Plasma::Applet *applet = qgraphicsitem_cast<Plasma::Applet*>(parent);
01343 
01344         if (applet && applet->isContainment()) {
01345             // our direct parent is a containment. just move ourselves.
01346             QPointF curPos = event->pos();
01347             QPointF lastPos = event->lastPos();
01348             QPointF delta = curPos - lastPos;
01349 
01350             moveBy(delta.x(), delta.y());
01351         } else if (parent) {
01352             //don't move the icon as well because our parent
01353             //(usually an appletHandle) will do it for us
01354             //parent->moveBy(delta.x(),delta.y());
01355             QPointF curPos = parent->transform().map(event->pos());
01356             QPointF lastPos = parent->transform().map(event->lastPos());
01357             QPointF delta = curPos - lastPos;
01358 
01359             parent->setPos(parent->pos() + delta);
01360         }
01361     }
01362 }
01363 
01364 void Applet::focusInEvent(QFocusEvent *event)
01365 {
01366     if (!isContainment() && containment()) {
01367         //focusing an applet may trigger this event again, but we won't be here more than twice
01368         containment()->d->focusApplet(this);
01369     }
01370 
01371     QGraphicsWidget::focusInEvent(event);
01372 }
01373 
01374 void Applet::resizeEvent(QGraphicsSceneResizeEvent *event)
01375 {
01376     QGraphicsWidget::resizeEvent(event);
01377 
01378     if (d->background) {
01379         d->background->resizeFrame(boundingRect().size());
01380     }
01381 
01382     updateConstraints(Plasma::SizeConstraint);
01383 
01384     d->scheduleModificationNotification();
01385     emit geometryChanged();
01386 }
01387 
01388 void Applet::showConfigurationInterface()
01389 {
01390     if (!hasConfigurationInterface()) {
01391         return;
01392     }
01393 
01394     if (immutability() != Mutable && !KAuthorized::authorize("PlasmaAllowConfigureWhenLocked")) {
01395         //FIXME: in 4.3 add an explanatory dialog
01396         return;
01397     }
01398 
01399     const QString dialogId = QString("%1settings%2").arg(id()).arg(name());
01400     KConfigDialog * dlg = KConfigDialog::exists(dialogId);
01401 
01402     if (dlg) {
01403         KWindowSystem::setOnDesktop(dlg->winId(), KWindowSystem::currentDesktop());
01404         dlg->show();
01405         KWindowSystem::activateWindow(dlg->winId());
01406         return;
01407     }
01408 
01409     const QString windowTitle = i18nc("@title:window", "%1 Settings", name());
01410     if (d->package && d->configLoader) {
01411         QString uiFile = d->package->filePath("mainconfigui");
01412         if (uiFile.isEmpty()) {
01413             return;
01414         }
01415 
01416         KConfigDialog *dialog = new KConfigDialog(0, dialogId, d->configLoader);
01417         dialog->setWindowTitle(windowTitle);
01418         dialog->setAttribute(Qt::WA_DeleteOnClose, true);
01419 
01420         QUiLoader loader;
01421         QFile f(uiFile);
01422         if (!f.open(QIODevice::ReadOnly)) {
01423             delete dialog;
01424 
01425             if (d->script) {
01426                 d->script->showConfigurationInterface();
01427             }
01428             return;
01429         }
01430 
01431         QWidget *w = loader.load(&f);
01432         f.close();
01433 
01434         dialog->addPage(w, i18n("Settings"), icon(), i18n("%1 Settings", name()));
01435         d->addGlobalShortcutsPage(dialog);
01436         connect(dialog, SIGNAL(applyClicked()), this, SLOT(configDialogFinished()));
01437         connect(dialog, SIGNAL(okClicked()), this, SLOT(configDialogFinished()));
01438         //FIXME: in this case use another ad-hoc slot?
01439         connect(dialog, SIGNAL(finished()), this, SLOT(configDialogFinished()));
01440         dialog->show();
01441     } else if (d->script) {
01442         //FIXME: global shorcuts?
01443         d->script->showConfigurationInterface();
01444     } else {
01445         KConfigSkeleton *nullManager = new KConfigSkeleton(0);
01446         KConfigDialog *dialog = new KConfigDialog(0, dialogId, nullManager);
01447         dialog->setFaceType(KPageDialog::Auto);
01448         dialog->setWindowTitle(windowTitle);
01449         dialog->setAttribute(Qt::WA_DeleteOnClose, true);
01450         createConfigurationInterface(dialog);
01451         d->addGlobalShortcutsPage(dialog);
01452         connect(dialog, SIGNAL(finished()), nullManager, SLOT(deleteLater()));
01453         //TODO: Apply button does not correctly work for now, so do not show it
01454         dialog->showButton(KDialog::Apply, false);
01455         connect(dialog, SIGNAL(applyClicked()), this, SLOT(configDialogFinished()));
01456         connect(dialog, SIGNAL(okClicked()), this, SLOT(configDialogFinished()));
01457         connect(dialog, SIGNAL(finished()), this, SLOT(configDialogFinished()));
01458         dialog->show();
01459     }
01460 
01461     emit releaseVisualFocus();
01462 }
01463 
01464 void AppletPrivate::addGlobalShortcutsPage(KConfigDialog *dialog)
01465 {
01466     if (isContainment) {
01467         return;
01468     }
01469 
01470     QWidget *page = new QWidget;
01471     QVBoxLayout *layout = new QVBoxLayout(page);
01472 
01473     if (!shortcutEditor) {
01474         shortcutEditor = new KKeySequenceWidget(page);
01475         QObject::connect(shortcutEditor, SIGNAL(destroyed(QObject*)), q, SLOT(clearShortcutEditorPtr()));
01476     }
01477 
01478     shortcutEditor->setKeySequence(q->globalShortcut().primary());
01479     layout->addWidget(shortcutEditor);
01480     layout->addStretch();
01481     dialog->addPage(page, i18n("Keyboard Shortcut"), "preferences-desktop-keyboard");
01482 }
01483 
01484 void AppletPrivate::clearShortcutEditorPtr()
01485 {
01486     shortcutEditor = 0;
01487 }
01488 
01489 void AppletPrivate::configDialogFinished()
01490 {
01491     if (shortcutEditor) {
01492         QKeySequence sequence = shortcutEditor->keySequence();
01493         if (sequence != q->globalShortcut().primary()) {
01494             q->setGlobalShortcut(KShortcut(sequence));
01495             emit q->configNeedsSaving();
01496         }
01497     }
01498 
01499     q->configChanged();
01500 }
01501 
01502 void Applet::configChanged()
01503 {
01504     if (d->script) {
01505         d->script->configChanged();
01506     }
01507 }
01508 
01509 void Applet::createConfigurationInterface(KConfigDialog *parent)
01510 {
01511     Q_UNUSED(parent)
01512     // virtual method reimplemented by subclasses.
01513     // do not put anything here ...
01514 }
01515 
01516 KPluginInfo::List Applet::listAppletInfo(const QString &category,
01517                                          const QString &parentApp)
01518 {
01519     QString constraint;
01520 
01521     if (parentApp.isEmpty()) {
01522         constraint.append("not exist [X-KDE-ParentApp]");
01523     } else {
01524         constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'");
01525     }
01526 
01527     if (!category.isEmpty()) {
01528         if (!constraint.isEmpty()) {
01529             constraint.append(" and ");
01530         }
01531 
01532         constraint.append("[X-KDE-PluginInfo-Category] == '").append(category).append("'");
01533         if (category == "Miscellaneous") {
01534             constraint.append(" or (not exist [X-KDE-PluginInfo-Category] or [X-KDE-PluginInfo-Category] == '')");
01535         }
01536     }
01537 
01538     KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
01539     //kDebug() << "Applet::listAppletInfo constraint was '" << constraint
01540     //         << "' which got us " << offers.count() << " matches";
01541     return KPluginInfo::fromServices(offers);
01542 }
01543 
01544 KPluginInfo::List Applet::listAppletInfoForMimetype(const QString &mimetype)
01545 {
01546     QString constraint = QString("'%1' in [X-Plasma-DropMimeTypes]").arg(mimetype);
01547     //kDebug() << "listAppletInfoForMimetype with" << mimetype << constraint;
01548     KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
01549     return KPluginInfo::fromServices(offers);
01550 }
01551 
01552 QStringList Applet::listCategories(const QString &parentApp, bool visibleOnly)
01553 {
01554     QString constraint = "exist [X-KDE-PluginInfo-Category]";
01555 
01556     if (parentApp.isEmpty()) {
01557         constraint.append(" and not exist [X-KDE-ParentApp]");
01558     } else {
01559         constraint.append(" and [X-KDE-ParentApp] == '").append(parentApp).append("'");
01560     }
01561 
01562     KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
01563     QStringList categories;
01564     foreach (const KService::Ptr &applet, offers) {
01565         QString appletCategory = applet->property("X-KDE-PluginInfo-Category").toString();
01566         if (visibleOnly && applet->noDisplay()) {
01567             // we don't want to show the hidden category
01568             continue;
01569         }
01570 
01571         //kDebug() << "   and we have " << appletCategory;
01572         if (appletCategory.isEmpty()) {
01573             if (!categories.contains(i18nc("misc category", "Miscellaneous"))) {
01574                 categories << i18nc("misc category", "Miscellaneous");
01575             }
01576         } else  if (!categories.contains(appletCategory)) {
01577             categories << appletCategory;
01578         }
01579     }
01580 
01581     categories.sort();
01582     return categories;
01583 }
01584 
01585 Applet *Applet::load(const QString &appletName, uint appletId, const QVariantList &args)
01586 {
01587     if (appletName.isEmpty()) {
01588         return 0;
01589     }
01590 
01591     QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(appletName);
01592     KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
01593 
01594     bool isContainment = false;
01595     if (offers.isEmpty()) {
01596         //TODO: what would be -really- cool is offer to try and download the applet
01597         //      from the network at this point
01598         offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint);
01599         isContainment = true;
01600         if (offers.isEmpty()) {
01601             kDebug() << "offers is empty for " << appletName;
01602             return 0;
01603         }
01604     } /* else if (offers.count() > 1) {
01605         kDebug() << "hey! we got more than one! let's blindly take the first one";
01606     } */
01607 
01608     KService::Ptr offer = offers.first();
01609 
01610     if (appletId == 0) {
01611         appletId = ++AppletPrivate::s_maxAppletId;
01612     }
01613 
01614     if (!offer->property("X-Plasma-API").toString().isEmpty()) {
01615         kDebug() << "we have a script using the"
01616                  << offer->property("X-Plasma-API").toString() << "API";
01617         if (isContainment) {
01618             return new Containment(0, offer->storageId(), appletId);
01619         }
01620         return new Applet(0, offer->storageId(), appletId);
01621     }
01622 
01623     KPluginLoader plugin(*offer);
01624 
01625     if (!Plasma::isPluginVersionCompatible(plugin.pluginVersion()) &&
01626         (appletName != "internal:extender")) {
01627         return 0;
01628     }
01629 
01630     QVariantList allArgs;
01631     allArgs << offer->storageId() << appletId << args;
01632     QString error;
01633     Applet *applet;
01634 
01635     if (appletName == "internal:extender") {
01636         applet = new ExtenderApplet(0, allArgs);
01637     } else {
01638         applet = offer->createInstance<Plasma::Applet>(0, allArgs, &error);
01639     }
01640 
01641     if (!applet) {
01642         kDebug() << "Couldn't load applet \"" << appletName << "\"! reason given: " << error;
01643     }
01644 
01645     return applet;
01646 }
01647 
01648 Applet *Applet::load(const KPluginInfo &info, uint appletId, const QVariantList &args)
01649 {
01650     if (!info.isValid()) {
01651         return 0;
01652     }
01653 
01654     return load(info.pluginName(), appletId, args);
01655 }
01656 
01657 QVariant Applet::itemChange(GraphicsItemChange change, const QVariant &value)
01658 {
01659     QVariant ret = QGraphicsWidget::itemChange(change, value);
01660 
01661     //kDebug() << change;
01662     switch (change) {
01663     case ItemSceneHasChanged:
01664     {
01665         QGraphicsScene *newScene = qvariant_cast<QGraphicsScene*>(value);
01666         if (newScene) {
01667             d->checkImmutability();
01668         }
01669     }
01670         break;
01671     case ItemPositionChange:
01672         return (immutability() == Mutable || formFactor() == Horizontal || formFactor() == Vertical) ? value : pos();
01673         break;
01674     case ItemTransformChange:
01675         return immutability() == Mutable ? value : transform();
01676         break;
01677     case ItemPositionHasChanged:
01678         emit geometryChanged();
01679         // fall through!
01680     case ItemTransformHasChanged:
01681         d->scheduleModificationNotification();
01682         break;
01683     default:
01684         break;
01685     };
01686 
01687     return ret;
01688 }
01689 
01690 QPainterPath Applet::shape() const
01691 {
01692     if (d->script) {
01693         return d->script->shape();
01694     }
01695 
01696     return QGraphicsWidget::shape();
01697 }
01698 
01699 QSizeF Applet::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
01700 {
01701     QSizeF hint = QGraphicsWidget::sizeHint(which, constraint);
01702 
01703     //in panels make sure that the contents won't exit from the panel
01704     if (formFactor() == Horizontal && which == Qt::MinimumSize) {
01705         hint.setHeight(0);
01706     } else if (formFactor() == Vertical && which == Qt::MinimumSize) {
01707         hint.setWidth(0);
01708     }
01709 
01710     // enforce a square size in panels
01711     if (d->aspectRatioMode == Plasma::Square) {
01712         if (formFactor() == Horizontal) {
01713             hint.setWidth(size().height());
01714         } else if (formFactor() == Vertical) {
01715             hint.setHeight(size().width());
01716         }
01717     } else if (d->aspectRatioMode == Plasma::ConstrainedSquare) {
01718         //enforce a size not wider than tall
01719         if (formFactor() == Horizontal &&
01720             (which == Qt::MaximumSize || size().height() <= KIconLoader::SizeLarge)) {
01721             hint.setWidth(size().height());
01722         //enforce a size not taller than wide
01723         } else if (formFactor() == Vertical &&
01724                    (which == Qt::MaximumSize || size().width() <= KIconLoader::SizeLarge)) {
01725             hint.setHeight(size().width());
01726         }
01727     }
01728 
01729     return hint;
01730 }
01731 
01732 void Applet::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
01733 {
01734     Q_UNUSED(event)
01735 }
01736 
01737 void Applet::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
01738 {
01739     Q_UNUSED(event)
01740 }
01741 
01742 void Applet::timerEvent(QTimerEvent *event)
01743 {
01744     if (d->transient) {
01745         killTimer(d->constraintsTimerId);
01746         killTimer(d->modificationsTimerId);
01747         return;
01748     }
01749 
01750     if (event->timerId() == d->constraintsTimerId) {
01751         killTimer(d->constraintsTimerId);
01752         d->constraintsTimerId = 0;
01753 
01754         // Don't flushPendingConstraints if we're just starting up
01755         // flushPendingConstraints will be called by Corona
01756         if(!(d->pendingConstraints & Plasma::StartupCompletedConstraint)) {
01757             flushPendingConstraintsEvents();
01758         }
01759     } else if (event->timerId() == d->modificationsTimerId) {
01760         killTimer(d->modificationsTimerId);
01761         d->modificationsTimerId = 0;
01762         // invalid group, will result in save using the default group
01763         KConfigGroup cg;
01764         save(cg);
01765         emit configNeedsSaving();
01766     }
01767 }
01768 
01769 QRect Applet::screenRect() const
01770 {
01771     QGraphicsView *v = view();
01772 
01773     if (v) {
01774         QPointF bottomRight = pos();
01775         bottomRight.rx() += size().width();
01776         bottomRight.ry() += size().height();
01777 
01778         QPoint tL = v->mapToGlobal(v->mapFromScene(pos()));
01779         QPoint bR = v->mapToGlobal(v->mapFromScene(bottomRight));
01780         return QRect(QPoint(tL.x(), tL.y()), QSize(bR.x() - tL.x(), bR.y() - tL.y()));
01781     }
01782 
01783     //The applet doesn't have a view on it.
01784     //So a screenRect isn't relevant.
01785     return QRect(QPoint(0, 0), QSize(0, 0));
01786 }
01787 
01788 void Applet::raise()
01789 {
01790     setZValue(++AppletPrivate::s_maxZValue);
01791 }
01792 
01793 void Applet::lower()
01794 {
01795     setZValue(--AppletPrivate::s_minZValue);
01796 }
01797 
01798 void AppletPrivate::setIsContainment(bool nowIsContainment)
01799 {
01800     if (isContainment == nowIsContainment) {
01801         return;
01802     }
01803 
01804     isContainment = nowIsContainment;
01805 
01806     Containment *c = qobject_cast<Containment*>(q);
01807     if (c) {
01808         if (isContainment) {
01809             // set up the toolbox
01810             c->d->createToolBox();
01811         } else {
01812             delete c->d->toolBox;
01813             c->d->toolBox = 0;
01814         }
01815     }
01816 }
01817 
01818 bool Applet::isContainment() const
01819 {
01820     return d->isContainment;
01821 }
01822 
01823 // PRIVATE CLASS IMPLEMENTATION
01824 
01825 AppletPrivate::AppletPrivate(KService::Ptr service, int uniqueID, Applet *applet)
01826         : appletId(uniqueID),
01827           q(applet),
01828           extender(0),
01829           backgroundHints(Applet::StandardBackground),
01830           appletDescription(service),
01831           messageOverlay(0),
01832           busyWidget(0),
01833           background(0),
01834           script(0),
01835           package(0),
01836           configLoader(0),
01837           mainConfig(0),
01838           pendingConstraints(NoConstraint),
01839           aspectRatioMode(Plasma::KeepAspectRatio),
01840           immutability(Mutable),
01841           actions(applet),
01842           activationAction(0),
01843           shortcutEditor(0),
01844           constraintsTimerId(0),
01845           modificationsTimerId(-1),
01846           hasConfigurationInterface(false),
01847           failed(false),
01848           isContainment(false),
01849           transient(false),
01850           needsConfig(false),
01851           started(false)
01852 {
01853     if (appletId == 0) {
01854         appletId = ++s_maxAppletId;
01855     } else if (appletId > s_maxAppletId) {
01856         s_maxAppletId = appletId;
01857     }
01858 }
01859 
01860 AppletPrivate::~AppletPrivate()
01861 {
01862     modificationsTimerId = -1;
01863 
01864     if (activationAction && activationAction->isGlobalShortcutEnabled()) {
01865         //kDebug() << "reseting global action for" << q->name() << activationAction->objectName();
01866         activationAction->forgetGlobalShortcut();
01867     }
01868 
01869     foreach (const QString &engine, loadedEngines) {
01870         DataEngineManager::self()->unloadEngine(engine);
01871     }
01872 
01873     if (extender) {
01874         delete extender;
01875         extender = 0;
01876     }
01877 
01878     delete script;
01879     script = 0;
01880     delete package;
01881     package = 0;
01882     delete configLoader;
01883     configLoader = 0;
01884     delete mainConfig;
01885     mainConfig = 0;
01886 }
01887 
01888 void AppletPrivate::init()
01889 {
01890     // WARNING: do not access config() OR globalConfig() in this method!
01891     //          that requires a scene, which is not available at this point
01892     q->setCacheMode(Applet::DeviceCoordinateCache);
01893     q->setAcceptsHoverEvents(true);
01894     q->setFlag(QGraphicsItem::ItemIsFocusable, true);
01895     q->setFocusPolicy(Qt::ClickFocus);
01896     // FIXME: adding here because nothing seems to be doing it in QGraphicsView,
01897     // but it doesn't actually work anyways =/
01898     q->setLayoutDirection(qApp->layoutDirection());
01899 
01900     if (!appletDescription.isValid()) {
01901         kDebug() << "Check your constructor! "
01902                  << "You probably want to be passing in a Service::Ptr "
01903                  << "or a QVariantList with a valid storageid as arg[0].";
01904         return;
01905     }
01906 
01907     QString api = appletDescription.property("X-Plasma-API").toString();
01908 
01909     // we have a scripted plasmoid
01910     if (!api.isEmpty()) {
01911         // find where the Package is
01912         QString path = KStandardDirs::locate(
01913             "data",
01914             "plasma/plasmoids/" + appletDescription.pluginName() + '/');
01915 
01916         if (path.isEmpty()) {
01917             q->setFailedToLaunch(
01918                 true,
01919                 i18nc("Package file, name of the widget",
01920                       "Could not locate the %1 package required for the %2 widget.",
01921                       appletDescription.pluginName(), appletDescription.name()));
01922         } else {
01923             // create the package and see if we have something real
01924             //kDebug() << "trying for" << path;
01925             PackageStructure::Ptr structure =
01926                 Plasma::packageStructure(api, Plasma::AppletComponent);
01927             structure->setPath(path);
01928             package = new Package(path, structure);
01929 
01930             if (package->isValid()) {
01931                 // now we try and set up the script engine.
01932                 // it will be parented to this applet and so will get
01933                 // deleted when the applet does
01934 
01935                 script = Plasma::loadScriptEngine(api, q);
01936                 if (!script) {
01937                     delete package;
01938                     package = 0;
01939                     q->setFailedToLaunch(true,
01940                                          i18nc("API or programming language the widget was written in, name of the widget",
01941                                                "Could not create a %1 ScriptEngine for the %2 widget.",
01942                                                api, appletDescription.name()));
01943                 }
01944             } else {
01945                 q->setFailedToLaunch(true, i18nc("Package file, name of the widget",
01946                                                  "Could not open the %1 package required for the %2 widget.",
01947                                                  appletDescription.pluginName(), appletDescription.name()));
01948                 delete package;
01949                 package = 0;
01950             }
01951 
01952             if (package) {
01953                 setupScriptSupport();
01954             }
01955         }
01956     }
01957 
01958     q->setBackgroundHints(Applet::DefaultBackground);
01959 
01960     QObject::connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), q, SLOT(themeChanged()));
01961 }
01962 
01963 // put all setup routines for script here. at this point we can assume that
01964 // package exists and that we have a script engine
01965 void AppletPrivate::setupScriptSupport()
01966 {
01967     Q_ASSERT(package);
01968     kDebug() << "setting up script support, package is in" << package->path()
01969              << "which is a" << package->structure()->type() << "package"
01970              << ", main script is" << package->filePath("mainscript");
01971 
01972     QString xmlPath = package->filePath("mainconfigxml");
01973     if (!xmlPath.isEmpty()) {
01974         QFile file(xmlPath);
01975         KConfigGroup config = q->config();
01976         configLoader = new ConfigLoader(&config, &file);
01977         QObject::connect(configLoader, SIGNAL(configChanged()), q, SLOT(configChanged()));
01978     }
01979 
01980     if (!package->filePath("mainconfigui").isEmpty()) {
01981         q->setHasConfigurationInterface(true);
01982     }
01983 
01984     //set a default size before any saved settings are read
01985     QSize size = appletDescription.property("X-Plasma-DefaultSize").toSize();
01986     if (size.isEmpty()) {
01987         size = QSize(200,200);
01988     }
01989     //kDebug() << "size" << size;
01990     q->resize(size);
01991 
01992 }
01993 
01994 QString AppletPrivate::globalName() const
01995 {
01996     if (!appletDescription.isValid()) {
01997         return QString();
01998     }
01999 
02000     return appletDescription.service()->library();
02001 }
02002 
02003 QString AppletPrivate::instanceName()
02004 {
02005     if (!appletDescription.isValid()) {
02006         return QString();
02007     }
02008 
02009     return appletDescription.service()->library() + QString::number(appletId);
02010 }
02011 
02012 void AppletPrivate::scheduleConstraintsUpdate(Plasma::Constraints c)
02013 {
02014     // Don't start up a timer if we're just starting up
02015     // flushPendingConstraints will be called by Corona
02016     if (started && !constraintsTimerId && !(c & Plasma::StartupCompletedConstraint)) {
02017         constraintsTimerId = q->startTimer(0);
02018     }
02019 
02020     if (c & Plasma::StartupCompletedConstraint) {
02021         started = true;
02022     }
02023 
02024     pendingConstraints |= c;
02025 }
02026 
02027 void AppletPrivate::scheduleModificationNotification()
02028 {
02029     // modificationsTimerId is -1 until we get our notice of being started
02030     if (modificationsTimerId != -1) {
02031         // schedule a save
02032         if (modificationsTimerId) {
02033             q->killTimer(modificationsTimerId);
02034         }
02035 
02036         modificationsTimerId = q->startTimer(1000);
02037     }
02038 }
02039 
02040 KConfigGroup *AppletPrivate::mainConfigGroup()
02041 {
02042     if (mainConfig) {
02043         return mainConfig;
02044     }
02045 
02046     if (isContainment) {
02047         Corona *corona = qobject_cast<Corona*>(q->scene());
02048         KConfigGroup containmentConfig;
02049         //kDebug() << "got a corona, baby?" << (QObject*)corona;
02050 
02051         if (corona) {
02052             containmentConfig = KConfigGroup(corona->config(), "Containments");
02053         } else {
02054             containmentConfig =  KConfigGroup(KGlobal::config(), "Containments");
02055         }
02056 
02057         mainConfig = new KConfigGroup(&containmentConfig, QString::number(appletId));
02058     } else {
02059         KConfigGroup appletConfig;
02060         if (q->containment()) {
02061             appletConfig = q->containment()->config();
02062             appletConfig = KConfigGroup(&appletConfig, "Applets");
02063         } else {
02064             kWarning() << "requesting config for" << q->name() << "without a containment!";
02065             appletConfig = KConfigGroup(KGlobal::config(), "Applets");
02066         }
02067 
02068         mainConfig = new KConfigGroup(&appletConfig, QString::number(appletId));
02069     }
02070 
02071     return mainConfig;
02072 }
02073 
02074 QString AppletPrivate::visibleFailureText(const QString &reason)
02075 {
02076     QString text;
02077 
02078     if (reason.isEmpty()) {
02079         text = i18n("This object could not be created.");
02080     } else {
02081         text = i18n("This object could not be created for the following reason:<p><b>%1</b></p>", reason);
02082     }
02083 
02084     return text;
02085 }
02086 
02087 void AppletPrivate::checkImmutability()
02088 {
02089     const bool systemImmutable = q->globalConfig().isImmutable() || q->config().isImmutable() ||
02090                                 ((!isContainment && q->containment()) &&
02091                                     q->containment()->immutability() == SystemImmutable) ||
02092                                 (qobject_cast<Corona*>(q->scene()) && static_cast<Corona*>(q->scene())->immutability() == SystemImmutable);
02093 
02094     if (systemImmutable) {
02095         q->updateConstraints(ImmutableConstraint);
02096     }
02097 }
02098 
02099 void AppletPrivate::themeChanged()
02100 {
02101     if (background) {
02102         //do again the translucent background fallback
02103         q->setBackgroundHints(backgroundHints);
02104 
02105         qreal left;
02106         qreal right;
02107         qreal top;
02108         qreal bottom;
02109         background->getMargins(left, top, right, bottom);
02110         q->setContentsMargins(left, right, top, bottom);
02111     }
02112     q->update();
02113 }
02114 
02115 void AppletPrivate::resetConfigurationObject()
02116 {
02117     // make sure mainConfigGroup exists in all cases
02118     mainConfigGroup();
02119 
02120     mainConfig->deleteGroup();
02121     delete mainConfig;
02122     mainConfig = 0;
02123 }
02124 
02125 uint AppletPrivate::s_maxAppletId = 0;
02126 uint AppletPrivate::s_maxZValue = 0;
02127 uint AppletPrivate::s_minZValue = 0;
02128 PackageStructure::Ptr AppletPrivate::packageStructure(0);
02129 
02130 AppletOverlayWidget::AppletOverlayWidget(QGraphicsWidget *parent)
02131     : QGraphicsWidget(parent)
02132 {
02133     resize(parent->size());
02134 }
02135 
02136 void AppletOverlayWidget::paint(QPainter *painter,
02137                                 const QStyleOptionGraphicsItem *option,
02138                                 QWidget *widget)
02139 {
02140     Q_UNUSED(option)
02141     Q_UNUSED(widget)
02142     painter->setRenderHint(QPainter::Antialiasing);
02143     QColor wash = Plasma::Theme::defaultTheme()->color(Theme::BackgroundColor);
02144     wash.setAlphaF(.6);
02145 
02146     Applet *applet = qobject_cast<Applet *>(parentWidget());
02147 
02148     if (applet->backgroundHints() & Applet::StandardBackground) {
02149         painter->fillRect(parentWidget()->contentsRect(), wash);
02150     } else {
02151         painter->fillPath(parentItem()->shape(), wash);
02152     }
02153 }
02154 
02155 } // Plasma namespace
02156 
02157 #include "applet.moc"

Plasma

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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