00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "applet.h"
00022
00023 #include <cmath>
00024 #include <limits>
00025
00026 #include <QApplication>
00027 #include <QEvent>
00028 #include <QFile>
00029 #include <QList>
00030 #include <QPainter>
00031 #include <QSize>
00032 #include <QStyleOptionGraphicsItem>
00033 #include <QTextDocument>
00034 #include <QTimer>
00035 #include <QUiLoader>
00036
00037 #include <KIcon>
00038 #include <KColorScheme>
00039 #include <KConfigDialog>
00040 #include <KDialog>
00041 #include <KPluginInfo>
00042 #include <KStandardDirs>
00043 #include <KService>
00044 #include <KServiceTypeTrader>
00045 #include <KIconLoader>
00046
00047 #include <Solid/PowerManagement>
00048
00049 #include "plasma/configxml.h"
00050 #include "plasma/containment.h"
00051 #include "plasma/corona.h"
00052 #include "plasma/dataenginemanager.h"
00053 #include "plasma/package.h"
00054 #include "plasma/packages_p.h"
00055 #include "plasma/plasma.h"
00056 #include "plasma/scriptengine.h"
00057 #include "plasma/shadowitem_p.h"
00058 #include "plasma/svg.h"
00059 #include "plasma/svgpanel.h"
00060 #include "plasma/theme.h"
00061 #include "plasma/view.h"
00062
00063 #include "plasma/layouts/boxlayout.h"
00064 #include "plasma/widgets/widget.h"
00065 #include "plasma/widgets/lineedit.h"
00066 #include "plasma/widgets/pushbutton.h"
00067
00068
00069 namespace Plasma
00070 {
00071
00072 class Applet::Private
00073 {
00074 public:
00075 Private(KService::Ptr service, int uniqueID)
00076 : appletId(uniqueID),
00077 appletDescription(service),
00078 package(0),
00079 background(0),
00080 failureText(0),
00081 scriptEngine(0),
00082 configXml(0),
00083 shadow(0),
00084 cachedBackground(0),
00085 mainConfig(0),
00086 pendingConstraints(NoConstraint),
00087 kioskImmutable(false),
00088 immutable(false),
00089 hasConfigurationInterface(false),
00090 failed(false),
00091 needsConfig(false),
00092 isContainment(false)
00093 {
00094 if (appletId == 0) {
00095 appletId = nextId();
00096 }
00097
00098 if (appletId > s_maxAppletId) {
00099 s_maxAppletId = appletId;
00100 }
00101 }
00102
00103 ~Private()
00104 {
00105 foreach ( const QString& engine, loadedEngines ) {
00106 DataEngineManager::self()->unloadDataEngine( engine );
00107 }
00108 delete background;
00109 delete package;
00110 delete configXml;
00111 delete shadow;
00112 delete cachedBackground;
00113 delete mainConfig;
00114 }
00115
00116 void init(Applet* applet)
00117 {
00118
00119
00120 applet->setAcceptsHoverEvents(true);
00121 applet->setZValue(100);
00122
00123 if (!appletDescription.isValid()) {
00124 applet->setFailedToLaunch(true);
00125 return;
00126 }
00127
00128 QString language = appletDescription.property("X-Plasma-Language").toString();
00129
00130
00131 if (!language.isEmpty()) {
00132
00133 QString path = KStandardDirs::locate("appdata",
00134 "plasmoids/" + appletDescription.pluginName() + '/');
00135
00136 if (path.isEmpty()) {
00137 applet->setFailedToLaunch(true, i18n("Could not locate the %1 package required for the %2 widget.",
00138 appletDescription.pluginName(), appletDescription.name()));
00139 } else {
00140
00141
00142 package = new Package(path, PlasmoidStructure());
00143 if (package->isValid()) {
00144
00145
00146
00147
00148 scriptEngine = ScriptEngine::load(language, applet);
00149 if (!scriptEngine) {
00150 delete package;
00151 package = 0;
00152 applet->setFailedToLaunch(true, i18n("Could not create a %1 ScriptEngine for the %2 widget.",
00153 language, appletDescription.name()));
00154 }
00155 } else {
00156 applet->setFailedToLaunch(true, i18n("Could not open the %1 package required for the %2 widget.",
00157 appletDescription.pluginName(), appletDescription.name()));
00158 delete package;
00159 package = 0;
00160 }
00161
00162 if (package) {
00163 setupScriptSupport(applet);
00164 }
00165 }
00166 }
00167 applet->setDrawStandardBackground(true);
00168 }
00169
00170
00171
00172 void setupScriptSupport(Applet* applet)
00173 {
00174 Q_ASSERT(package);
00175 QString xmlPath = package->filePath("mainconfigxml");
00176 if (!xmlPath.isEmpty()) {
00177 QFile file(xmlPath);
00178
00179 KConfigGroup config = applet->config();
00180 configXml = new ConfigXml(&config, &file);
00181 }
00182
00183 if (!package->filePath("mainconfigui").isEmpty()) {
00184 applet->setHasConfigurationInterface(true);
00185 }
00186 }
00187
00188 QSizeF contentSize(const Applet* q)
00189 {
00190 if (failureText) {
00191 return failureText->geometry().size();
00192 }
00193
00194 return q->contentSize();
00195 }
00196
00197 static uint nextId()
00198 {
00199 ++s_maxAppletId;
00200 return s_maxAppletId;
00201 }
00202
00203 QString instanceName()
00204 {
00205 if (!appletDescription.isValid()) {
00206 return QString();
00207 }
00208
00209 return appletDescription.service()->library() + QString::number(appletId);
00210 }
00211
00212 void getBorderSize(int& left , int& top, int &right, int& bottom)
00213 {
00214 if (background) {
00215 top = background->marginSize(Plasma::TopMargin);
00216 left = background->marginSize(Plasma::LeftMargin);
00217 right = background->marginSize(Plasma::RightMargin);
00218 bottom = background->marginSize(Plasma::BottomMargin);
00219 } else {
00220 top = left = right = bottom = 0;
00221 }
00222 }
00223
00224 void scheduleConstraintsUpdate(Plasma::Constraints c, Applet* applet)
00225 {
00226 if (pendingConstraints == NoConstraint) {
00227 QTimer::singleShot(0, applet, SLOT(flushUpdatedConstraints()));
00228 }
00229 pendingConstraints |= c;
00230 }
00231
00232 KConfigGroup* mainConfigGroup(const Applet* q)
00233 {
00234 if (mainConfig) {
00235 return mainConfig;
00236 }
00237
00238 if (isContainment) {
00239 const Containment *asContainment = qobject_cast<Containment*>(const_cast<Applet*>(q));
00240 Q_ASSERT(asContainment);
00241
00242 KConfigGroup containmentConfig;
00243
00244 if (asContainment->corona()) {
00245 containmentConfig = KConfigGroup(asContainment->corona()->config(), "Containments");
00246 } else {
00247 containmentConfig = KConfigGroup(KGlobal::config(), "Containments");
00248 }
00249
00250 mainConfig = new KConfigGroup(&containmentConfig, QString::number(appletId));
00251 } else {
00252 KConfigGroup appletConfig;
00253 if (q->containment()) {
00254 appletConfig = q->containment()->config();
00255 appletConfig = KConfigGroup(&appletConfig, "Applets");
00256 } else {
00257 kWarning() << "requesting config for" << q->name() << "without a containment!";
00258 appletConfig = KConfigGroup(KGlobal::config(), "Applets");
00259 }
00260
00261 mainConfig = new KConfigGroup(&appletConfig, QString::number(appletId));
00262 }
00263
00264 return mainConfig;
00265 }
00266
00267 void copyEntries(KConfigGroup *source, KConfigGroup *destination)
00268 {
00269 foreach (const QString &group, source->groupList()) {
00270 KConfigGroup subSource(source, group);
00271 KConfigGroup subDest(destination, group);
00272 copyEntries(&subSource, &subDest);
00273 }
00274
00275 QMap<QString, QString> entries = source->entryMap();
00276 QMapIterator<QString, QString> it(entries);
00277 while (it.hasNext()) {
00278 it.next();
00279 destination->writeEntry(it.key(), it.value());
00280 }
00281 }
00282
00283
00284
00285 uint appletId;
00286 KPluginInfo appletDescription;
00287 Package* package;
00288 QList<QObject*> watchedForFocus;
00289 QStringList loadedEngines;
00290 static uint s_maxAppletId;
00291 Plasma::SvgPanel *background;
00292 Plasma::LineEdit *failureText;
00293 ScriptEngine* scriptEngine;
00294 ConfigXml* configXml;
00295 ShadowItem* shadow;
00296 QPixmap* cachedBackground;
00297 KConfigGroup *mainConfig;
00298 Plasma::Constraints pendingConstraints;
00299 bool kioskImmutable : 1;
00300 bool immutable : 1;
00301 bool hasConfigurationInterface : 1;
00302 bool failed : 1;
00303 bool needsConfig : 1;
00304 bool isContainment : 1;
00305 };
00306
00307 uint Applet::Private::s_maxAppletId = 0;
00308
00309 Applet::Applet(QGraphicsItem *parent,
00310 const QString& serviceID,
00311 uint appletId)
00312 : Widget(parent),
00313 d(new Private(KService::serviceByStorageId(serviceID), appletId))
00314 {
00315
00316
00317 d->init(this);
00318 }
00319
00320 Applet::Applet(QObject* parentObject, const QVariantList& args)
00321 : Widget(0,parentObject),
00322 d(new Private(KService::serviceByStorageId(args.count() > 0 ? args[0].toString() : QString()),
00323 args.count() > 1 ? args[1].toInt() : 0))
00324 {
00325
00326
00327 d->init(this);
00328
00329
00330 }
00331
00332 Applet::~Applet()
00333 {
00334 needsFocus(false);
00335 delete d;
00336 }
00337
00338 void Applet::init()
00339 {
00340 }
00341
00342 uint Applet::id() const
00343 {
00344 return d->appletId;
00345 }
00346
00347 void Applet::save(KConfigGroup* group) const
00348 {
00349
00350
00351 group->writeEntry("locked", d->immutable);
00352 group->writeEntry("plugin", pluginName());
00353
00354
00355
00356 group->writeEntry("geometry", geometry());
00357
00358 if (transform() == QTransform()) {
00359 group->deleteEntry("transform");
00360 } else {
00361 QList<qreal> m;
00362 QTransform t = transform();
00363 m << t.m11() << t.m12() << t.m13() << t.m21() << t.m22() << t.m23() << t.m31() << t.m32() << t.m33();
00364 group->writeEntry("transform", m);
00365
00366 }
00367
00368 KConfigGroup appletConfigGroup(group, "Configuration");
00369
00370 saveState(&appletConfigGroup);
00371 }
00372
00373 void Applet::saveState(KConfigGroup* group) const
00374 {
00375 if (group->config()->name() != config().config()->name()) {
00376
00377
00378 KConfigGroup c = config();
00379 d->copyEntries(&c, group);
00380 }
00381
00382 Q_UNUSED(group)
00383 }
00384
00385 KConfigGroup Applet::config(const QString &group) const
00386 {
00387 KConfigGroup cg = config();
00388 return KConfigGroup(&cg, group);
00389 }
00390
00391 KConfigGroup Applet::config() const
00392 {
00393 if (d->isContainment) {
00394 return *(d->mainConfigGroup(this));
00395 }
00396
00397 return KConfigGroup(d->mainConfigGroup(this), "Configuration");
00398 }
00399
00400 KConfigGroup Applet::globalConfig() const
00401 {
00402 KConfigGroup globalAppletConfig;
00403 const Containment *c = isContainment() ? dynamic_cast<const Containment*>(this) : containment();
00404 QString group = isContainment() ? "ContainmentGlobals" : "AppletGlobals";
00405
00406 if (c && c->corona()) {
00407 KSharedConfig::Ptr coronaConfig = c->corona()->config();
00408 globalAppletConfig = KConfigGroup(coronaConfig, group);
00409 } else {
00410 globalAppletConfig = KConfigGroup(KGlobal::config(), group);
00411 }
00412
00413 return KConfigGroup(&globalAppletConfig, globalName());
00414 }
00415
00416 void Applet::destroy()
00417 {
00418
00419 if (d->configXml) {
00420 d->configXml->setDefaults();
00421 }
00422
00423 resetConfigurationObject();
00424 deleteLater();
00425 }
00426
00427 void Applet::resetConfigurationObject()
00428 {
00429 d->mainConfigGroup(this)->deleteGroup();
00430 delete d->mainConfig;
00431 d->mainConfig = 0;
00432 }
00433
00434 ConfigXml* Applet::configXml() const
00435 {
00436 return d->configXml;
00437 }
00438
00439 DataEngine* Applet::dataEngine(const QString& name) const
00440 {
00441 int index = d->loadedEngines.indexOf(name);
00442 if (index != -1) {
00443 return DataEngineManager::self()->dataEngine(name);
00444 }
00445
00446 DataEngine* engine = DataEngineManager::self()->loadDataEngine(name);
00447 if (engine->isValid()) {
00448 d->loadedEngines.append(name);
00449 }
00450
00451 return engine;
00452 }
00453
00454 const Package* Applet::package() const
00455 {
00456 return d->package;
00457 }
00458
00459 void Applet::updateConstraints(Plasma::Constraints constraints)
00460 {
00461 d->scheduleConstraintsUpdate(constraints, this);
00462 }
00463
00464 void Applet::constraintsUpdated(Plasma::Constraints constraints)
00465 {
00466 Q_UNUSED(constraints)
00467
00468 }
00469
00470 QString Applet::name() const
00471 {
00472 if (!d->appletDescription.isValid()) {
00473 return i18n("Unknown Applet");
00474 }
00475
00476 return d->appletDescription.name();
00477 }
00478
00479 QString Applet::icon() const
00480 {
00481 if (!d->appletDescription.isValid()) {
00482 return QString();
00483 }
00484
00485 return d->appletDescription.icon();
00486 }
00487
00488 QString Applet::pluginName() const
00489 {
00490 if (!d->appletDescription.isValid()) {
00491 return QString();
00492 }
00493
00494 return d->appletDescription.pluginName();
00495 }
00496
00497 bool Applet::shouldConserveResources() const
00498 {
00499 return Solid::PowerManagement::appShouldConserveResources();
00500 }
00501
00502 QString Applet::category() const
00503 {
00504 if (!d->appletDescription.isValid()) {
00505 return i18n("Miscellaneous");
00506 }
00507
00508 return d->appletDescription.category();
00509 }
00510
00511 QString Applet::category(const KPluginInfo& applet)
00512 {
00513 return applet.property("X-KDE-PluginInfo-Category").toString();
00514 }
00515
00516 QString Applet::category(const QString& appletName)
00517 {
00518 if (appletName.isEmpty()) {
00519 return QString();
00520 }
00521
00522 QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(appletName);
00523 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
00524
00525 if (offers.isEmpty()) {
00526 return QString();
00527 }
00528
00529 return offers.first()->property("X-KDE-PluginInfo-Category").toString();
00530 }
00531
00532 bool Applet::isImmutable() const
00533 {
00534 return d->immutable || d->kioskImmutable ||
00535 (containment() && containment()->isImmutable()) ||
00536 (dynamic_cast<Corona*>( scene() ) && static_cast<Corona*>(scene())->isImmutable());
00537 }
00538
00539 bool Applet::isKioskImmutable() const
00540 {
00541 return d->kioskImmutable;
00542 }
00543
00544 void Applet::setImmutable(bool immutable)
00545 {
00546 if (d->immutable == immutable ||
00547 (immutable && d->kioskImmutable)) {
00548 return;
00549 }
00550
00551 d->immutable = immutable;
00552
00553 updateConstraints(ImmutableConstraint);
00554 }
00555
00556 bool Applet::drawStandardBackground()
00557 {
00558 return d->background != 0;
00559 }
00560
00561 void Applet::setDrawStandardBackground(bool drawBackground)
00562 {
00563 if (drawBackground) {
00564 if (!d->background) {
00565 d->background = new Plasma::SvgPanel("widgets/background");
00566 updateGeometry();
00567 }
00568 } else if (d->background) {
00569 delete d->background;
00570 d->background = 0;
00571 updateGeometry();
00572 }
00573 }
00574
00575 bool Applet::failedToLaunch() const
00576 {
00577 return d->failed;
00578 }
00579
00580 QString visibleFailureText(const QString& reason)
00581 {
00582 QString text;
00583
00584 if (reason.isEmpty()) {
00585 text = i18n("This object could not be created.");
00586 } else {
00587 text = i18n("This object could not be created for the following reason:<p><b>%1</b></p>", reason);
00588 }
00589
00590 return text;
00591 }
00592
00593 void Applet::setFailedToLaunch(bool failed, const QString& reason)
00594 {
00595 if (d->failed == failed) {
00596 if (d->failureText) {
00597 d->failureText->setHtml(visibleFailureText(reason));
00598 setGeometry(QRectF(geometry().topLeft(), d->failureText->sizeHint()));
00599 }
00600 return;
00601 }
00602
00603 d->failed = failed;
00604 prepareGeometryChange();
00605
00606 d->failureText = 0;
00607 qDeleteAll(QGraphicsItem::children());
00608 setLayout(0);
00609
00610 if (failed) {
00611 setDrawStandardBackground(true);
00612 Layout* failureLayout = new BoxLayout(BoxLayout::TopToBottom, this);
00613 failureLayout->setMargin(0);
00614 d->failureText = new LineEdit(this);
00615 d->failureText->setTextInteractionFlags( Qt::TextSelectableByMouse );
00616 d->failureText->setStyled(false);
00617 d->failureText->document()->setTextWidth(200);
00618 d->failureText->setHtml(visibleFailureText(reason));
00619
00620 d->failureText->setDefaultTextColor(KStatefulBrush(KColorScheme::Window,
00621 KColorScheme::NormalText,
00622 Theme::self()->colors())
00623 .brush(QPalette::Normal).color());
00624 failureLayout->addItem(d->failureText);
00625 setGeometry(QRectF(geometry().topLeft(), d->failureText->sizeHint()));
00626 }
00627
00628 update();
00629 }
00630
00631 bool Applet::needsConfiguring() const
00632 {
00633 return d->needsConfig;
00634 }
00635
00636 void Applet::setNeedsConfiguring(bool needsConfig)
00637 {
00638 if (d->needsConfig == needsConfig) {
00639 return;
00640 }
00641
00642 d->needsConfig = needsConfig;
00643 prepareGeometryChange();
00644 qDeleteAll(QGraphicsItem::children());
00645 setLayout(0);
00646
00647 if (needsConfig) {
00648 setDrawStandardBackground(true);
00649 Layout* layout = new BoxLayout(BoxLayout::TopToBottom,this);
00650 PushButton* button = new PushButton(this);
00651 button->setText(i18n("Configure..."));
00652 connect(button, SIGNAL(clicked()), this, SLOT(performSetupConfig()));
00653 layout->addItem(button);
00654 }
00655 }
00656
00657 void Applet::performSetupConfig()
00658 {
00659 qDeleteAll(QGraphicsItem::children());
00660 setLayout(0);
00661 showConfigurationInterface();
00662 }
00663
00664 void Applet::checkImmutability()
00665 {
00666 d->kioskImmutable = globalConfig().isImmutable() || config().isImmutable() ||
00667 (containment() && containment()->isKioskImmutable()) ||
00668 (dynamic_cast<Corona*>(scene()) && static_cast<Corona*>(scene())->isKioskImmutable());
00669
00670 if (d->kioskImmutable) {
00671 updateConstraints(ImmutableConstraint);
00672 }
00673 }
00674
00675 void Applet::flushUpdatedConstraints()
00676 {
00677 if (d->pendingConstraints == NoConstraint) {
00678 return;
00679 }
00680
00681
00682 Plasma::Constraints c = d->pendingConstraints;
00683 d->pendingConstraints = NoConstraint;
00684
00685 Containment* containment = qobject_cast<Plasma::Containment*>(this);
00686 if (c & Plasma::FormFactorConstraint) {
00687 FormFactor f = formFactor();
00688 setShadowShown(f == Planar);
00689 setDrawStandardBackground(!containment && f != Vertical && f != Horizontal);
00690 }
00691
00692 if (isContainment() && containment) {
00693 containment->containmentConstraintsUpdated(c);
00694 }
00695
00696 constraintsUpdated(c);
00697
00698 if (layout()) {
00699 layout()->updateGeometry();
00700 }
00701 }
00702
00703 int Applet::type() const
00704 {
00705 return Type;
00706 }
00707
00708 QRectF Applet::boundingRect() const
00709 {
00710 QRectF rect = QRectF(QPointF(0,0), d->contentSize(this));
00711
00712 int left;
00713 int right;
00714 int top;
00715 int bottom;
00716
00717 d->getBorderSize(left,top,right,bottom);
00718
00719
00720
00721
00722 return rect.adjusted(-left,-top,right,bottom);
00723 }
00724
00725 QSizeF Applet::sizeHint() const
00726 {
00727 int left = 0;
00728 int right = 0;
00729 int top = 0;
00730 int bottom = 0;
00731
00732 d->getBorderSize(left, top, right, bottom);
00733 QSizeF borderSize = QSizeF(left + right, top + bottom);
00734
00735
00736
00737 return contentSizeHint() + QSizeF(left + right, top + bottom);
00738 }
00739
00740 QList<QAction*> Applet::contextActions()
00741 {
00742 kDebug() << "empty context actions";
00743 return QList<QAction*>();
00744 }
00745
00746 QColor Applet::color() const
00747 {
00748
00749
00750 QString c = category();
00751 int alpha = 200;
00752
00753 if (c == "Date and Time") {
00754 return QColor(191, 94, 0, alpha);
00755 } else if (c == "Environment & Weather") {
00756 return QColor(191, 0, 0, alpha);
00757 } else if (c == "Examples") {
00758 return QColor(204, 0, 154, alpha);
00759 } else if (c == "File System") {
00760 return QColor(90, 0, 179, alpha);
00761 } else if (c == "Graphics") {
00762 return QColor(0, 0, 255, alpha);
00763 } else if (c == "Language") {
00764 return QColor(0, 191, 0, alpha);
00765 } else if (c == "Mapping") {
00766 return QColor(191, 245, 0, alpha);
00767 } else if (c == "Online Services") {
00768 return QColor(255, 213, 0, alpha);
00769 } else if (c == "System Information") {
00770 return QColor(0, 196, 204, alpha);
00771 } else if (c == "Windows and Tasks") {
00772 return QColor(255, 126, 0, alpha);
00773 } else {
00774 return QColor(136, 136, 136, alpha);
00775 }
00776 }
00777
00778 void Applet::paintWidget(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
00779 {
00780 Q_UNUSED(widget)
00781 if (d->shadow && d->shadow->shadowedSize() != boundingRect().size()) {
00782
00783 d->shadow->generate();
00784 }
00785
00786 painter->save();
00787 if (transform().isRotating()) {
00788 painter->setRenderHint(QPainter::SmoothPixmapTransform);
00789 painter->setRenderHint(QPainter::Antialiasing);
00790 }
00791
00792 if (d->background &&
00793 formFactor() != Plasma::Vertical &&
00794 formFactor() != Plasma::Horizontal) {
00795
00796 d->background->paint(painter, option->rect);
00797 }
00798
00799 if (!d->failed && !d->needsConfig) {
00800 if (widget && isContainment()) {
00801
00802 View* v = qobject_cast<Plasma::View*>(widget->parent());
00803 if (v && !v->drawWallpaper()) {
00804 painter->restore();
00805 return;
00806 }
00807 }
00808
00809
00810 paintInterface(painter, option, QRect(QPoint(0,0), d->contentSize(this).toSize()));
00811 }
00812
00813 painter->restore();
00814 }
00815
00816 void Applet::paintInterface(QPainter *painter, const QStyleOptionGraphicsItem *option,
00817 const QRect & contentsRect)
00818 {
00819 Q_UNUSED(contentsRect)
00820
00821 if (d->scriptEngine) {
00822 d->scriptEngine->paintInterface(painter, option, contentsRect);
00823 } else {
00824
00825 }
00826 }
00827
00828 FormFactor Applet::formFactor() const
00829 {
00830 Containment* c = containment();
00831 return c ? c->formFactor() : Plasma::Planar;
00832 }
00833
00834 Containment* Applet::containment() const
00835 {
00836
00837
00838
00839
00840
00841
00842
00843
00844 QGraphicsItem *parent = parentItem();
00845 Containment *c = 0;
00846
00847 while (parent) {
00848 Containment *possibleC = dynamic_cast<Containment*>(parent);
00849 if (possibleC && possibleC->isContainment()) {
00850 c = possibleC;
00851 break;
00852 }
00853 parent = parent->parentItem();
00854 }
00855
00856 return c;
00857 }
00858
00859 Location Applet::location() const
00860 {
00861 Containment* c = containment();
00862
00863 if (!c) {
00864 return Plasma::Desktop;
00865 }
00866
00867 return c->location();
00868 }
00869
00870 QRectF Applet::contentRect() const
00871 {
00872 return QRectF(QPointF(0, 0), contentSize());
00873 }
00874
00875 QSizeF Applet::contentSize() const
00876 {
00877 int top, left, right, bottom;
00878 d->getBorderSize(left, top, right, bottom);
00879
00880
00881
00882
00883 return (geometry().size() - QSizeF(left + right, top + bottom)).expandedTo(QSizeF(0, 0));
00884 }
00885
00886 void Applet::setContentSize(const QSizeF &size)
00887 {
00888 int top, left, right, bottom;
00889 d->getBorderSize(left, top, right, bottom);
00890
00891 resize(size + QSizeF(left + right, top + bottom));
00892 }
00893
00894 void Applet::setContentSize(int width, int height)
00895 {
00896 setContentSize(QSizeF(width, height));
00897 }
00898
00899 QSizeF Applet::contentSizeHint() const
00900 {
00901 if (layout()) {
00902 return layout()->sizeHint();
00903 }
00904
00905 return contentSize();
00906 }
00907
00908 void Applet::setMinimumContentSize(const QSizeF &minSize)
00909 {
00910 int top, left, right, bottom;
00911 d->getBorderSize(left, top, right, bottom);
00912
00913 setMinimumSize(minSize + QSizeF(left + right, top + bottom));
00914 }
00915
00916 void Applet::setMinimumContentSize(int minWidth, int minHeight)
00917 {
00918 setMinimumContentSize(QSizeF(minWidth, minHeight));
00919 }
00920
00921 QSizeF Applet::minimumContentSize() const
00922 {
00923 int top, left, right, bottom;
00924 d->getBorderSize(left, top, right, bottom);
00925
00926 return minimumSize() - QSizeF(left + right, top + bottom);
00927 }
00928
00929 void Applet::setMaximumContentSize(const QSizeF &maxSize)
00930 {
00931 int top, left, right, bottom;
00932 d->getBorderSize(left, top, right, bottom);
00933
00934 setMaximumSize(maxSize + QSizeF(left + right, top + bottom));
00935 }
00936
00937 void Applet::setMaximumContentSize(int maxWidth, int maxHeight)
00938 {
00939 setMaximumContentSize(QSizeF(maxWidth, maxHeight));
00940 }
00941
00942 QSizeF Applet::maximumContentSize() const
00943 {
00944 int top, left, right, bottom;
00945 d->getBorderSize(left, top, right, bottom);
00946
00947 return maximumSize() - QSizeF(left + right, top + bottom);
00948 }
00949
00950 QString Applet::globalName() const
00951 {
00952 if (!d->appletDescription.isValid()) {
00953 return QString();
00954 }
00955
00956 return d->appletDescription.service()->library();
00957 }
00958
00959 QString Applet::instanceName() const
00960 {
00961 return d->instanceName();
00962 }
00963
00964 void Applet::watchForFocus(QObject *widget, bool watch)
00965 {
00966 if ( !widget ) {
00967 return;
00968 }
00969
00970 int index = d->watchedForFocus.indexOf(widget);
00971 if ( watch ) {
00972 if ( index == -1 ) {
00973 d->watchedForFocus.append( widget );
00974 widget->installEventFilter( this );
00975 }
00976 } else if ( index != -1 ) {
00977 d->watchedForFocus.removeAt( index );
00978 widget->removeEventFilter( this );
00979 }
00980 }
00981
00982 void Applet::needsFocus(bool focus)
00983 {
00984 if (focus == QGraphicsItem::hasFocus()) {
00985 return;
00986 }
00987
00988 emit requestFocus(focus);
00989 }
00990
00991 bool Applet::hasConfigurationInterface()
00992 {
00993 return d->hasConfigurationInterface;
00994 }
00995
00996 void Applet::setHasConfigurationInterface(bool hasInterface)
00997 {
00998 d->hasConfigurationInterface = hasInterface;
00999 }
01000
01001 bool Applet::eventFilter( QObject *o, QEvent * e )
01002 {
01003 if ( !d->watchedForFocus.contains( o ) )
01004 {
01005 if ( e->type() == QEvent::MouseButtonRelease ||
01006 e->type() == QEvent::FocusIn ) {
01007 needsFocus( true );
01008 } else if ( e->type() == QEvent::FocusOut ) {
01009 needsFocus( false );
01010 }
01011 }
01012
01013 return QObject::eventFilter(o, e);
01014 }
01015
01016 void Applet::showConfigurationInterface()
01017 {
01018 if (d->package && d->configXml) {
01019 QString uiFile = d->package->filePath("mainconfigui");
01020 if (uiFile.isEmpty()) {
01021 return;
01022 }
01023
01024 KConfigDialog *dialog = new KConfigDialog(0, "", d->configXml);
01025 dialog->setWindowTitle(i18n("%1 Settings", name()));
01026 dialog->setAttribute(Qt::WA_DeleteOnClose, true);
01027
01028 QUiLoader loader;
01029 QString filename = d->package->filePath("mainconfigui");
01030 QFile f(filename);
01031 if (!f.open(QIODevice::ReadOnly)) {
01032 delete dialog;
01033 return;
01034 }
01035
01036 QWidget *w = loader.load(&f);
01037 f.close();
01038
01039 dialog->addPage(w, i18n("Settings"), icon(), i18n("%1 Settings", name()));
01040 dialog->show();
01041 }
01042 }
01043
01044 KPluginInfo::List Applet::knownApplets(const QString &category,
01045 const QString &parentApp)
01046 {
01047 QString constraint;
01048
01049 if (parentApp.isEmpty()) {
01050 constraint.append("not exist [X-KDE-ParentApp]");
01051 } else {
01052 constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'");
01053 }
01054
01055 if (!category.isEmpty()) {
01056 if (!constraint.isEmpty()) {
01057 constraint.append(" and ");
01058 }
01059
01060 constraint.append("[X-KDE-PluginInfo-Category] == '").append(category).append("'");
01061 if (category == "Miscellaneous") {
01062 constraint.append(" or (not exist [X-KDE-PluginInfo-Category] or [X-KDE-PluginInfo-Category] == '')");
01063 }
01064 }
01065
01066 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
01067
01068 return KPluginInfo::fromServices(offers);
01069 }
01070
01071 KPluginInfo::List Applet::knownAppletsForMimetype(const QString &mimetype)
01072 {
01073 QString constraint = QString("'%1' in MimeTypes").arg(mimetype);
01074
01075 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
01076 return KPluginInfo::fromServices(offers);
01077 }
01078
01079 QStringList Applet::knownCategories(const QString &parentApp, bool visibleOnly)
01080 {
01081 QString constraint = "exist [X-KDE-PluginInfo-Category]";
01082
01083 if (parentApp.isEmpty()) {
01084 constraint.append(" and not exist [X-KDE-ParentApp]");
01085 } else {
01086 constraint.append(" and [X-KDE-ParentApp] == '").append(parentApp).append("'");
01087 }
01088
01089 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
01090 QStringList categories;
01091 foreach (const KService::Ptr applet, offers) {
01092 QString appletCategory = applet->property("X-KDE-PluginInfo-Category").toString();
01093 if (visibleOnly && applet->noDisplay()) {
01094
01095 continue;
01096 }
01097
01098
01099 if (appletCategory.isEmpty()) {
01100 if (!categories.contains(i18n("Miscellaneous"))) {
01101 categories << i18n("Miscellaneous");
01102 }
01103 } else if (!categories.contains(appletCategory)) {
01104 categories << appletCategory;
01105 }
01106 }
01107
01108 categories.sort();
01109 return categories;
01110 }
01111
01112 Applet* Applet::loadApplet(const QString& appletName, uint appletId, const QVariantList& args)
01113 {
01114 if (appletName.isEmpty()) {
01115 return 0;
01116 }
01117
01118 QString constraint = QString("[X-KDE-PluginInfo-Name] == '%1'").arg(appletName);
01119 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Applet", constraint);
01120
01121 if (offers.isEmpty()) {
01122
01123
01124 kDebug() << "Applet::loadApplet: offers is empty for \"" << appletName << "\"";
01125 return 0;
01126 }
01127
01128
01129
01130 KService::Ptr offer = offers.first();
01131
01132 if (appletId == 0) {
01133 appletId = Private::nextId();
01134 }
01135
01136 if (!offer->property("X-Plasma-Language").toString().isEmpty()) {
01137 kDebug() << "we have a script in the language of" << offer->property("X-Plasma-Language").toString();
01138 Applet *applet = new Applet(0, offer->storageId(), appletId);
01139 return applet;
01140 }
01141
01142 QVariantList allArgs;
01143 allArgs << offer->storageId() << appletId << args;
01144 QString error;
01145 Applet* applet = offer->createInstance<Plasma::Applet>(0, allArgs, &error);
01146
01147 if (!applet) {
01148 kDebug() << "Couldn't load applet \"" << appletName << "\"! reason given: " << error;
01149 }
01150
01151 return applet;
01152 }
01153
01154 Applet* Applet::loadApplet(const KPluginInfo& info, uint appletId, const QVariantList& args)
01155 {
01156 if (!info.isValid()) {
01157 return 0;
01158 }
01159
01160 return loadApplet(info.pluginName(), appletId, args);
01161 }
01162
01163 void Applet::setShadowShown(bool shown)
01164 {
01165
01166
01167
01168
01169
01170
01171 #ifdef DYNAMIC_SHADOWS
01172 if (shown) {
01173 if (d->shadow) {
01174 d->shadow->setVisible(true);
01175 } else {
01176 d->shadow = new ShadowItem(this);
01177 if (scene()) {
01178 scene()->addItem(d->shadow);
01179 d->shadow->show();
01180 }
01181 }
01182 } else {
01183 delete d->shadow;
01184 d->shadow = 0;
01185 }
01186 #else
01187 Q_UNUSED(shown);
01188 #endif
01189 }
01190
01191 bool Applet::isShadowShown() const
01192 {
01193 return d->shadow && d->shadow->isVisible();
01194 }
01195
01196
01197
01198 QVariant Applet::itemChange(GraphicsItemChange change, const QVariant &value)
01199 {
01200 switch (change) {
01201 case ItemPositionChange:
01202 if (d->shadow) {
01203 d->shadow->adjustPosition();
01204 }
01205 break;
01206 case ItemSceneChange: {
01207 QGraphicsScene *newScene = qvariant_cast<QGraphicsScene*>(value);
01208 if (newScene) {
01209
01210
01211
01212
01213 QTimer::singleShot(0, this, SLOT(checkImmutability()));
01214 }
01215
01216 if (d->shadow) {
01217 if (d->shadow->scene()) {
01218 d->shadow->scene()->removeItem(d->shadow);
01219 }
01220
01221 if (newScene) {
01222 newScene->addItem(d->shadow);
01223 d->shadow->generate();
01224 d->shadow->adjustPosition();
01225 d->shadow->show();
01226 }
01227 }
01228 }
01229 break;
01230 case ItemVisibleChange:
01231 if (d->shadow) {
01232 d->shadow->setVisible(isVisible());
01233 }
01234 break;
01235 default:
01236 break;
01237 };
01238
01239 return Widget::itemChange(change, value);
01240 }
01241
01242 void Applet::setGeometry(const QRectF& geometry)
01243 {
01244 Plasma::Constraints updatedConstraints(0);
01245
01246 if (geometry.size().width() > 0 && geometry.size().height() > 0 && size() != geometry.size()) {
01247 prepareGeometryChange();
01248 qreal width = qBound(minimumSize().width(), geometry.size().width(), maximumSize().width());
01249 qreal height = qBound(minimumSize().height(), geometry.size().height(), maximumSize().height());
01250
01251 setSize(QSizeF(width, height));
01252
01253 if (layout()) {
01254 layout()->setGeometry(QRectF(QPoint(0, 0), contentSize()));
01255 }
01256
01257 if (managingLayout()) {
01258 managingLayout()->invalidate();
01259 }
01260
01261 if (d->background) {
01262 d->background->resize(size());
01263 }
01264 updatedConstraints |= Plasma::SizeConstraint;
01265 }
01266
01267 if (geometry.topLeft() != pos()) {
01268 setPos(geometry.topLeft());
01269 updatedConstraints |= Plasma::LocationConstraint;
01270 }
01271
01272 if (updatedConstraints) {
01273 updateConstraints(updatedConstraints);
01274 emit geometryChanged();
01275 update();
01276 }
01277 }
01278
01279 void Applet::setIsContainment(bool isContainment)
01280 {
01281 d->isContainment = isContainment;
01282 }
01283
01284 bool Applet::isContainment() const
01285 {
01286 return d->isContainment;
01287 }
01288
01289 }
01290
01291 #include "applet.moc"