00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "containment.h"
00022 #include "private/containment_p.h"
00023
00024 #include <QAction>
00025 #include <QFile>
00026 #include <QGraphicsSceneContextMenuEvent>
00027 #include <QGraphicsView>
00028 #include <QMimeData>
00029 #include <QPainter>
00030 #include <QStyleOptionGraphicsItem>
00031 #include <QGraphicsLayout>
00032 #include <QGraphicsLinearLayout>
00033
00034 #include <kaction.h>
00035 #include <kapplication.h>
00036 #include <kauthorized.h>
00037 #include <kicon.h>
00038 #include <kmenu.h>
00039 #include <kmessagebox.h>
00040 #include <kmimetype.h>
00041 #include <krun.h>
00042 #include <kservicetypetrader.h>
00043 #include <kstandarddirs.h>
00044 #include <ktemporaryfile.h>
00045 #include <kwindowsystem.h>
00046
00047 #include "animator.h"
00048 #include "context.h"
00049 #include "corona.h"
00050 #include "svg.h"
00051 #include "wallpaper.h"
00052
00053 #include "private/applet_p.h"
00054 #include "private/applethandle_p.h"
00055 #include "private/desktoptoolbox_p.h"
00056 #include "private/paneltoolbox_p.h"
00057
00058 namespace Plasma
00059 {
00060
00061 bool ContainmentPrivate::s_positioning = false;
00062 static const char defaultWallpaper[] = "image";
00063 static const char defaultWallpaperMode[] = "SingleImage";
00064
00065 Containment::StyleOption::StyleOption()
00066 : QStyleOptionGraphicsItem(),
00067 view(0)
00068 {
00069 version = Version;
00070 type = Type;
00071 }
00072
00073 Containment::StyleOption::StyleOption(const Containment::StyleOption & other)
00074 : QStyleOptionGraphicsItem(other),
00075 view(other.view)
00076 {
00077 version = Version;
00078 type = Type;
00079 }
00080
00081 Containment::StyleOption::StyleOption(const QStyleOptionGraphicsItem &other)
00082 : QStyleOptionGraphicsItem(other),
00083 view(0)
00084 {
00085 version = Version;
00086 type = Type;
00087 }
00088
00089 Containment::Containment(QGraphicsItem *parent,
00090 const QString &serviceId,
00091 uint containmentId)
00092 : Applet(parent, serviceId, containmentId),
00093 d(new ContainmentPrivate(this))
00094 {
00095
00096
00097 setPos(0, 0);
00098 setBackgroundHints(NoBackground);
00099 setContainmentType(CustomContainment);
00100 }
00101
00102 Containment::Containment(QObject *parent, const QVariantList &args)
00103 : Applet(parent, args),
00104 d(new ContainmentPrivate(this))
00105 {
00106
00107
00108 setPos(0, 0);
00109 setBackgroundHints(NoBackground);
00110 }
00111
00112 Containment::~Containment()
00113 {
00114 if (Applet::d->transient) {
00115 Applet::d->resetConfigurationObject();
00116 Applet::d->transient = false;
00117 }
00118
00119 delete d;
00120 }
00121
00122 void Containment::init()
00123 {
00124 if (!isContainment()) {
00125 return;
00126 }
00127
00128 setCacheMode(NoCache);
00129 setFlag(QGraphicsItem::ItemIsMovable, false);
00130 setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
00131 setAcceptDrops(true);
00132 setAcceptsHoverEvents(true);
00133
00134
00135 connect(Animator::self(), SIGNAL(animationFinished(QGraphicsItem*,Plasma::Animator::Animation)),
00136 this, SLOT(containmentAppletAnimationComplete(QGraphicsItem*,Plasma::Animator::Animation)));
00137
00138 if (d->type == NoContainmentType) {
00139 setContainmentType(DesktopContainment);
00140 }
00141
00142
00143 bool unlocked = immutability() == Mutable;
00144
00145 QAction *appletBrowserAction = new QAction(i18n("Add Widgets..."), this);
00146 appletBrowserAction->setIcon(KIcon("list-add"));
00147 appletBrowserAction->setVisible(unlocked);
00148 appletBrowserAction->setEnabled(unlocked);
00149 connect(appletBrowserAction, SIGNAL(triggered()), this, SLOT(triggerShowAddWidgets()));
00150 appletBrowserAction->setShortcutContext(Qt::WidgetShortcut);
00151
00152 d->actions().addAction("add widgets", appletBrowserAction);
00153
00154 QAction *configureActivityAction = new QAction(i18n("Appearance Settings"), this);
00155 configureActivityAction->setIcon(KIcon("configure"));
00156 bool canConfig = unlocked || KAuthorized::authorize("PlasmaAllowConfigureWhenLocked");
00157 configureActivityAction->setVisible(canConfig);
00158 configureActivityAction->setEnabled(canConfig);
00159 connect(configureActivityAction, SIGNAL(triggered()), this, SLOT(requestConfiguration()));
00160 d->actions().addAction("activity settings", configureActivityAction);
00161
00162 QAction *action = new QAction(i18n("Next Widget"), this);
00163
00164 connect(action, SIGNAL(triggered()), this, SLOT(focusNextApplet()));
00165 action->setShortcutContext(Qt::WidgetShortcut);
00166 action->setShortcut(QKeySequence("ctrl+n"));
00167 d->actions().addAction("next applet", action);
00168
00169 action = new QAction(i18n("Previous Widget"), this);
00170
00171 connect(action, SIGNAL(triggered()), this, SLOT(focusPreviousApplet()));
00172 action->setShortcutContext(Qt::WidgetShortcut);
00173 action->setShortcut(QKeySequence("ctrl+p"));
00174 d->actions().addAction("previous applet", action);
00175
00176 if (immutability() != SystemImmutable) {
00177
00178
00179 QAction *lockDesktopAction =
00180 new QAction(unlocked ? i18n("Lock Widgets") : i18n("Unlock Widgets"), this);
00181 lockDesktopAction->setIcon(KIcon(unlocked ? "object-locked" : "object-unlocked"));
00182 connect(lockDesktopAction, SIGNAL(triggered(bool)),
00183 this, SLOT(toggleDesktopImmutability()));
00184 lockDesktopAction->setShortcutContext(Qt::WidgetShortcut);
00185 lockDesktopAction->setShortcut(QKeySequence("ctrl+l"));
00186 d->actions().addAction("lock widgets", lockDesktopAction);
00187 }
00188
00189 if (d->type != PanelContainment &&
00190 d->type != CustomPanelContainment) {
00191 QAction *zoomAction = new QAction(i18n("Zoom In"), this);
00192 zoomAction->setIcon(KIcon("zoom-in"));
00193 connect(zoomAction, SIGNAL(triggered(bool)), this, SLOT(zoomIn()));
00194 zoomAction->setShortcutContext(Qt::WidgetShortcut);
00195
00196 QList<QKeySequence> keys;
00197 keys << QKeySequence(QKeySequence::ZoomIn);
00198 keys << QKeySequence("ctrl+=");
00199 zoomAction->setShortcuts(keys);
00200 d->actions().addAction("zoom in", zoomAction);
00201
00202 zoomAction = new QAction(i18n("Zoom Out"), this);
00203 zoomAction->setIcon(KIcon("zoom-out"));
00204 connect(zoomAction, SIGNAL(triggered(bool)), this, SLOT(zoomOut()));
00205 zoomAction->setShortcutContext(Qt::WidgetShortcut);
00206 zoomAction->setShortcut(QKeySequence(QKeySequence::ZoomOut));
00207 d->actions().addAction("zoom out", zoomAction);
00208
00209 QAction *activityAction = new QAction(i18n("Add Activity"), this);
00210 activityAction->setIcon(KIcon("list-add"));
00211 activityAction->setVisible(unlocked);
00212 activityAction->setEnabled(unlocked);
00213 connect(activityAction, SIGNAL(triggered(bool)), this, SLOT(addSiblingContainment()));
00214 activityAction->setShortcutContext(Qt::WidgetShortcut);
00215 activityAction->setShortcut(QKeySequence("ctrl+shift+a"));
00216 d->actions().addAction("add sibling containment", activityAction);
00217
00218 if (d->type == DesktopContainment && d->toolBox) {
00219 d->toolBox->addTool(this->action("add widgets"));
00220 d->toolBox->addTool(this->action("add sibling containment"));
00221 d->toolBox->addTool(this->action("zoom in"));
00222 d->toolBox->addTool(this->action("zoom out"));
00223
00224 if (immutability() != SystemImmutable) {
00225 d->toolBox->addTool(this->action("lock widgets"));
00226 }
00227 d->toolBox->addTool(this->action("activity settings"));
00228 if (hasConfigurationInterface()) {
00229
00230 QAction *configureContainment = this->action("configure");
00231 if (configureContainment) {
00232 d->toolBox->addTool(this->action("configure"));
00233 }
00234 }
00235 }
00236
00237
00238
00239 if (d->drawWallpaper) {
00240 setDrawWallpaper(true);
00241 }
00242 }
00243 }
00244
00245
00246 bool appletConfigLessThan(const KConfigGroup &c1, const KConfigGroup &c2)
00247 {
00248 QPointF p1 = c1.readEntry("geometry", QRectF()).topLeft();
00249 QPointF p2 = c2.readEntry("geometry", QRectF()).topLeft();
00250
00251 if (!qFuzzyCompare(p1.x(), p2.x())) {
00252 return p1.x() < p2.x();
00253 }
00254
00255 return qFuzzyCompare(p1.y(), p2.y()) || p1.y() < p2.y();
00256 }
00257
00258 void Containment::restore(KConfigGroup &group)
00259 {
00260
00261
00262
00263
00264
00265 if (!isContainment()) {
00266 Applet::restore(group);
00267 return;
00268 }
00269
00270 QRectF geo = group.readEntry("geometry", geometry());
00271
00272
00273
00274 if (geo.size() != geo.size().boundedTo(maximumSize())) {
00275 setMaximumSize(maximumSize().expandedTo(geo.size()));
00276 }
00277 if (geo.size() != geo.size().expandedTo(minimumSize())) {
00278 setMinimumSize(minimumSize().boundedTo(geo.size()));
00279 }
00280 setGeometry(geo);
00281
00282 setLocation((Plasma::Location)group.readEntry("location", (int)d->location));
00283 setFormFactor((Plasma::FormFactor)group.readEntry("formfactor", (int)d->formFactor));
00284 setScreen(group.readEntry("screen", d->screen), group.readEntry("desktop", d->desktop));
00285 setActivity(group.readEntry("activity", QString()));
00286
00287 flushPendingConstraintsEvents();
00288 restoreContents(group);
00289 setImmutability((ImmutabilityType)group.readEntry("immutability", (int)Mutable));
00290
00291 setWallpaper(group.readEntry("wallpaperplugin", defaultWallpaper),
00292 group.readEntry("wallpaperpluginmode", defaultWallpaperMode));
00293
00294
00295
00296
00297
00298
00299
00300
00301 }
00302
00303 void Containment::save(KConfigGroup &g) const
00304 {
00305 KConfigGroup group = g;
00306 if (!group.isValid()) {
00307 group = config();
00308 }
00309
00310
00311 Applet::save(group);
00312 group.writeEntry("screen", d->screen);
00313 group.writeEntry("desktop", d->desktop);
00314 group.writeEntry("formfactor", (int)d->formFactor);
00315 group.writeEntry("location", (int)d->location);
00316 group.writeEntry("activity", d->context()->currentActivity());
00317
00318 if (d->toolBox) {
00319 d->toolBox->save(group);
00320 }
00321
00322 if (d->wallpaper) {
00323 group.writeEntry("wallpaperplugin", d->wallpaper->pluginName());
00324 group.writeEntry("wallpaperpluginmode", d->wallpaper->renderingMode().name());
00325
00326 if (d->wallpaper->isInitialized()) {
00327 KConfigGroup wallpaperConfig(&group, "Wallpaper");
00328 wallpaperConfig = KConfigGroup(&wallpaperConfig, d->wallpaper->pluginName());
00329 d->wallpaper->save(wallpaperConfig);
00330 }
00331 }
00332
00333 saveContents(group);
00334 }
00335
00336 void Containment::saveContents(KConfigGroup &group) const
00337 {
00338 KConfigGroup applets(&group, "Applets");
00339 foreach (const Applet *applet, d->applets) {
00340 KConfigGroup appletConfig(&applets, QString::number(applet->id()));
00341 applet->save(appletConfig);
00342 }
00343 }
00344
00345 void Containment::restoreContents(KConfigGroup &group)
00346 {
00347 KConfigGroup applets(&group, "Applets");
00348
00349
00350
00351 QList<KConfigGroup> appletConfigs;
00352 foreach (const QString &appletGroup, applets.groupList()) {
00353
00354 KConfigGroup appletConfig(&applets, appletGroup);
00355 appletConfigs.append(appletConfig);
00356 }
00357 qStableSort(appletConfigs.begin(), appletConfigs.end(), appletConfigLessThan);
00358
00359 QMutableListIterator<KConfigGroup> it(appletConfigs);
00360 while (it.hasNext()) {
00361 KConfigGroup &appletConfig = it.next();
00362 int appId = appletConfig.name().toUInt();
00363 QString plugin = appletConfig.readEntry("plugin", QString());
00364
00365 if (plugin.isEmpty()) {
00366 continue;
00367 }
00368
00369 Applet *applet = d->addApplet(plugin, QVariantList(),
00370 appletConfig.readEntry("geometry", QRectF()),
00371 appId, true);
00372 applet->restore(appletConfig);
00373 }
00374 }
00375
00376 Containment::Type Containment::containmentType() const
00377 {
00378 return d->type;
00379 }
00380
00381 void Containment::setContainmentType(Containment::Type type)
00382 {
00383 if (d->type == type) {
00384 return;
00385 }
00386
00387 delete d->toolBox;
00388 d->toolBox = 0;
00389 d->type = type;
00390
00391 if (!isContainment()) {
00392 return;
00393 }
00394
00395 if ((type == DesktopContainment || type == PanelContainment)) {
00396 d->createToolBox();
00397 }
00398
00399 d->checkRemoveAction();
00400 }
00401
00402 Corona *Containment::corona() const
00403 {
00404 return dynamic_cast<Corona*>(scene());
00405 }
00406
00407 void Containment::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
00408 {
00409 event->ignore();
00410 if (d->wallpaper && d->wallpaper->isInitialized()) {
00411 QGraphicsItem *item = scene()->itemAt(event->scenePos());
00412 if (item == this) {
00413 d->wallpaper->mouseMoveEvent(event);
00414 }
00415 }
00416
00417 if (!event->isAccepted()) {
00418 event->accept();
00419 Applet::mouseMoveEvent(event);
00420 }
00421 }
00422
00423 void Containment::mousePressEvent(QGraphicsSceneMouseEvent *event)
00424 {
00425 event->ignore();
00426 if (d->wallpaper && d->wallpaper->isInitialized()) {
00427 QGraphicsItem *item = scene()->itemAt(event->scenePos());
00428 if (item == this) {
00429 d->wallpaper->mousePressEvent(event);
00430 }
00431 }
00432
00433 if (event->isAccepted()) {
00434 setFocus(Qt::MouseFocusReason);
00435 } else {
00436 event->accept();
00437 Applet::mousePressEvent(event);
00438 }
00439 }
00440
00441 void Containment::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
00442 {
00443 event->ignore();
00444 if (d->wallpaper && d->wallpaper->isInitialized()) {
00445 QGraphicsItem *item = scene()->itemAt(event->scenePos());
00446 if (item == this) {
00447 d->wallpaper->mouseReleaseEvent(event);
00448 }
00449 }
00450
00451 if (!event->isAccepted()) {
00452 event->accept();
00453 Applet::mouseReleaseEvent(event);
00454 }
00455 }
00456
00457 void Containment::showDropZone(const QPoint pos)
00458 {
00459 Q_UNUSED(pos)
00460
00461 }
00462
00463 void Containment::showContextMenu(const QPointF &containmentPos, const QPoint &screenPos)
00464 {
00465 d->showContextMenu(mapToScene(containmentPos), screenPos, false);
00466 }
00467
00468 void Containment::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
00469 {
00470
00471 if (!isContainment() || !scene() || !KAuthorized::authorizeKAction("desktop_contextmenu")) {
00472 Applet::contextMenuEvent(event);
00473 return;
00474 }
00475
00476 if (!d->showContextMenu(event->scenePos(), event->screenPos(), true)) {
00477 Applet::contextMenuEvent(event);
00478 } else {
00479 event->accept();
00480 }
00481 }
00482
00483 void ContainmentPrivate::containmentActions(KMenu &desktopMenu)
00484 {
00485 if (static_cast<Corona*>(q->scene())->immutability() != Mutable &&
00486 !KAuthorized::authorizeKAction("unlock_desktop")) {
00487
00488 return;
00489 }
00490
00491
00492 QList<QAction*> actions = q->contextualActions();
00493
00494
00495 QAction *separatorAction = 0;
00496
00497 foreach (QAction *action, actions) {
00498 if (action) {
00499 desktopMenu.addAction(action);
00500 if (action->isSeparator()) {
00501 separatorAction = action;
00502 }
00503 }
00504 }
00505
00506 desktopMenu.addSeparator();
00507
00508
00509
00510 if (q->containmentType() == Containment::DesktopContainment) {
00511 desktopMenu.insertAction(separatorAction, q->action("activity settings"));
00512 if (q->hasConfigurationInterface()) {
00513 desktopMenu.addAction(q->action("configure"));
00514 }
00515 }
00516 }
00517
00518 void ContainmentPrivate::appletActions(KMenu &desktopMenu, Applet *applet, bool includeApplet)
00519 {
00520 QList<QAction*> actions;
00521
00522 if (includeApplet) {
00523 actions = applet->contextualActions();
00524 if (!actions.isEmpty()) {
00525 foreach (QAction *action, actions) {
00526 if (action) {
00527 desktopMenu.addAction(action);
00528 }
00529 }
00530 }
00531 }
00532
00533 if (applet->hasConfigurationInterface()) {
00534 QAction *configureApplet = applet->d->actions.action("configure");
00535 if (configureApplet) {
00536 desktopMenu.addAction(configureApplet);
00537 }
00538 }
00539
00540 KMenu *containmentMenu = new KMenu(i18nc("%1 is the name of the containment", "%1 Options", q->name()), &desktopMenu);
00541 containmentActions(*containmentMenu);
00542 if (!containmentMenu->isEmpty()) {
00543 int enabled = 0;
00544
00545 foreach(QAction *action, containmentMenu->actions()) {
00546 if(action->isEnabled() && !action->isSeparator()) {
00547 enabled++;
00548 }
00549 }
00550
00551 if (enabled > 0) {
00552 desktopMenu.addSeparator();
00553 }
00554
00555
00556 if(enabled < 2) {
00557 foreach(QAction *action, containmentMenu->actions()) {
00558 desktopMenu.addAction(action);
00559 }
00560 } else {
00561 desktopMenu.addMenu(containmentMenu);
00562 }
00563 }
00564
00565 if (static_cast<Corona*>(q->scene())->immutability() == Mutable) {
00566 if (!desktopMenu.isEmpty()) {
00567 desktopMenu.addSeparator();
00568 }
00569
00570 QAction *closeApplet = applet->d->actions.action("remove");
00571 if (!closeApplet) {
00572 closeApplet = new QAction(i18nc("%1 is the name of the applet", "Remove this %1", applet->name()), &desktopMenu);
00573 closeApplet->setIcon(KIcon("edit-delete"));
00574 QObject::connect(closeApplet, SIGNAL(triggered(bool)), applet, SLOT(destroy()));
00575 }
00576 desktopMenu.addAction(closeApplet);
00577 }
00578 }
00579
00580 bool ContainmentPrivate::showContextMenu(const QPointF &point,
00581 const QPoint &screenPos, bool includeApplet)
00582 {
00583 Applet *applet = 0;
00584
00585 QGraphicsItem *item = q->scene()->itemAt(point);
00586 if (item == q) {
00587 item = 0;
00588 }
00589
00590 while (item) {
00591 applet = qgraphicsitem_cast<Applet*>(item);
00592 if (applet && !applet->isContainment()) {
00593 break;
00594 }
00595
00596
00597 applet = 0;
00598 item = item->parentItem();
00599 }
00600
00601 KMenu desktopMenu;
00602
00603 if (applet) {
00604 appletActions(desktopMenu, applet, includeApplet);
00605 } else {
00606 containmentActions(desktopMenu);
00607 }
00608
00609 if (!desktopMenu.isEmpty()) {
00610
00611 desktopMenu.exec(screenPos);
00612 return true;
00613 }
00614
00615 return false;
00616 }
00617
00618 void Containment::setFormFactor(FormFactor formFactor)
00619 {
00620 if (d->formFactor == formFactor) {
00621 return;
00622 }
00623
00624
00625 FormFactor was = d->formFactor;
00626 d->formFactor = formFactor;
00627
00628 if (isContainment() &&
00629 was != formFactor &&
00630 (d->type == PanelContainment ||
00631 d->type == CustomPanelContainment)) {
00632
00633 d->positionPanel(true);
00634 }
00635
00636 updateConstraints(Plasma::FormFactorConstraint);
00637
00638 KConfigGroup c = config();
00639 c.writeEntry("formfactor", (int)formFactor);
00640 emit configNeedsSaving();
00641 }
00642
00643 void Containment::setLocation(Location location)
00644 {
00645 if (d->location == location) {
00646 return;
00647 }
00648
00649 bool emitGeomChange = false;
00650
00651 if ((location == TopEdge || location == BottomEdge) &&
00652 (d->location == TopEdge || d->location == BottomEdge)) {
00653 emitGeomChange = true;
00654 }
00655
00656 if ((location == RightEdge || location == LeftEdge) &&
00657 (d->location == RightEdge || d->location == LeftEdge)) {
00658 emitGeomChange = true;
00659 }
00660
00661 d->location = location;
00662
00663 foreach (Applet *applet, d->applets) {
00664 applet->updateConstraints(Plasma::LocationConstraint);
00665 }
00666
00667 if (emitGeomChange) {
00668
00669
00670 emit geometryChanged();
00671 }
00672
00673 updateConstraints(Plasma::LocationConstraint);
00674
00675 KConfigGroup c = config();
00676 c.writeEntry("location", (int)location);
00677 emit configNeedsSaving();
00678 }
00679
00680 void Containment::addSiblingContainment()
00681 {
00682 emit addSiblingContainment(this);
00683 }
00684
00685 void Containment::clearApplets()
00686 {
00687 foreach (Applet *applet, d->applets) {
00688 applet->d->cleanUpAndDelete();
00689 }
00690
00691 d->applets.clear();
00692 }
00693
00694 Applet *Containment::addApplet(const QString &name, const QVariantList &args,
00695 const QRectF &appletGeometry)
00696 {
00697 return d->addApplet(name, args, appletGeometry);
00698 }
00699
00700 void Containment::addApplet(Applet *applet, const QPointF &pos, bool delayInit)
00701 {
00702 if (!isContainment() || (!delayInit && immutability() != Mutable)) {
00703 return;
00704 }
00705
00706 if (!applet) {
00707 kDebug() << "adding null applet!?!";
00708 return;
00709 }
00710
00711 if (d->applets.contains(applet)) {
00712 kDebug() << "already have this applet!";
00713 }
00714
00715 Containment *currentContainment = applet->containment();
00716
00717 if (containmentType() == PanelContainment) {
00718
00719 setBackgroundHints(NoBackground);
00720 }
00721
00722 if (currentContainment && currentContainment != this) {
00723 emit currentContainment->appletRemoved(applet);
00724 disconnect(applet, 0, currentContainment, 0);
00725 applet->removeSceneEventFilter(currentContainment);
00726 KConfigGroup oldConfig = applet->config();
00727 currentContainment->d->applets.removeAll(applet);
00728 if (currentContainment->d->handles.contains(applet)) {
00729 currentContainment->d->handles.remove(applet);
00730 }
00731 applet->setParentItem(this);
00732
00733
00734 KConfigGroup c = config().group("Applets").group(QString::number(applet->id()));
00735 oldConfig.reparent(&c);
00736 applet->d->resetConfigurationObject();
00737 } else {
00738 applet->setParentItem(this);
00739 }
00740
00741 d->applets << applet;
00742
00743 connect(applet, SIGNAL(configNeedsSaving()), this, SIGNAL(configNeedsSaving()));
00744 connect(applet, SIGNAL(releaseVisualFocus()), this, SIGNAL(releaseVisualFocus()));
00745 connect(applet, SIGNAL(destroyed(QObject*)), this, SLOT(appletDestroyed(QObject*)));
00746
00747 if (pos != QPointF(-1, -1)) {
00748 applet->setPos(pos);
00749 }
00750
00751 if (delayInit || currentContainment) {
00752 if (containmentType() == DesktopContainment) {
00753 applet->installSceneEventFilter(this);
00754
00755 }
00756 } else {
00757 applet->init();
00758 Animator::self()->animateItem(applet, Animator::AppearAnimation);
00759 }
00760
00761 applet->updateConstraints(Plasma::AllConstraints);
00762
00763 if (!delayInit) {
00764 applet->flushPendingConstraintsEvents();
00765 }
00766
00767 emit appletAdded(applet, pos);
00768
00769 if (!currentContainment) {
00770 applet->updateConstraints(Plasma::StartupCompletedConstraint);
00771 if (!delayInit) {
00772 applet->flushPendingConstraintsEvents();
00773 }
00774 }
00775
00776 if (!delayInit) {
00777 applet->d->scheduleModificationNotification();
00778 }
00779 }
00780
00781 Applet::List Containment::applets() const
00782 {
00783 return d->applets;
00784 }
00785
00786 void Containment::setScreen(int screen, int desktop)
00787 {
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798 Containment *swapScreensWith(0);
00799 if (d->type == DesktopContainment || d->type >= CustomContainment) {
00800
00801 if (d->screen < 0 && screen > -1) {
00802 connect(KWindowSystem::self(), SIGNAL(workAreaChanged()),
00803 this, SLOT(positionToolBox()));
00804 } else if (screen < 0) {
00805 disconnect(KWindowSystem::self(), SIGNAL(workAreaChanged()),
00806 this, SLOT(positionToolBox()));
00807 }
00808
00809 if (screen > -1 && corona()) {
00810
00811 Containment *currently = corona()->containmentForScreen(screen, desktop);
00812 if (currently && currently != this) {
00813 kDebug() << "currently is on screen" << currently->screen()
00814 << "and is" << currently->name()
00815 << (QObject*)currently << (QObject*)this;
00816 currently->setScreen(-1);
00817 swapScreensWith = currently;
00818 }
00819 }
00820 }
00821
00822 kDebug() << "setting screen to" << screen << "and we are a" << containmentType();
00823 Q_ASSERT(corona());
00824 int numScreens = corona()->numScreens();
00825 if (screen < -1) {
00826 screen = -1;
00827 }
00828
00829
00830 kDebug() << "setting screen to " << screen << "and type is" << containmentType();
00831 if (screen < numScreens && screen > -1) {
00832 if (containmentType() == DesktopContainment ||
00833 containmentType() >= CustomContainment) {
00834 resize(corona()->screenGeometry(screen).size());
00835 }
00836 }
00837
00838
00839 if (desktop < -1 || desktop > KWindowSystem::numberOfDesktops() - 1) {
00840 desktop = -1;
00841 }
00842
00843 d->desktop = desktop;
00844
00845 int oldScreen = d->screen;
00846 d->screen = screen;
00847 updateConstraints(Plasma::ScreenConstraint);
00848 if (oldScreen != screen) {
00849 emit screenChanged(oldScreen, screen, this);
00850
00851 KConfigGroup c = config();
00852 c.writeEntry("screen", d->screen);
00853 emit configNeedsSaving();
00854 }
00855
00856 if (swapScreensWith) {
00857 swapScreensWith->setScreen(oldScreen);
00858 }
00859
00860 d->checkRemoveAction();
00861 }
00862
00863 int Containment::screen() const
00864 {
00865 return d->screen;
00866 }
00867
00868 int Containment::desktop() const
00869 {
00870 return d->desktop;
00871 }
00872
00873 KPluginInfo::List Containment::listContainments(const QString &category,
00874 const QString &parentApp)
00875 {
00876 QString constraint;
00877
00878 if (parentApp.isEmpty()) {
00879 constraint.append("not exist [X-KDE-ParentApp]");
00880 } else {
00881 constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'");
00882 }
00883
00884 if (!category.isEmpty()) {
00885 if (!constraint.isEmpty()) {
00886 constraint.append(" and ");
00887 }
00888
00889 constraint.append("[X-KDE-PluginInfo-Category] == '").append(category).append("'");
00890 if (category == "Miscellaneous") {
00891 constraint.append(" or (not exist [X-KDE-PluginInfo-Category] or [X-KDE-PluginInfo-Category] == '')");
00892 }
00893 }
00894
00895 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint);
00896
00897 return KPluginInfo::fromServices(offers);
00898 }
00899
00900 KPluginInfo::List Containment::listContainmentsForMimetype(const QString &mimetype)
00901 {
00902 QString constraint = QString("'%1' in [X-Plasma-DropMimeTypes]").arg(mimetype);
00903
00904 KService::List offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint);
00905 return KPluginInfo::fromServices(offers);
00906 }
00907
00908 void Containment::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
00909 {
00910
00911 event->setAccepted(immutability() == Mutable &&
00912 (event->mimeData()->hasFormat(static_cast<Corona*>(scene())->appletMimeType()) ||
00913 KUrl::List::canDecode(event->mimeData())));
00914
00915 if (!event->isAccepted()) {
00916
00917 QStringList formats = event->mimeData()->formats();
00918
00919 foreach (const QString &format, formats) {
00920 KPluginInfo::List appletList = Applet::listAppletInfoForMimetype(format);
00921 if (!appletList.isEmpty()) {
00922 event->setAccepted(true);
00923 break;
00924 }
00925 }
00926 }
00927 }
00928
00929 void Containment::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
00930 {
00931 QGraphicsItem *item = scene()->itemAt(event->scenePos());
00932 event->setAccepted(item == this || !item);
00933 }
00934
00935 void Containment::dropEvent(QGraphicsSceneDragDropEvent *event)
00936 {
00937
00938 if (!isContainment()) {
00939 Applet::dropEvent(event);
00940 return;
00941 }
00942
00943 QString mimetype(static_cast<Corona*>(scene())->appletMimeType());
00944
00945 if (event->mimeData()->hasFormat(mimetype) && scene()) {
00946 QString data = event->mimeData()->data(mimetype);
00947 QStringList appletNames = data.split('\n', QString::SkipEmptyParts);
00948
00949 foreach (const QString &appletName, appletNames) {
00950
00951 QRectF geom(mapFromScene(event->scenePos()), QSize(0, 0));
00952 addApplet(appletName, QVariantList(), geom);
00953 }
00954 event->acceptProposedAction();
00955 } else if (KUrl::List::canDecode(event->mimeData())) {
00956
00957
00958 KUrl::List urls = KUrl::List::fromMimeData(event->mimeData());
00959 foreach (const KUrl &url, urls) {
00960 KMimeType::Ptr mime = KMimeType::findByUrl(url);
00961 QString mimeName = mime->name();
00962 QRectF geom(event->pos(), QSize());
00963 QVariantList args;
00964 args << url.url();
00965
00966 KPluginInfo::List appletList = Applet::listAppletInfoForMimetype(mimeName);
00967
00968 if (!appletList.isEmpty()) {
00969
00971 QMenu choices;
00972 QHash<QAction *, QString> actionsToPlugins;
00973 foreach (const KPluginInfo &info, appletList) {
00974 QAction *action;
00975 if (!info.icon().isEmpty()) {
00976 action = choices.addAction(KIcon(info.icon()), info.name());
00977 } else {
00978 action = choices.addAction(info.name());
00979 }
00980
00981 actionsToPlugins.insert(action, info.pluginName());
00982 }
00983
00984 actionsToPlugins.insert(choices.addAction(i18n("Icon")), "icon");
00985 QAction *choice = choices.exec(event->screenPos());
00986 if (choice) {
00987 addApplet(actionsToPlugins[choice], args, geom);
00988 }
00989 } else if (url.protocol() != "data") {
00990
00991
00992 addApplet("icon", args, geom);
00993 }
00994 }
00995 event->acceptProposedAction();
00996 } else {
00997 QStringList formats = event->mimeData()->formats();
00998 QHash<QString, KPluginInfo> seenPlugins;
00999 QHash<QString, QString> pluginFormats;
01000
01001 foreach (const QString &format, formats) {
01002 KPluginInfo::List plugins = Applet::listAppletInfoForMimetype(format);
01003
01004 foreach (const KPluginInfo &plugin, plugins) {
01005 if (seenPlugins.contains(plugin.pluginName())) {
01006 continue;
01007 }
01008
01009 seenPlugins.insert(plugin.pluginName(), plugin);
01010 pluginFormats.insert(plugin.pluginName(), format);
01011 }
01012 }
01013
01014 QString selectedPlugin;
01015
01016 if (seenPlugins.isEmpty()) {
01017
01018 }
01019
01020 if (seenPlugins.count() == 1) {
01021 selectedPlugin = seenPlugins.constBegin().key();
01022 } else {
01023 QMenu choices;
01024 QHash<QAction *, QString> actionsToPlugins;
01025 foreach (const KPluginInfo &info, seenPlugins) {
01026 QAction *action;
01027 if (!info.icon().isEmpty()) {
01028 action = choices.addAction(KIcon(info.icon()), info.name());
01029 } else {
01030 action = choices.addAction(info.name());
01031 }
01032
01033 actionsToPlugins.insert(action, info.pluginName());
01034 }
01035
01036 QAction *choice = choices.exec(event->screenPos());
01037 if (choice) {
01038 selectedPlugin = actionsToPlugins[choice];
01039 }
01040 }
01041
01042 if (!selectedPlugin.isEmpty()) {
01043 KTemporaryFile tempFile;
01044 if (tempFile.open()) {
01045
01046 tempFile.setAutoRemove(false);
01047
01048 {
01049 QDataStream stream(&tempFile);
01050 QByteArray data = event->mimeData()->data(pluginFormats[selectedPlugin]);
01051 stream.writeRawData(data, data.size());
01052 }
01053
01054 QRectF geom(event->pos(), QSize());
01055 QVariantList args;
01056 args << tempFile.fileName();
01057 kDebug() << args;
01058 tempFile.close();
01059
01060 addApplet(selectedPlugin, args, geom);
01061 }
01062 }
01063 }
01064 }
01065
01066 const QGraphicsItem *Containment::toolBoxItem() const
01067 {
01068 return d->toolBox;
01069 }
01070
01071 void Containment::resizeEvent(QGraphicsSceneResizeEvent *event)
01072 {
01073 Applet::resizeEvent(event);
01074 if (d->wallpaper) {
01075 d->wallpaper->setBoundingRect(boundingRect());
01076 }
01077 }
01078
01079 void Containment::keyPressEvent(QKeyEvent *event)
01080 {
01081
01082
01083 if (event->key() == Qt::Key_Tab) {
01084 if (!d->applets.isEmpty()) {
01085 kDebug() << "let's give focus to...." << (QObject*)d->applets.first();
01086 d->applets.first()->setFocus(Qt::TabFocusReason);
01087 }
01088 }
01089 }
01090
01091 void Containment::wheelEvent(QGraphicsSceneWheelEvent *event)
01092 {
01093 if (d->wallpaper && d->wallpaper->isInitialized()) {
01094 QGraphicsItem *item = scene()->itemAt(event->scenePos());
01095 if (item == this) {
01096 event->ignore();
01097 d->wallpaper->wheelEvent(event);
01098
01099 if (event->isAccepted()) {
01100 return;
01101 }
01102
01103 event->accept();
01104 }
01105 }
01106
01107 if (containmentType() == DesktopContainment) {
01108 QGraphicsItem *item = scene()->itemAt(event->scenePos());
01109 if (item == this) {
01110 int numDesktops = KWindowSystem::numberOfDesktops();
01111 int currentDesktop = KWindowSystem::currentDesktop();
01112
01113 if (event->delta() < 0) {
01114 KWindowSystem::setCurrentDesktop(currentDesktop % numDesktops + 1);
01115 } else {
01116 KWindowSystem::setCurrentDesktop((numDesktops + currentDesktop - 2) % numDesktops + 1);
01117 }
01118
01119 event->accept();
01120 return;
01121 }
01122 }
01123
01124 event->ignore();
01125 Applet::wheelEvent(event);
01126 }
01127
01128 bool Containment::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
01129 {
01130 Applet *applet = qgraphicsitem_cast<Applet*>(watched);
01131
01132
01133 Q_ASSERT(applet != 0);
01134 if (!d->applets.contains(applet)) {
01135 return false;
01136 }
01137
01138
01139 switch (event->type()) {
01140 case QEvent::GraphicsSceneHoverEnter:
01141
01142 if (immutability() == Mutable && applet->immutability() == Mutable) {
01143 QGraphicsSceneHoverEvent *he = static_cast<QGraphicsSceneHoverEvent*>(event);
01144 if (d->handles.contains(applet)) {
01145 AppletHandle *handle = d->handles.value(applet);
01146 if (handle) {
01147 handle->setHoverPos(he->pos());
01148 }
01149 } else {
01150
01151 AppletHandle *handle = new AppletHandle(this, applet, he->pos());
01152 d->handles[applet] = handle;
01153 connect(handle, SIGNAL(disappearDone(AppletHandle*)),
01154 this, SLOT(handleDisappeared(AppletHandle*)));
01155 connect(applet, SIGNAL(geometryChanged()),
01156 handle, SLOT(appletResized()));
01157 }
01158 }
01159 break;
01160 default:
01161 break;
01162 }
01163
01164 return false;
01165 }
01166
01167 QVariant Containment::itemChange(GraphicsItemChange change, const QVariant &value)
01168 {
01169
01170
01171 if (isContainment() && !ContainmentPrivate::s_positioning &&
01172 (change == QGraphicsItem::ItemSceneHasChanged || change == QGraphicsItem::ItemPositionHasChanged)) {
01173 switch (containmentType()) {
01174 case PanelContainment:
01175 case CustomPanelContainment:
01176 d->positionPanel();
01177 break;
01178 default:
01179 d->positionContainments();
01180 break;
01181 }
01182 }
01183
01184 return Applet::itemChange(change, value);
01185 }
01186
01187 void Containment::enableAction(const QString &name, bool enable)
01188 {
01189 QAction *action = this->action(name);
01190 if (action) {
01191 action->setEnabled(enable);
01192 action->setVisible(enable);
01193 }
01194 }
01195
01196 void Containment::addToolBoxAction(QAction *action)
01197 {
01198 if (d->toolBox) {
01199 d->toolBox->addTool(action);
01200 }
01201 }
01202
01203 void Containment::removeToolBoxAction(QAction *action)
01204 {
01205 if (d->toolBox) {
01206 d->toolBox->removeTool(action);
01207 }
01208 }
01209
01210 void Containment::setToolBoxOpen(bool open)
01211 {
01212 if (open) {
01213 openToolBox();
01214 } else {
01215 closeToolBox();
01216 }
01217 }
01218
01219 void Containment::openToolBox()
01220 {
01221 if (d->toolBox) {
01222 d->toolBox->showToolBox();
01223 }
01224 }
01225
01226 void Containment::closeToolBox()
01227 {
01228 if (d->toolBox) {
01229 d->toolBox->hideToolBox();
01230 }
01231 }
01232
01233 void Containment::addAssociatedWidget(QWidget *widget)
01234 {
01235 Applet::addAssociatedWidget(widget);
01236 if (d->focusedApplet) {
01237 d->focusedApplet->addAssociatedWidget(widget);
01238 }
01239
01240 foreach (const Applet *applet, d->applets) {
01241 if (applet->d->activationAction) {
01242 widget->addAction(applet->d->activationAction);
01243 }
01244 }
01245 }
01246
01247 void Containment::removeAssociatedWidget(QWidget *widget)
01248 {
01249 Applet::removeAssociatedWidget(widget);
01250 if (d->focusedApplet) {
01251 d->focusedApplet->removeAssociatedWidget(widget);
01252 }
01253
01254 foreach (const Applet *applet, d->applets) {
01255 if (applet->d->activationAction) {
01256 widget->removeAction(applet->d->activationAction);
01257 }
01258 }
01259 }
01260
01261 void Containment::setDrawWallpaper(bool drawWallpaper)
01262 {
01263 d->drawWallpaper = drawWallpaper;
01264 if (drawWallpaper) {
01265 KConfigGroup cfg = config();
01266 QString wallpaper = cfg.readEntry("wallpaperplugin", defaultWallpaper);
01267 QString mode = cfg.readEntry("wallpaperpluginmode", defaultWallpaperMode);
01268 setWallpaper(wallpaper, mode);
01269 } else {
01270 delete d->wallpaper;
01271 d->wallpaper = 0;
01272 }
01273 }
01274
01275 bool Containment::drawWallpaper()
01276 {
01277 return d->drawWallpaper;
01278 }
01279
01280 void Containment::setWallpaper(const QString &pluginName, const QString &mode)
01281 {
01282 KConfigGroup cfg = config();
01283 bool newPlugin = true;
01284 bool newMode = true;
01285
01286 if (d->drawWallpaper) {
01287 if (d->wallpaper) {
01288
01289 if (d->wallpaper->pluginName() != pluginName) {
01290 delete d->wallpaper;
01291 d->wallpaper = 0;
01292 } else {
01293
01294
01295 newMode = d->wallpaper->renderingMode().name() != mode;
01296 newPlugin = false;
01297 }
01298 }
01299
01300 if (!pluginName.isEmpty() && !d->wallpaper) {
01301 d->wallpaper = Plasma::Wallpaper::load(pluginName);
01302 }
01303
01304 if (d->wallpaper) {
01305 d->wallpaper->setBoundingRect(boundingRect());
01306 d->wallpaper->setRenderingMode(mode);
01307
01308 if (newPlugin) {
01309 connect(d->wallpaper, SIGNAL(update(const QRectF&)),
01310 this, SLOT(updateRect(const QRectF&)));
01311 cfg.writeEntry("wallpaperplugin", pluginName);
01312 }
01313
01314 if (d->wallpaper->isInitialized()) {
01315 KConfigGroup wallpaperConfig = KConfigGroup(&cfg, "Wallpaper");
01316 wallpaperConfig = KConfigGroup(&wallpaperConfig, pluginName);
01317 d->wallpaper->restore(wallpaperConfig);
01318 }
01319
01320 if (newMode) {
01321 cfg.writeEntry("wallpaperpluginmode", mode);
01322 }
01323 }
01324
01325 update();
01326 }
01327
01328 if (!d->wallpaper) {
01329 cfg.deleteEntry("wallpaperplugin");
01330 cfg.deleteEntry("wallpaperpluginmode");
01331 }
01332
01333 if (newPlugin || newMode) {
01334 emit configNeedsSaving();
01335 }
01336 }
01337
01338 Plasma::Wallpaper *Containment::wallpaper() const
01339 {
01340 return d->wallpaper;
01341 }
01342
01343 void Containment::setActivity(const QString &activity)
01344 {
01345 Context *context = d->context();
01346 if (context->currentActivity() != activity) {
01347 context->setCurrentActivity(activity);
01348
01349 foreach (Applet *a, d->applets) {
01350 a->updateConstraints(ContextConstraint);
01351 }
01352
01353 KConfigGroup c = config();
01354 c.writeEntry("activity", activity);
01355 emit configNeedsSaving();
01356 }
01357 }
01358
01359 QString Containment::activity() const
01360 {
01361 return d->context()->currentActivity();
01362 }
01363
01364 Context *ContainmentPrivate::context()
01365 {
01366 if (!con) {
01367 con = new Context(q);
01368 q->connect(con, SIGNAL(changed(Plasma::Context*)),
01369 q, SIGNAL(contextChanged(Plasma::Context*)));
01370 }
01371
01372 return con;
01373 }
01374
01375 KActionCollection &ContainmentPrivate::actions()
01376 {
01377 return static_cast<Applet*>(q)->d->actions;
01378 }
01379
01380 void ContainmentPrivate::focusApplet(Plasma::Applet *applet)
01381 {
01382 if (focusedApplet == applet) {
01383 return;
01384 }
01385
01386 QList<QWidget *> widgets = actions().associatedWidgets();
01387 if (focusedApplet) {
01388 foreach (QWidget *w, widgets) {
01389 focusedApplet->removeAssociatedWidget(w);
01390 }
01391 }
01392
01393 if (applet && applets.contains(applet)) {
01394
01395 focusedApplet = applet;
01396 foreach (QWidget *w, widgets) {
01397 focusedApplet->addAssociatedWidget(w);
01398 }
01399
01400 if (!focusedApplet->hasFocus()) {
01401 focusedApplet->setFocus(Qt::ShortcutFocusReason);
01402 }
01403 } else {
01404 focusedApplet = 0;
01405 }
01406 }
01407
01408 void Containment::focusNextApplet()
01409 {
01410 if (d->applets.isEmpty()) {
01411 return;
01412 }
01413 int index = d->focusedApplet ? d->applets.indexOf(d->focusedApplet) + 1 : 0;
01414 if (index >= d->applets.size()) {
01415 index = 0;
01416 }
01417 kDebug() << "index" << index;
01418 d->focusApplet(d->applets.at(index));
01419 }
01420
01421 void Containment::focusPreviousApplet()
01422 {
01423 if (d->applets.isEmpty()) {
01424 return;
01425 }
01426 int index = d->focusedApplet ? d->applets.indexOf(d->focusedApplet) - 1 : -1;
01427 if (index < 0) {
01428 index = d->applets.size() - 1;
01429 }
01430 kDebug() << "index" << index;
01431 d->focusApplet(d->applets.at(index));
01432 }
01433
01434 void Containment::destroy()
01435 {
01436 destroy(true);
01437 }
01438
01439 void Containment::showConfigurationInterface()
01440 {
01441 Applet::showConfigurationInterface();
01442 }
01443
01444 void ContainmentPrivate::requestConfiguration()
01445 {
01446 emit q->configureRequested(q);
01447 }
01448
01449 void Containment::destroy(bool confirm)
01450 {
01451 if (immutability() != Mutable) {
01452 return;
01453 }
01454
01455 if (isContainment()) {
01456
01457
01458
01459 Q_ASSERT(corona());
01460 if (d->type != PanelContainment && d->type != CustomPanelContainment &&
01461 (d->screen != -1 || d->screen >= corona()->numScreens())) {
01462 kDebug() << (QObject*)this << "containment has a screen number?" << d->screen;
01463 return;
01464 }
01465
01466
01467 if (!confirm ||
01468 KMessageBox::warningContinueCancel(
01469 view(),
01470 i18nc("%1 is the name of the containment", "Do you really want to remove this %1?", name()),
01471 i18nc("@title:window %1 is the name of the containment", "Remove %1", name()), KStandardGuiItem::remove()) == KMessageBox::Continue) {
01472
01473 Applet::destroy();
01474 }
01475 } else {
01476 Applet::destroy();
01477 }
01478 }
01479
01480 void ContainmentPrivate::toggleDesktopImmutability()
01481 {
01482 if (q->corona()) {
01483 if (q->corona()->immutability() == Mutable) {
01484 q->corona()->setImmutability(UserImmutable);
01485 } else if (q->corona()->immutability() == UserImmutable) {
01486 q->corona()->setImmutability(Mutable);
01487 }
01488 } else {
01489 if (q->immutability() == Mutable) {
01490 q->setImmutability(UserImmutable);
01491 } else if (q->immutability() == UserImmutable) {
01492 q->setImmutability(Mutable);
01493 }
01494 }
01495
01496 if (q->immutability() != Mutable) {
01497 QMap<Applet*, AppletHandle*> h = handles;
01498 handles.clear();
01499
01500 foreach (AppletHandle *handle, h) {
01501 handle->disconnect(q);
01502 handle->deleteLater();
01503 }
01504 }
01505
01506
01507 }
01508
01509 void ContainmentPrivate::zoomIn()
01510 {
01511 emit q->zoomRequested(q, Plasma::ZoomIn);
01512 positionToolBox();
01513 }
01514
01515 void ContainmentPrivate::zoomOut()
01516 {
01517 emit q->zoomRequested(q, Plasma::ZoomOut);
01518 positionToolBox();
01519 }
01520
01521 ToolBox *ContainmentPrivate::createToolBox()
01522 {
01523 if (!toolBox) {
01524 switch (type) {
01525 case Containment::PanelContainment:
01526 toolBox = new PanelToolBox(q);
01527 toolBox->setSize(22);
01528 toolBox->setIconSize(QSize(16, 16));
01529 if (q->immutability() != Mutable) {
01530 toolBox->hide();
01531 }
01532 break;
01533 case Containment::DesktopContainment:
01534 toolBox = new DesktopToolBox(q);
01535 break;
01536 default:
01537 break;
01538 }
01539
01540 if (toolBox) {
01541 QObject::connect(toolBox, SIGNAL(toggled()), q, SIGNAL(toolBoxToggled()));
01542 toolBox->load();
01543 positionToolBox();
01544 }
01545 }
01546
01547 return toolBox;
01548 }
01549
01550 void ContainmentPrivate::positionToolBox()
01551 {
01552 if (toolBox) {
01553 toolBox->reposition();
01554 }
01555 }
01556
01557 void ContainmentPrivate::triggerShowAddWidgets()
01558 {
01559 emit q->showAddWidgetsInterface(QPointF());
01560 }
01561
01562 void ContainmentPrivate::handleDisappeared(AppletHandle *handle)
01563 {
01564 if (handles.contains(handle->applet())) {
01565 handles.remove(handle->applet());
01566 handle->detachApplet();
01567 handle->deleteLater();
01568 }
01569 }
01570
01571 void ContainmentPrivate::checkRemoveAction()
01572 {
01573 q->enableAction("remove", (q->immutability() == Mutable &&
01574 (screen == -1 ||
01575 type == Plasma::Containment::PanelContainment ||
01576 type == Plasma::Containment::CustomPanelContainment)));
01577 }
01578
01579 void ContainmentPrivate::containmentConstraintsEvent(Plasma::Constraints constraints)
01580 {
01581 if (!q->isContainment()) {
01582 return;
01583 }
01584
01585
01586 if (constraints & Plasma::ImmutableConstraint) {
01587
01588 checkRemoveAction();
01589 bool unlocked = q->immutability() == Mutable;
01590 q->setAcceptDrops(unlocked);
01591 q->enableAction("add widgets", unlocked);
01592
01593
01594
01595
01596
01597
01598 QAction *action = actions().action("lock widgets");
01599 if (action) {
01600 action->setText(unlocked ? i18n("Lock Widgets") : i18n("Unlock Widgets"));
01601 action->setIcon(KIcon(unlocked ? "object-locked" : "object-unlocked"));
01602 }
01603
01604 bool canConfig = unlocked || KAuthorized::authorize("PlasmaAllowConfigureWhenLocked");
01605 if (canConfig) {
01606 action = actions().action("activity settings");
01607 if (action) {
01608 action->setVisible(canConfig);
01609 action->setEnabled(canConfig);
01610 }
01611 }
01612
01613
01614 foreach (Applet *a, applets) {
01615 a->updateConstraints(ImmutableConstraint);
01616 }
01617
01618 if (toolBox) {
01619 if (type == Containment::PanelContainment || type == Containment::CustomPanelContainment) {
01620 toolBox->setVisible(unlocked);
01621 } else {
01622 toolBox->setIsMovable(unlocked);
01623 }
01624 }
01625 }
01626
01627 if (constraints & Plasma::FormFactorConstraint) {
01628 if (toolBox) {
01629 if (q->formFactor() == Vertical) {
01630 toolBox->setCorner(ToolBox::Bottom);
01631
01632 } else if (QApplication::layoutDirection() == Qt::RightToLeft) {
01633 toolBox->setCorner(ToolBox::Left);
01634 } else {
01635 toolBox->setCorner(ToolBox::Right);
01636 }
01637 }
01638
01639 foreach (Applet *applet, applets) {
01640 applet->updateConstraints(Plasma::FormFactorConstraint);
01641 }
01642 }
01643
01644 if (constraints & Plasma::SizeConstraint && !ContainmentPrivate::s_positioning) {
01645 switch (q->containmentType()) {
01646 case Containment::PanelContainment:
01647 case Containment::CustomPanelContainment:
01648 positionPanel();
01649 break;
01650 default:
01651 positionContainments();
01652 break;
01653 }
01654 }
01655
01656 if (toolBox && (constraints & Plasma::SizeConstraint ||
01657 constraints & Plasma::FormFactorConstraint ||
01658 constraints & Plasma::ScreenConstraint ||
01659 constraints & Plasma::StartupCompletedConstraint)) {
01660
01661 positionToolBox();
01662 }
01663
01664 if (toolBox && constraints & Plasma::StartupCompletedConstraint) {
01665 toolBox->addTool(q->action("remove"));
01666 checkRemoveAction();
01667 }
01668 }
01669
01670 Applet *ContainmentPrivate::addApplet(const QString &name, const QVariantList &args,
01671 const QRectF &appletGeometry, uint id, bool delayInit)
01672 {
01673 if (!q->isContainment()) {
01674 return 0;
01675 }
01676
01677 if (!delayInit && q->immutability() != Mutable) {
01678 kDebug() << "addApplet for" << name << "requested, but we're currently immutable!";
01679 return 0;
01680 }
01681
01682 QGraphicsView *v = q->view();
01683 if (v) {
01684 v->setCursor(Qt::BusyCursor);
01685 }
01686
01687 Applet *applet = Applet::load(name, id, args);
01688 if (v) {
01689 v->unsetCursor();
01690 }
01691
01692 if (!applet) {
01693 kDebug() << "Applet" << name << "could not be loaded.";
01694 applet = new Applet(0, QString(), id);
01695 applet->setFailedToLaunch(true, i18n("Could not find requested component: %1", name));
01696 }
01697
01698
01699
01700 q->addApplet(applet, appletGeometry.topLeft(), delayInit);
01701 return applet;
01702 }
01703
01704 bool ContainmentPrivate::regionIsEmpty(const QRectF ®ion, Applet *ignoredApplet) const
01705 {
01706 foreach (Applet *applet, applets) {
01707 if (applet != ignoredApplet && applet->geometry().intersects(region)) {
01708 return false;
01709 }
01710 }
01711 return true;
01712 }
01713
01714 void ContainmentPrivate::appletDestroyed(QObject *object)
01715 {
01716
01717
01718
01719
01720
01721
01722
01723 Applet *applet = static_cast<Plasma::Applet*>(object);
01724 applets.removeAll(applet);
01725 if (focusedApplet == applet) {
01726 focusedApplet = 0;
01727 }
01728
01729 if (handles.contains(applet)) {
01730 AppletHandle *handle = handles.value(applet);
01731 handles.remove(applet);
01732 handle->deleteLater();
01733 }
01734
01735 emit q->appletRemoved(applet);
01736 emit q->configNeedsSaving();
01737 }
01738
01739 void ContainmentPrivate::containmentAppletAnimationComplete(QGraphicsItem *item, Plasma::Animator::Animation anim)
01740 {
01741 if (anim == Animator::AppearAnimation &&
01742 q->containmentType() == Containment::DesktopContainment &&
01743 item->parentItem() == q) {
01744 Applet *applet = qgraphicsitem_cast<Applet*>(item);
01745
01746 if (applet) {
01747 applet->installSceneEventFilter(q);
01748 KConfigGroup *cg = applet->d->mainConfigGroup();
01749 applet->save(*cg);
01750 emit q->configNeedsSaving();
01751
01752 }
01753 }
01754 }
01755
01756 bool containmentSortByPosition(const Containment *c1, const Containment *c2)
01757 {
01758 return c1->id() < c2->id();
01759 }
01760
01761 void ContainmentPrivate::positionContainments()
01762 {
01763 Corona *c = q->corona();
01764 if (!c || ContainmentPrivate::s_positioning) {
01765 return;
01766 }
01767
01768 ContainmentPrivate::s_positioning = true;
01769
01770
01771
01772 QList<Containment*> containments = c->containments();
01773 QMutableListIterator<Containment*> it(containments);
01774
01775 while (it.hasNext()) {
01776 Containment *containment = it.next();
01777 if (containment->containmentType() == Containment::PanelContainment ||
01778 containment->containmentType() == Containment::CustomPanelContainment) {
01779
01780
01781 it.remove();
01782 continue;
01783 }
01784 }
01785
01786 if (containments.isEmpty()) {
01787 ContainmentPrivate::s_positioning = false;
01788 return;
01789 }
01790
01791 qSort(containments.begin(), containments.end(), containmentSortByPosition);
01792 it.toFront();
01793
01794 int column = 0;
01795 int x = 0;
01796 int y = 0;
01797 int rowHeight = 0;
01798
01799
01800
01801 while (it.hasNext()) {
01802 Containment *containment = it.next();
01803 containment->setPos(x, y);
01804
01805
01806 int height = containment->size().height();
01807 if (height > rowHeight) {
01808 rowHeight = height;
01809 }
01810
01811 ++column;
01812
01813 if (column == CONTAINMENT_COLUMNS) {
01814 column = 0;
01815 x = 0;
01816 y += rowHeight + INTER_CONTAINMENT_MARGIN + TOOLBOX_MARGIN;
01817 rowHeight = 0;
01818 } else {
01819 x += containment->size().width() + INTER_CONTAINMENT_MARGIN;
01820 }
01821
01822
01823 }
01824
01825
01826 ContainmentPrivate::s_positioning = false;
01827 }
01828
01829 void ContainmentPrivate::positionPanel(bool force)
01830 {
01831 if (!q->scene()) {
01832 kDebug() << "no scene yet";
01833 return;
01834 }
01835
01836
01837
01838
01839 const QPointF p = q->pos();
01840
01841 if (!force &&
01842 p.y() + q->size().height() < -INTER_CONTAINMENT_MARGIN &&
01843 q->scene()->collidingItems(q).isEmpty()) {
01844
01845 return;
01846 }
01847
01848
01849 bool horiz = q->formFactor() == Plasma::Horizontal;
01850 qreal bottom = horiz ? 0 : VERTICAL_STACKING_OFFSET;
01851 qreal lastHeight = 0;
01852
01853
01854
01855
01856 foreach (const Containment *other, q->corona()->containments()) {
01857 if (other == q ||
01858 (other->containmentType() != Containment::PanelContainment &&
01859 other->containmentType() != Containment::CustomPanelContainment) ||
01860 horiz != (other->formFactor() == Plasma::Horizontal)) {
01861
01862 continue;
01863 }
01864
01865 if (horiz) {
01866 qreal y = other->pos().y();
01867 if (y < bottom) {
01868 lastHeight = other->size().height();
01869 bottom = y;
01870 }
01871 } else {
01872 qreal width = other->size().width();
01873 qreal x = other->pos().x() + width;
01874 if (x > bottom) {
01875 lastHeight = width;
01876 bottom = x + lastHeight;
01877 }
01878 }
01879 }
01880
01881 kDebug() << "positioning" << (horiz ? "" : "non-") << "horizontal panel; forced?" << force;
01882
01883
01884 QPointF newPos;
01885 if (horiz) {
01886 bottom -= lastHeight + INTER_CONTAINMENT_MARGIN;
01887
01888 kDebug() << "moved to" << QPointF(0, bottom - q->size().height());
01889 newPos = QPointF(0, bottom - q->size().height());
01890 } else {
01891 bottom += lastHeight + INTER_CONTAINMENT_MARGIN;
01892
01893 kDebug() << "moved to" << QPointF(bottom + q->size().width(), -INTER_CONTAINMENT_MARGIN - q->size().height());
01894 newPos = QPointF(bottom + q->size().width(), -INTER_CONTAINMENT_MARGIN - q->size().height());
01895 }
01896
01897 ContainmentPrivate::s_positioning = true;
01898 if (p != newPos) {
01899 q->setPos(newPos);
01900 emit q->geometryChanged();
01901 }
01902 ContainmentPrivate::s_positioning = false;
01903 }
01904
01905 }
01906
01907 #include "containment.moc"
01908