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

Plasma

containment.cpp

Go to the documentation of this file.
00001 /*
00002  *   Copyright 2007 by Aaron Seigo <aseigo@kde.org>
00003  *   Copyright 2008 by Ménard Alexis <darktears31@gmail.com>
00004  *
00005  *   This program is free software; you can redistribute it and/or modify
00006  *   it under the terms of the GNU Library General Public License as
00007  *   published by the Free Software Foundation; either version 2, or
00008  *   (at your option) any later version.
00009  *
00010  *   This program is distributed in the hope that it will be useful,
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *   GNU General Public License for more details
00014  *
00015  *   You should have received a copy of the GNU Library General Public
00016  *   License along with this program; if not, write to the
00017  *   Free Software Foundation, Inc.,
00018  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00019  */
00020 
00021 #include "containment.h"
00022 #include "private/containment_p.h"
00023 
00024 #include <QApplication>
00025 #include <QClipboard>
00026 #include <QFile>
00027 #include <QGraphicsSceneContextMenuEvent>
00028 #include <QGraphicsView>
00029 #include <QMimeData>
00030 #include <QPainter>
00031 #include <QStyleOptionGraphicsItem>
00032 #include <QGraphicsLayout>
00033 #include <QGraphicsLinearLayout>
00034 
00035 #include <kaction.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 "extenderitem.h"
00051 #include "svg.h"
00052 #include "wallpaper.h"
00053 
00054 #include "private/applet_p.h"
00055 #include "private/applethandle_p.h"
00056 #include "private/desktoptoolbox_p.h"
00057 #include "private/extenderitemmimedata_p.h"
00058 #include "private/paneltoolbox_p.h"
00059 
00060 namespace Plasma
00061 {
00062 
00063 bool ContainmentPrivate::s_positioning = false;
00064 static const char defaultWallpaper[] = "image";
00065 static const char defaultWallpaperMode[] = "SingleImage";
00066 
00067 Containment::StyleOption::StyleOption()
00068     : QStyleOptionGraphicsItem(),
00069       view(0)
00070 {
00071     version = Version;
00072     type = Type;
00073 }
00074 
00075 Containment::StyleOption::StyleOption(const Containment::StyleOption & other)
00076     : QStyleOptionGraphicsItem(other),
00077       view(other.view)
00078 {
00079     version = Version;
00080     type = Type;
00081 }
00082 
00083 Containment::StyleOption::StyleOption(const QStyleOptionGraphicsItem &other)
00084     : QStyleOptionGraphicsItem(other),
00085       view(0)
00086 {
00087     version = Version;
00088     type = Type;
00089 }
00090 
00091 Containment::Containment(QGraphicsItem *parent,
00092                          const QString &serviceId,
00093                          uint containmentId)
00094     : Applet(parent, serviceId, containmentId),
00095       d(new ContainmentPrivate(this))
00096 {
00097     // WARNING: do not access config() OR globalConfig() in this method!
00098     //          that requires a scene, which is not available at this point
00099     setPos(0, 0);
00100     setBackgroundHints(NoBackground);
00101     setContainmentType(CustomContainment);
00102     setHasConfigurationInterface(false);
00103 }
00104 
00105 Containment::Containment(QObject *parent, const QVariantList &args)
00106     : Applet(parent, args),
00107       d(new ContainmentPrivate(this))
00108 {
00109     // WARNING: do not access config() OR globalConfig() in this method!
00110     //          that requires a scene, which is not available at this point
00111     setPos(0, 0);
00112     setBackgroundHints(NoBackground);
00113     setHasConfigurationInterface(false);
00114 }
00115 
00116 Containment::~Containment()
00117 {
00118     delete d;
00119 }
00120 
00121 void Containment::init()
00122 {
00123     if (!isContainment()) {
00124         return;
00125     }
00126 
00127     setCacheMode(NoCache);
00128     setFlag(QGraphicsItem::ItemIsMovable, false);
00129     setFlag(QGraphicsItem::ItemClipsChildrenToShape, false);
00130     setAcceptDrops(true);
00131     setAcceptsHoverEvents(true);
00132 
00133     //TODO: would be nice to not do this on init, as it causes Animator to init
00134     connect(Animator::self(), SIGNAL(animationFinished(QGraphicsItem*,Plasma::Animator::Animation)),
00135             this, SLOT(containmentAppletAnimationComplete(QGraphicsItem*,Plasma::Animator::Animation)));
00136 
00137     if (d->type == NoContainmentType) {
00138         setContainmentType(DesktopContainment);
00139     }
00140 
00141     //connect actions
00142     ContainmentPrivate::addDefaultActions(d->actions());
00143     bool unlocked = immutability() == Mutable;
00144 
00145     //fix the text of the actions that need name()
00146     //btw, do we really want to use name() when it's a desktopcontainment?
00147     QAction *closeApplet = action("remove");
00148     if (closeApplet) {
00149         closeApplet->setText(i18nc("%1 is the name of the applet", "Remove this %1", name()));
00150     }
00151 
00152     QAction *configAction = action("configure");
00153     if (configAction) {
00154         configAction->setText(i18nc("%1 is the name of the applet", "%1 Settings", name()));
00155     }
00156 
00157     QAction *appletBrowserAction = action("add widgets");
00158     if (appletBrowserAction) {
00159         appletBrowserAction->setVisible(unlocked);
00160         appletBrowserAction->setEnabled(unlocked);
00161         connect(appletBrowserAction, SIGNAL(triggered()), this, SLOT(triggerShowAddWidgets()));
00162     }
00163 
00164     QAction *act = action("next applet");
00165     if (act) {
00166         connect(act, SIGNAL(triggered()), this, SLOT(focusNextApplet()));
00167     }
00168 
00169     act = action("previous applet");
00170     if (act) {
00171         connect(act, SIGNAL(triggered()), this, SLOT(focusPreviousApplet()));
00172     }
00173 
00174     if (immutability() != SystemImmutable && corona()) {
00175         QAction *lockDesktopAction = corona()->action("lock widgets");
00176         //keep a pointer so nobody notices it moved to corona
00177         if (lockDesktopAction) {
00178             d->actions()->addAction("lock widgets", lockDesktopAction);
00179         }
00180     }
00181 
00182     if (d->type == PanelContainment ||
00183         d->type == CustomPanelContainment) {
00184         d->actions()->removeAction(action("zoom in"));
00185     } else {
00186         QAction *zoomAction = action("zoom in");
00187         connect(zoomAction, SIGNAL(triggered()), this, SLOT(zoomIn()));
00188 
00189         if (corona()) {
00190             QAction *action = corona()->action("zoom out");
00191             if (action) {
00192                 d->actions()->addAction("zoom out", action);
00193             }
00194             action = corona()->action("add sibling containment");
00195             if (action) {
00196                 d->actions()->addAction("add sibling containment", action);
00197             }
00198             //a stupid hack to make this one's keyboard shortcut work
00199             action = corona()->action("configure shortcuts");
00200             if (action) {
00201                 d->actions()->addAction("configure shortcuts", action);
00202             }
00203         }
00204 
00205         if (d->type == DesktopContainment && d->toolBox) {
00206             d->toolBox->addTool(this->action("add widgets"));
00207             d->toolBox->addTool(this->action("zoom in"));
00208 
00209             //TODO: do we need some way to allow this be overridden?
00210             //      it's always available because shells rely on this
00211             //      to offer their own custom configuration as well
00212             QAction *configureContainment = this->action("configure");
00213             if (configureContainment) {
00214                 d->toolBox->addTool(configureContainment);
00215             }
00216         }
00217 
00218         //Set a default wallpaper the first time the containment is created,
00219         //for instance from the toolbox by the user
00220         if (d->drawWallpaper) {
00221             setDrawWallpaper(true);
00222         }
00223     }
00224 
00225 }
00226 
00227 void ContainmentPrivate::addDefaultActions(KActionCollection *actions)
00228 {
00229     actions->setConfigGroup("Shortcuts-Containment");
00230 
00231     //adjust applet actions
00232     KAction *appAction = qobject_cast<KAction*>(actions->action("remove"));
00233     appAction->setShortcut(KShortcut("alt+d, alt+r"));
00234     appAction->setText(i18n("Remove this Activity"));
00235     appAction = qobject_cast<KAction*>(actions->action("configure"));
00236     if (appAction) {
00237         appAction->setShortcut(KShortcut("alt+d, alt+s"));
00238         appAction->setText(i18n("Activity Settings"));
00239     }
00240 
00241     //add our own actions
00242     KAction *appletBrowserAction = actions->addAction("add widgets");
00243     appletBrowserAction->setAutoRepeat(false);
00244     appletBrowserAction->setText(i18n("Add Widgets..."));
00245     appletBrowserAction->setIcon(KIcon("list-add"));
00246     appletBrowserAction->setShortcut(KShortcut("alt+d, a"));
00247 
00248     KAction *action = actions->addAction("next applet");
00249     action->setText(i18n("Next Widget"));
00250     //no icon
00251     action->setShortcut(KShortcut("alt+d, n"));
00252 
00253     action = actions->addAction("previous applet");
00254     action->setText(i18n("Previous Widget"));
00255     //no icon
00256     action->setShortcut(KShortcut("alt+d, p"));
00257 
00258     KAction *zoomAction = actions->addAction("zoom in");
00259     zoomAction->setAutoRepeat(false);
00260     zoomAction->setText(i18n("Zoom In"));
00261     zoomAction->setIcon(KIcon("zoom-in"));
00262     //two shortcuts because I hate ctrl-+ but others expect it
00263     zoomAction->setShortcuts(KShortcut("alt+d, +; alt+d, ="));
00264 
00265 }
00266 
00267 // helper function for sorting the list of applets
00268 bool appletConfigLessThan(const KConfigGroup &c1, const KConfigGroup &c2)
00269 {
00270     QPointF p1 = c1.readEntry("geometry", QRectF()).topLeft();
00271     QPointF p2 = c2.readEntry("geometry", QRectF()).topLeft();
00272 
00273     if (!qFuzzyCompare(p1.x(), p2.x())) {
00274         if (QApplication::layoutDirection() == Qt::RightToLeft) {
00275             return p1.x() > p2.x();
00276         }
00277 
00278         return p1.x() < p2.x();
00279     }
00280 
00281     return qFuzzyCompare(p1.y(), p2.y()) || p1.y() < p2.y();
00282 }
00283 
00284 void Containment::restore(KConfigGroup &group)
00285 {
00286     /*kDebug() << "!!!!!!!!!!!!initConstraints" << group.name() << d->type;
00287     kDebug() << "    location:" << group.readEntry("location", (int)d->location);
00288     kDebug() << "    geom:" << group.readEntry("geometry", geometry());
00289     kDebug() << "    formfactor:" << group.readEntry("formfactor", (int)d->formFactor);
00290     kDebug() << "    screen:" << group.readEntry("screen", d->screen);*/
00291     if (!isContainment()) {
00292         Applet::restore(group);
00293         return;
00294     }
00295 
00296     QRectF geo = group.readEntry("geometry", geometry());
00297     //override max/min
00298     //this ensures panels are set to their saved size even when they have max & min set to prevent
00299     //resizing
00300     if (geo.size() != geo.size().boundedTo(maximumSize())) {
00301         setMaximumSize(maximumSize().expandedTo(geo.size()));
00302     }
00303     if (geo.size() != geo.size().expandedTo(minimumSize())) {
00304         setMinimumSize(minimumSize().boundedTo(geo.size()));
00305     }
00306 
00307 
00308     setGeometry(geo);
00309     //are we an offscreen containment?
00310     if (containmentType() != PanelContainment && containmentType() != CustomPanelContainment && geo.right() < 0) {
00311         corona()->addOffscreenWidget(this);
00312     }
00313 
00314     setLocation((Plasma::Location)group.readEntry("location", (int)d->location));
00315     setFormFactor((Plasma::FormFactor)group.readEntry("formfactor", (int)d->formFactor));
00316     //kDebug() << "setScreen from restore";
00317     setScreen(group.readEntry("screen", d->screen), group.readEntry("desktop", d->desktop));
00318     setActivity(group.readEntry("activity", QString()));
00319 
00320     flushPendingConstraintsEvents();
00321     restoreContents(group);
00322     setImmutability((ImmutabilityType)group.readEntry("immutability", (int)Mutable));
00323 
00324     setWallpaper(group.readEntry("wallpaperplugin", defaultWallpaper),
00325                  group.readEntry("wallpaperpluginmode", defaultWallpaperMode));
00326 
00327     if (d->toolBox) {
00328         d->toolBox->load(group);
00329     }
00330     /*
00331     kDebug() << "Containment" << id() <<
00332                 "screen" << screen() <<
00333                 "geometry is" << geometry() <<
00334                 "wallpaper" << ((d->wallpaper) ? d->wallpaper->pluginName() : QString()) <<
00335                 "wallpaper mode" << wallpaperMode() <<
00336                 "config entries" << group.entryMap();
00337     */
00338 }
00339 
00340 void Containment::save(KConfigGroup &g) const
00341 {
00342     if (Applet::d->transient) {
00343         return;
00344     }
00345 
00346     KConfigGroup group = g;
00347     if (!group.isValid()) {
00348         group = config();
00349     }
00350 
00351     // locking is saved in Applet::save
00352     Applet::save(group);
00353     group.writeEntry("screen", d->screen);
00354     group.writeEntry("desktop", d->desktop);
00355     group.writeEntry("formfactor", (int)d->formFactor);
00356     group.writeEntry("location", (int)d->location);
00357     group.writeEntry("activity", d->context()->currentActivity());
00358 
00359     if (d->toolBox) {
00360         d->toolBox->save(group);
00361     }
00362 
00363     if (d->wallpaper) {
00364         group.writeEntry("wallpaperplugin", d->wallpaper->pluginName());
00365         group.writeEntry("wallpaperpluginmode", d->wallpaper->renderingMode().name());
00366 
00367         if (d->wallpaper->isInitialized()) {
00368             KConfigGroup wallpaperConfig(&group, "Wallpaper");
00369             wallpaperConfig = KConfigGroup(&wallpaperConfig, d->wallpaper->pluginName());
00370             d->wallpaper->save(wallpaperConfig);
00371         }
00372     }
00373 
00374     saveContents(group);
00375 }
00376 
00377 void Containment::saveContents(KConfigGroup &group) const
00378 {
00379     KConfigGroup applets(&group, "Applets");
00380     foreach (const Applet *applet, d->applets) {
00381         KConfigGroup appletConfig(&applets, QString::number(applet->id()));
00382         applet->save(appletConfig);
00383     }
00384 }
00385 
00386 void Containment::restoreContents(KConfigGroup &group)
00387 {
00388     KConfigGroup applets(&group, "Applets");
00389 
00390     // Sort the applet configs in order of geometry to ensure that applets
00391     // are added from left to right or top to bottom for a panel containment
00392     QList<KConfigGroup> appletConfigs;
00393     foreach (const QString &appletGroup, applets.groupList()) {
00394         //kDebug() << "reading from applet group" << appletGroup;
00395         KConfigGroup appletConfig(&applets, appletGroup);
00396         appletConfigs.append(appletConfig);
00397     }
00398     qStableSort(appletConfigs.begin(), appletConfigs.end(), appletConfigLessThan);
00399 
00400     QMutableListIterator<KConfigGroup> it(appletConfigs);
00401     while (it.hasNext()) {
00402         KConfigGroup &appletConfig = it.next();
00403         int appId = appletConfig.name().toUInt();
00404         QString plugin = appletConfig.readEntry("plugin", QString());
00405 
00406         if (plugin.isEmpty()) {
00407             continue;
00408         }
00409 
00410         Applet *applet = d->addApplet(plugin, QVariantList(),
00411                                       appletConfig.readEntry("geometry", QRectF()),
00412                                       appId, true);
00413         applet->restore(appletConfig);
00414     }
00415 }
00416 
00417 Containment::Type Containment::containmentType() const
00418 {
00419     return d->type;
00420 }
00421 
00422 void Containment::setContainmentType(Containment::Type type)
00423 {
00424     if (d->type == type) {
00425         return;
00426     }
00427 
00428     delete d->toolBox;
00429     d->toolBox = 0;
00430     d->type = type;
00431 
00432     if (!isContainment()) {
00433         return;
00434     }
00435 
00436     if (type == DesktopContainment || type == PanelContainment) {
00437         d->createToolBox();
00438     }
00439 
00440     d->checkRemoveAction();
00441 }
00442 
00443 Corona *Containment::corona() const
00444 {
00445     return dynamic_cast<Corona*>(scene());
00446 }
00447 
00448 void Containment::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
00449 {
00450     event->ignore();
00451     if (d->wallpaper && d->wallpaper->isInitialized()) {
00452         QGraphicsItem *item = scene()->itemAt(event->scenePos());
00453         if (item == this) {
00454             d->wallpaper->mouseMoveEvent(event);
00455         }
00456     }
00457 
00458     if (!event->isAccepted()) {
00459         event->accept();
00460         Applet::mouseMoveEvent(event);
00461     }
00462 }
00463 
00464 void Containment::mousePressEvent(QGraphicsSceneMouseEvent *event)
00465 {
00466     event->ignore();
00467     if (d->wallpaper && d->wallpaper->isInitialized()) {
00468         QGraphicsItem *item = scene()->itemAt(event->scenePos());
00469         if (item == this) {
00470             d->wallpaper->mousePressEvent(event);
00471         }
00472     }
00473 
00474     if (event->isAccepted()) {
00475         setFocus(Qt::MouseFocusReason);
00476     } else if (event->button() == Qt::MidButton) {
00477         //middle-click = paste
00478         event->accept();
00479     } else {
00480         event->accept();
00481         Applet::mousePressEvent(event);
00482     }
00483 }
00484 
00485 void Containment::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
00486 {
00487     event->ignore();
00488     if (d->wallpaper && d->wallpaper->isInitialized()) {
00489         QGraphicsItem *item = scene()->itemAt(event->scenePos());
00490         if (item == this) {
00491             d->wallpaper->mouseReleaseEvent(event);
00492         }
00493     }
00494 
00495     if (event->isAccepted() || !isContainment()) {
00496         //do nothing
00497     } else if (event->button() == Qt::MidButton) {
00498         //middle-click = paste
00499         d->dropData(event);
00500         event->accept();
00501     } else {
00502         event->accept();
00503         Applet::mouseReleaseEvent(event);
00504     }
00505 }
00506 
00507 void Containment::showDropZone(const QPoint pos)
00508 {
00509     Q_UNUSED(pos)
00510     //Base implementation does nothing, don't put code here
00511 }
00512 
00513 void Containment::showContextMenu(const QPointF &containmentPos, const QPoint &screenPos)
00514 {
00515     d->showContextMenu(mapToScene(containmentPos), screenPos, false);
00516 }
00517 
00518 void Containment::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
00519 {
00520     //kDebug() << "let's see if we manage to get a context menu here, huh";
00521     if (!isContainment() || !scene() || !KAuthorized::authorizeKAction("desktop_contextmenu")) {
00522         Applet::contextMenuEvent(event);
00523         return;
00524     }
00525 
00526     if (!d->showContextMenu(event->scenePos(), event->screenPos(), true)) {
00527         Applet::contextMenuEvent(event);
00528     } else {
00529         event->accept();
00530     }
00531 }
00532 
00533 void ContainmentPrivate::containmentActions(KMenu &desktopMenu)
00534 {
00535     if (static_cast<Corona*>(q->scene())->immutability() != Mutable &&
00536         !KAuthorized::authorizeKAction("unlock_desktop")) {
00537         //kDebug() << "immutability";
00538         return;
00539     }
00540 
00541     //get base context actions
00542     QList<QAction*> actions = q->contextualActions();
00543 
00544     //find the separator to insert the activity settings before it
00545     QAction *separatorAction = 0;
00546 
00547     //TODO: should a submenu be created if there are too many containment specific
00548     //      actions? see folderview containment
00549     foreach (QAction *action, actions) {
00550         if (action) {
00551             desktopMenu.addAction(action);
00552             if (action->isSeparator()) {
00553                 separatorAction = action;
00554             }
00555         }
00556     }
00557 
00558     desktopMenu.addSeparator();
00559 
00560     if (type == Containment::DesktopContainment) {
00561         desktopMenu.addAction(q->action("configure"));
00562     }
00563 }
00564 
00565 void ContainmentPrivate::appletActions(KMenu &desktopMenu, Applet *applet, bool includeApplet)
00566 {
00567     QList<QAction*> actions;
00568 
00569     if (includeApplet) {
00570         actions = applet->contextualActions();
00571         if (!actions.isEmpty()) {
00572             foreach (QAction *action, actions) {
00573                 if (action) {
00574                     desktopMenu.addAction(action);
00575                 }
00576             }
00577         }
00578     }
00579 
00580     if (applet->hasConfigurationInterface()) {
00581         QAction *configureApplet = applet->d->actions->action("configure");
00582         if (configureApplet) {
00583             desktopMenu.addAction(configureApplet);
00584         }
00585     }
00586 
00587 
00588     if (static_cast<Corona*>(q->scene())->immutability() == Mutable) {
00589         if (!desktopMenu.isEmpty()) {
00590             desktopMenu.addSeparator();
00591         }
00592 
00593         QAction *closeApplet = applet->d->actions->action("remove");
00594         if (closeApplet) {
00595             desktopMenu.addAction(closeApplet);
00596         }
00597     }
00598 
00599     KMenu *containmentMenu = new KMenu(i18nc("%1 is the name of the containment", "%1 Options", q->name()), &desktopMenu);
00600     containmentActions(*containmentMenu);
00601     if (!containmentMenu->isEmpty()) {
00602         int enabled = 0;
00603         //count number of real actions
00604         foreach(QAction *action, containmentMenu->actions()) {
00605             if(action->isEnabled() && !action->isSeparator()) {
00606                 enabled++;
00607             }
00608         }
00609 
00610         if (enabled > 0) {
00611             desktopMenu.addSeparator();
00612         }
00613 
00614         //if there is only one, don't create a submenu
00615         if(enabled < 2) {
00616             foreach(QAction *action, containmentMenu->actions()) {
00617                 desktopMenu.addAction(action); 
00618             }
00619         } else {
00620             desktopMenu.addMenu(containmentMenu);
00621         }
00622     }
00623 }
00624 
00625 bool ContainmentPrivate::showContextMenu(const QPointF &point, const QPoint &screenPos, bool includeApplet)
00626 {
00627     Applet *applet = 0;
00628 
00629     QGraphicsItem *item = q->scene()->itemAt(point);
00630     if (item == q) {
00631         item = 0;
00632     }
00633 
00634     while (item) {
00635         applet = qgraphicsitem_cast<Applet*>(item);
00636         if (applet && !applet->isContainment()) {
00637             break;
00638         }
00639 
00640         // applet may have a value due to finding a containment!
00641         applet = 0;
00642         item = item->parentItem();
00643     }
00644 
00645     KMenu desktopMenu;
00646     //kDebug() << "context menu event " << (QObject*)applet;
00647     if (applet) {
00648         appletActions(desktopMenu, applet, includeApplet);
00649     } else {
00650         containmentActions(desktopMenu);
00651     }
00652 
00653     if (!desktopMenu.isEmpty()) {
00654         //kDebug() << "executing at" << screenPos;
00655         desktopMenu.exec(screenPos);
00656         return true;
00657     }
00658 
00659     return false;
00660 }
00661 
00662 void Containment::setFormFactor(FormFactor formFactor)
00663 {
00664     if (d->formFactor == formFactor) {
00665         return;
00666     }
00667 
00668     //kDebug() << "switching FF to " << formFactor;
00669     d->formFactor = formFactor;
00670 
00671     if (isContainment() &&
00672         (d->type == PanelContainment || d->type == CustomPanelContainment)) {
00673         // we are a panel and we have chaged our orientation
00674         d->positionPanel(true);
00675     }
00676 
00677     if (d->toolBox) {
00678         if (d->formFactor == Vertical) {
00679             d->toolBox->setCorner(ToolBox::Bottom);
00680             //defaults to horizontal
00681         } else if (QApplication::layoutDirection() == Qt::RightToLeft) {
00682             d->toolBox->setCorner(ToolBox::Left);
00683         } else {
00684             d->toolBox->setCorner(ToolBox::Right);
00685         }
00686     }
00687 
00688     updateConstraints(Plasma::FormFactorConstraint);
00689 
00690     KConfigGroup c = config();
00691     c.writeEntry("formfactor", (int)formFactor);
00692     emit configNeedsSaving();
00693 }
00694 
00695 void Containment::setLocation(Location location)
00696 {
00697     if (d->location == location) {
00698         return;
00699     }
00700 
00701     bool emitGeomChange = false;
00702 
00703     if ((location == TopEdge || location == BottomEdge) &&
00704         (d->location == TopEdge || d->location == BottomEdge)) {
00705         emitGeomChange = true;
00706     }
00707 
00708     if ((location == RightEdge || location == LeftEdge) &&
00709         (d->location == RightEdge || d->location == LeftEdge)) {
00710         emitGeomChange = true;
00711     }
00712 
00713     d->location = location;
00714 
00715     foreach (Applet *applet, d->applets) {
00716         applet->updateConstraints(Plasma::LocationConstraint);
00717     }
00718 
00719     if (emitGeomChange) {
00720         // our geometry on the scene will not actually change,
00721         // but for the purposes of views it has
00722         emit geometryChanged();
00723     }
00724 
00725     updateConstraints(Plasma::LocationConstraint);
00726 
00727     KConfigGroup c = config();
00728     c.writeEntry("location", (int)location);
00729     emit configNeedsSaving();
00730 }
00731 
00732 void Containment::addSiblingContainment()
00733 {
00734     emit addSiblingContainment(this);
00735 }
00736 
00737 void Containment::clearApplets()
00738 {
00739     foreach (Applet *applet, d->applets) {
00740         applet->d->cleanUpAndDelete();
00741     }
00742 
00743     d->applets.clear();
00744 }
00745 
00746 Applet *Containment::addApplet(const QString &name, const QVariantList &args,
00747                                const QRectF &appletGeometry)
00748 {
00749     return d->addApplet(name, args, appletGeometry);
00750 }
00751 
00752 void Containment::addApplet(Applet *applet, const QPointF &pos, bool delayInit)
00753 {
00754     if (!isContainment() || (!delayInit && immutability() != Mutable)) {
00755         return;
00756     }
00757 
00758     if (!applet) {
00759         kDebug() << "adding null applet!?!";
00760         return;
00761     }
00762 
00763     if (d->applets.contains(applet)) {
00764         kDebug() << "already have this applet!";
00765     }
00766 
00767     Containment *currentContainment = applet->containment();
00768 
00769     if (d->type == PanelContainment) {
00770         //panels don't want backgrounds, which is important when setting geometry
00771         setBackgroundHints(NoBackground);
00772     }
00773 
00774     if (currentContainment && currentContainment != this) {
00775         emit currentContainment->appletRemoved(applet);
00776         if (currentContainment->d->focusedApplet == applet) {
00777             currentContainment->d->focusedApplet = 0;
00778         }
00779 
00780         disconnect(applet, 0, currentContainment, 0);
00781         applet->removeSceneEventFilter(currentContainment);
00782         KConfigGroup oldConfig = applet->config();
00783         currentContainment->d->applets.removeAll(applet);
00784         if (currentContainment->d->handles.contains(applet)) {
00785             currentContainment->d->handles.remove(applet);
00786         }
00787         applet->setParentItem(this);
00788 
00789         // now move the old config to the new location
00790         //FIXME: this doesn't seem to get the actual main config group containing plugin=, etc
00791         KConfigGroup c = config().group("Applets").group(QString::number(applet->id()));
00792         oldConfig.reparent(&c);
00793         applet->d->resetConfigurationObject();
00794 
00795         disconnect(applet, SIGNAL(activate()), currentContainment, SIGNAL(activate()));
00796     } else {
00797         applet->setParentItem(this);
00798     }
00799 
00800     d->applets << applet;
00801 
00802     connect(applet, SIGNAL(configNeedsSaving()), this, SIGNAL(configNeedsSaving()));
00803     connect(applet, SIGNAL(releaseVisualFocus()), this, SIGNAL(releaseVisualFocus()));
00804     connect(applet, SIGNAL(appletDestroyed(Plasma::Applet*)), this, SLOT(appletDestroyed(Plasma::Applet*)));
00805     connect(applet, SIGNAL(activate()), this, SIGNAL(activate()));
00806 
00807     if (pos != QPointF(-1, -1)) {
00808         applet->setPos(pos);
00809     }
00810 
00811     if (delayInit || currentContainment) {
00812         if (d->type == DesktopContainment) {
00813             applet->installSceneEventFilter(this);
00814             //applet->setWindowFlags(Qt::Window);
00815         }
00816     } else {
00817         applet->init();
00818         Animator::self()->animateItem(applet, Animator::AppearAnimation);
00819     }
00820 
00821     applet->updateConstraints(Plasma::AllConstraints);
00822 
00823     if (!delayInit) {
00824         applet->flushPendingConstraintsEvents();
00825     }
00826 
00827     emit appletAdded(applet, pos);
00828 
00829     if (!currentContainment) {
00830         applet->updateConstraints(Plasma::StartupCompletedConstraint);
00831         if (!delayInit) {
00832             applet->flushPendingConstraintsEvents();
00833         }
00834     }
00835 
00836     if (!delayInit) {
00837         applet->d->scheduleModificationNotification();
00838     }
00839 }
00840 
00841 Applet::List Containment::applets() const
00842 {
00843     return d->applets;
00844 }
00845 
00846 void Containment::setScreen(int newScreen, int newDesktop)
00847 {
00848     // What we want to do in here is:
00849     //   * claim the screen as our own
00850     //   * signal whatever may be watching this containment about the switch
00851     //   * if we are a full screen containment, then:
00852     //      * resize to match the screen if we're that kind of containment
00853     //      * kick other full-screen containments off this screen
00854     //          * if we had a screen, then give our screen to the containment
00855     //            we kick out
00856     //
00857     // a screen of -1 means no associated screen.
00858     Q_ASSERT(corona());
00859     int numScreens = corona()->numScreens();
00860     if (newScreen < -1) {
00861         newScreen = -1;
00862     }
00863 
00864     // -1 == All desktops
00865     if (newDesktop < -1 || newDesktop > KWindowSystem::numberOfDesktops() - 1) {
00866         newDesktop = -1;
00867     }
00868 
00869     //kDebug() << activity() << "setting screen to " << newScreen << newDesktop << "and type is" << d->type;
00870 
00871     Containment *swapScreensWith(0);
00872     if (d->type == DesktopContainment || d->type >= CustomContainment) {
00873         // we want to listen to changes in work area if our screen changes
00874         if (d->screen < 0 && newScreen > -1) {
00875             connect(KWindowSystem::self(), SIGNAL(workAreaChanged()), this, SLOT(positionToolBox()));
00876         } else if (newScreen < 0) {
00877             disconnect(KWindowSystem::self(), SIGNAL(workAreaChanged()), this, SLOT(positionToolBox()));
00878         }
00879 
00880         if (newScreen > -1 && corona()) {
00881             // sanity check to make sure someone else doesn't have this screen already!
00882             Containment *currently = corona()->containmentForScreen(newScreen, newDesktop);
00883             if (currently && currently != this) {
00884                 kDebug() << "currently is on screen" << currently->screen()
00885                          << "desktop" << currently->desktop()
00886                          << "and is" << currently->activity()
00887                          << (QObject*)currently << "i'm" << (QObject*)this;
00888                 //kDebug() << "setScreen due to swap";
00889                 currently->setScreen(-1, newDesktop);
00890                 swapScreensWith = currently;
00891             }
00892         }
00893     }
00894 
00895     if (newScreen < numScreens && newScreen > -1) {
00896         if (d->type == DesktopContainment ||
00897             d->type >= CustomContainment) {
00898             resize(corona()->screenGeometry(newScreen).size());
00899         }
00900     }
00901 
00902     int oldDesktop = d->desktop;
00903     d->desktop = newDesktop;
00904 
00905     int oldScreen = d->screen;
00906     d->screen = newScreen;
00907 
00908     updateConstraints(Plasma::ScreenConstraint);
00909 
00910     if (oldScreen != newScreen || oldDesktop != newDesktop) {
00911         if (oldScreen != newScreen) {
00912             emit screenChanged(oldScreen, newScreen, this);
00913         }
00914 
00915         KConfigGroup c = config();
00916         c.writeEntry("screen", d->screen);
00917         c.writeEntry("desktop", d->desktop);
00918         emit configNeedsSaving();
00919     }
00920 
00921     if (swapScreensWith) {
00922         //kDebug() << "setScreen due to swap, part 2";
00923         swapScreensWith->setScreen(oldScreen, oldDesktop);
00924     }
00925 
00926     d->checkRemoveAction();
00927 
00928     if (newScreen >= 0) {
00929         emit activate();
00930     }
00931 }
00932 
00933 int Containment::screen() const
00934 {
00935     return d->screen;
00936 }
00937 
00938 int Containment::desktop() const
00939 {
00940     return d->desktop;
00941 }
00942 
00943 KPluginInfo::List Containment::listContainments(const QString &category,
00944                                                 const QString &parentApp)
00945 {
00946     return listContainmentsOfType(QString(), category, parentApp);
00947 }
00948 
00949 
00950 KPluginInfo::List Containment::listContainmentsOfType(const QString &type,
00951                                                       const QString &category,
00952                                                       const QString &parentApp)
00953 {
00954     QString constraint;
00955 
00956     if (parentApp.isEmpty()) {
00957         constraint.append("not exist [X-KDE-ParentApp]");
00958     } else {
00959         constraint.append("[X-KDE-ParentApp] == '").append(parentApp).append("'");
00960     }
00961 
00962     if (!type.isEmpty()) {
00963         if (!constraint.isEmpty()) {
00964             constraint.append(" and ");
00965         }
00966 
00967         constraint.append("'").append(type).append("' ~in [X-Plasma-ContainmentCategories]");
00968     }
00969 
00970     if (!category.isEmpty()) {
00971         if (!constraint.isEmpty()) {
00972             constraint.append(" and ");
00973         }
00974 
00975         constraint.append("[X-KDE-PluginInfo-Category] == '").append(category).append("'");
00976         if (category == "Miscellaneous") {
00977             constraint.append(" or (not exist [X-KDE-PluginInfo-Category] or [X-KDE-PluginInfo-Category] == '')");
00978         }
00979     }
00980 
00981     KService::List offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint);
00982     //kDebug() << "constraint was" << constraint << "which got us" << offers.count() << "matches";
00983     return KPluginInfo::fromServices(offers);
00984 }
00985 
00986 KPluginInfo::List Containment::listContainmentsForMimetype(const QString &mimetype)
00987 {
00988     QString constraint = QString("'%1' in [X-Plasma-DropMimeTypes]").arg(mimetype);
00989     //kDebug() << mimetype << constraint;
00990     KService::List offers = KServiceTypeTrader::self()->query("Plasma/Containment", constraint);
00991     return KPluginInfo::fromServices(offers);
00992 }
00993 
00994 QStringList Containment::listContainmentTypes()
00995 {
00996     KPluginInfo::List containmentInfos = listContainments();
00997     QSet<QString> types;
00998 
00999     foreach (const KPluginInfo &containmentInfo, containmentInfos) {
01000         QStringList theseTypes = containmentInfo.service()->property("X-Plasma-ContainmentCategories").toStringList();
01001         foreach (const QString &type, theseTypes) {
01002             types.insert(type);
01003         }
01004     }
01005 
01006     return types.toList();
01007 }
01008 
01009 void Containment::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
01010 {
01011     //kDebug() << immutability() << Mutable << (immutability() == Mutable);
01012     event->setAccepted(immutability() == Mutable &&
01013                        (event->mimeData()->hasFormat(static_cast<Corona*>(scene())->appletMimeType()) ||
01014                         KUrl::List::canDecode(event->mimeData()) ||
01015                         event->mimeData()->hasFormat(ExtenderItemMimeData::mimeType())));
01016 
01017     if (!event->isAccepted()) {
01018         // check to see if we have an applet that accepts the format.
01019         QStringList formats = event->mimeData()->formats();
01020 
01021         foreach (const QString &format, formats) {
01022             KPluginInfo::List appletList = Applet::listAppletInfoForMimetype(format);
01023             if (!appletList.isEmpty()) {
01024                 event->setAccepted(true);
01025                 break;
01026             }
01027         }
01028     }
01029 
01030     if (event->isAccepted() && view()) {
01031         showDropZone(view()->mapFromScene(event->scenePos()));
01032     }
01033 }
01034 
01035 void Containment::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
01036 {
01037     QGraphicsItem *item = scene()->itemAt(event->scenePos());
01038     event->setAccepted(item == this || !item);
01039     Plasma::Containment *c = containment();
01040     if (c && c->immutability() == Plasma::Mutable &&
01041         (event->mimeData()->hasFormat(static_cast<Plasma::Corona*>(scene())->appletMimeType()) ||
01042         KUrl::List::canDecode(event->mimeData())) && view()) {
01043             showDropZone(view()->mapFromScene(event->scenePos()));
01044      }
01045 }
01046 
01047 void Containment::dropEvent(QGraphicsSceneDragDropEvent *event)
01048 {
01049     if (isContainment()) {
01050         d->dropData(event);
01051     } else {
01052         Applet::dropEvent(event);
01053     }
01054 }
01055 
01056 void ContainmentPrivate::dropData(QGraphicsSceneEvent *event)
01057 {
01058     if (q->immutability() != Mutable) {
01059         return;
01060     }
01061 
01062     QGraphicsSceneDragDropEvent *dropEvent = dynamic_cast<QGraphicsSceneDragDropEvent*>(event);
01063     QGraphicsSceneMouseEvent *mouseEvent = dynamic_cast<QGraphicsSceneMouseEvent*>(event);
01064 
01065     QPointF pos;
01066     QPointF scenePos;
01067     QPoint screenPos;
01068     const QMimeData *mimeData = 0;
01069 
01070     if (dropEvent) {
01071         pos = dropEvent->pos();
01072         scenePos = dropEvent->scenePos();
01073         screenPos = dropEvent->screenPos();
01074         mimeData = dropEvent->mimeData();
01075     } else if (mouseEvent) {
01076         pos = mouseEvent->pos();
01077         scenePos = mouseEvent->scenePos();
01078         screenPos = mouseEvent->screenPos();
01079         QClipboard *clipboard = QApplication::clipboard();
01080         mimeData = clipboard->mimeData(QClipboard::Selection);
01081         //TODO if that's not supported (ie non-linux) should we try clipboard instead of selection?
01082     } else {
01083         kDebug() << "unexpected event";
01084     }
01085 
01086     if (!mimeData) {
01087         //Selection is either empty or not sopported on this OS
01088         kDebug() << "no mime data";
01089         return;
01090     }
01091 
01092     //kDebug() << event->mimeData()->text();
01093 
01094     QString appletMimetype(q->corona() ? q->corona()->appletMimeType() : QString());
01095 
01096     if (!appletMimetype.isEmpty() && mimeData->hasFormat(appletMimetype)) {
01097         QString data = mimeData->data(appletMimetype);
01098         QStringList appletNames = data.split('\n', QString::SkipEmptyParts);
01099 
01100         foreach (const QString &appletName, appletNames) {
01101             //kDebug() << "doing" << appletName;
01102             QRectF geom(q->mapFromScene(scenePos), QSize(0, 0));
01103             q->addApplet(appletName, QVariantList(), geom);
01104         }
01105         if (dropEvent) {
01106             dropEvent->acceptProposedAction();
01107         }
01108     } else if (mimeData->hasFormat(ExtenderItemMimeData::mimeType())) {
01109         kDebug() << "mimetype plasma/extenderitem is dropped, creating internal:extender";
01110         //Handle dropping extenderitems.
01111         const ExtenderItemMimeData *extenderData = qobject_cast<const ExtenderItemMimeData*>(mimeData);
01112         if (extenderData) {
01113             ExtenderItem *item = extenderData->extenderItem();
01114             QRectF geometry(pos, item->size());
01115             kDebug() << "desired geometry: " << geometry;
01116             Applet *applet = q->addApplet("internal:extender", QVariantList(), geometry);
01117             item->setExtender(applet->extender());
01118         }
01119     } else if (KUrl::List::canDecode(mimeData)) {
01120         //TODO: collect the mimetypes of available script engines and offer
01121         //      to create widgets out of the matching URLs, if any
01122         KUrl::List urls = KUrl::List::fromMimeData(mimeData);
01123         foreach (const KUrl &url, urls) {
01124             KMimeType::Ptr mime = KMimeType::findByUrl(url);
01125             QString mimeName = mime->name();
01126             QRectF geom(pos, QSize());
01127             QVariantList args;
01128             args << url.url();
01129             //             kDebug() << mimeName;
01130             KPluginInfo::List appletList = Applet::listAppletInfoForMimetype(mimeName);
01131 
01132             if (!appletList.isEmpty()) {
01133                 //TODO: should we show a dialog here to choose which plasmoid load if
01135                 QMenu choices;
01136                 QHash<QAction *, QString> actionsToPlugins;
01137                 foreach (const KPluginInfo &info, appletList) {
01138                     QAction *action;
01139                     if (!info.icon().isEmpty()) {
01140                         action = choices.addAction(KIcon(info.icon()), info.name());
01141                     } else {
01142                         action = choices.addAction(info.name());
01143                     }
01144 
01145                     actionsToPlugins.insert(action, info.pluginName());
01146                 }
01147 
01148                 actionsToPlugins.insert(choices.addAction(i18n("Icon")), "icon");
01149                 QAction *choice = choices.exec(screenPos);
01150                 if (choice) {
01151                     q->addApplet(actionsToPlugins[choice], args, geom);
01152                 }
01153             } else if (url.protocol() != "data") {
01154                 // We don't try to do anything with data: URIs
01155                 // no special applet associated with this mimetype, let's
01156                 q->addApplet("icon", args, geom);
01157             }
01158         }
01159 
01160         if (dropEvent) {
01161             dropEvent->acceptProposedAction();
01162         }
01163     } else {
01164         QStringList formats = mimeData->formats();
01165         QHash<QString, KPluginInfo> seenPlugins;
01166         QHash<QString, QString> pluginFormats;
01167 
01168         foreach (const QString &format, formats) {
01169             KPluginInfo::List plugins = Applet::listAppletInfoForMimetype(format);
01170 
01171             foreach (const KPluginInfo &plugin, plugins) {
01172                 if (seenPlugins.contains(plugin.pluginName())) {
01173                     continue;
01174                 }
01175 
01176                 seenPlugins.insert(plugin.pluginName(), plugin);
01177                 pluginFormats.insert(plugin.pluginName(), format);
01178             }
01179         }
01180 
01181         QString selectedPlugin;
01182 
01183         if (seenPlugins.isEmpty()) {
01184             // do nothing
01185         } else if (seenPlugins.count() == 1) {
01186             selectedPlugin = seenPlugins.constBegin().key();
01187         } else {
01188             QMenu choices;
01189             QHash<QAction *, QString> actionsToPlugins;
01190             foreach (const KPluginInfo &info, seenPlugins) {
01191                 QAction *action;
01192                 if (!info.icon().isEmpty()) {
01193                     action = choices.addAction(KIcon(info.icon()), info.name());
01194                 } else {
01195                     action = choices.addAction(info.name());
01196                 }
01197 
01198                 actionsToPlugins.insert(action, info.pluginName());
01199             }
01200 
01201             QAction *choice = choices.exec(screenPos);
01202             if (choice) {
01203                 selectedPlugin = actionsToPlugins[choice];
01204             }
01205         }
01206 
01207         if (!selectedPlugin.isEmpty()) {
01208             KTemporaryFile tempFile;
01209             if (tempFile.open()) {
01210                 //TODO: what should we do with files after the applet is done with them??
01211                 tempFile.setAutoRemove(false);
01212 
01213                 {
01214                     QDataStream stream(&tempFile);
01215                     QByteArray data = mimeData->data(pluginFormats[selectedPlugin]);
01216                     stream.writeRawData(data, data.size());
01217                 }
01218 
01219                 QRectF geom(pos, QSize());
01220                 QVariantList args;
01221                 args << tempFile.fileName();
01222                 kDebug() << args;
01223                 tempFile.close();
01224 
01225                 q->addApplet(selectedPlugin, args, geom);
01226             }
01227         }
01228     }
01229 }
01230 
01231 const QGraphicsItem *Containment::toolBoxItem() const
01232 {
01233     return d->toolBox;
01234 }
01235 
01236 void Containment::resizeEvent(QGraphicsSceneResizeEvent *event)
01237 {
01238     Applet::resizeEvent(event);
01239 
01240     if (!ContainmentPrivate::s_positioning) {
01241         switch (d->type) {
01242             case Containment::PanelContainment:
01243             case Containment::CustomPanelContainment:
01244                 d->positionPanel();
01245                 break;
01246             default:
01247                 d->positionContainments();
01248                 break;
01249         }
01250     }
01251 
01252     if (d->wallpaper) {
01253         d->wallpaper->setBoundingRect(QRectF(QPointF(0, 0), size()));
01254     }
01255 }
01256 
01257 void Containment::keyPressEvent(QKeyEvent *event)
01258 {
01259     //kDebug() << "keyPressEvent with" << event->key()
01260     //         << "and hoping and wishing for a" << Qt::Key_Tab;
01261     if (event->key() == Qt::Key_Tab) { // && event->modifiers() == 0) {
01262         if (!d->applets.isEmpty()) {
01263             kDebug() << "let's give focus to...." << (QObject*)d->applets.first();
01264             d->applets.first()->setFocus(Qt::TabFocusReason);
01265         }
01266     }
01267 }
01268 
01269 void Containment::wheelEvent(QGraphicsSceneWheelEvent *event)
01270 {
01271     if (d->wallpaper && d->wallpaper->isInitialized()) {
01272         QGraphicsItem *item = scene()->itemAt(event->scenePos());
01273         if (item == this) {
01274             event->ignore();
01275             d->wallpaper->wheelEvent(event);
01276 
01277             if (event->isAccepted()) {
01278                 return;
01279             }
01280 
01281             event->accept();
01282         }
01283     }
01284 
01285     if (d->type == DesktopContainment) {
01286         QGraphicsItem *item = scene()->itemAt(event->scenePos());
01287         if (item == this) {
01288             int numDesktops = KWindowSystem::numberOfDesktops();
01289             int currentDesktop = KWindowSystem::currentDesktop();
01290 
01291             if (event->delta() < 0) {
01292                 KWindowSystem::setCurrentDesktop(currentDesktop % numDesktops + 1);
01293             } else {
01294                 KWindowSystem::setCurrentDesktop((numDesktops + currentDesktop - 2) % numDesktops + 1);
01295             }
01296 
01297             event->accept();
01298             return;
01299         }
01300     }
01301 
01302     event->ignore();
01303     Applet::wheelEvent(event);
01304 }
01305 
01306 bool Containment::sceneEventFilter(QGraphicsItem *watched, QEvent *event)
01307 {
01308     Applet *applet = qgraphicsitem_cast<Applet*>(watched);
01309 
01310     // Otherwise we're watching something we shouldn't be...
01311     Q_ASSERT(applet != 0);
01312     if (!d->applets.contains(applet)) {
01313         return false;
01314     }
01315 
01316     //kDebug() << "got sceneEvent";
01317     switch (event->type()) {
01318     case QEvent::GraphicsSceneHoverEnter:
01319         //kDebug() << "got hoverenterEvent" << immutability() << " " << applet->immutability();
01320         if (immutability() == Mutable && applet->immutability() == Mutable) {
01321             QGraphicsSceneHoverEvent *he = static_cast<QGraphicsSceneHoverEvent*>(event);
01322             if (d->handles.contains(applet)) {
01323                 AppletHandle *handle = d->handles.value(applet);
01324                 if (handle) {
01325                     handle->setHoverPos(he->pos());
01326                 }
01327             } else {
01328                 //kDebug() << "generated applet handle";
01329                 AppletHandle *handle = new AppletHandle(this, applet, he->pos());
01330                 d->handles[applet] = handle;
01331                 connect(handle, SIGNAL(disappearDone(AppletHandle*)),
01332                         this, SLOT(handleDisappeared(AppletHandle*)));
01333                 connect(applet, SIGNAL(geometryChanged()),
01334                         handle, SLOT(appletResized()));
01335             }
01336         }
01337         break;
01338     case QEvent::GraphicsSceneHoverMove:
01339         if (immutability() == Mutable && applet->immutability() == Mutable) {
01340             QGraphicsSceneHoverEvent *he = static_cast<QGraphicsSceneHoverEvent*>(event);
01341             if (d->handles.contains(applet)) {
01342                 AppletHandle *handle = d->handles.value(applet);
01343                 if (handle) {
01344                     handle->setHoverPos(he->pos());
01345                 }
01346             }
01347         }
01348         break;
01349     default:
01350         break;
01351     }
01352 
01353     return false;
01354 }
01355 
01356 QVariant Containment::itemChange(GraphicsItemChange change, const QVariant &value)
01357 {
01358     //FIXME if the applet is moved to another containment we need to unfocus it
01359 
01360     if (isContainment() && !ContainmentPrivate::s_positioning &&
01361         (change == QGraphicsItem::ItemSceneHasChanged || change == QGraphicsItem::ItemPositionHasChanged)) {
01362         switch (d->type) {
01363             case PanelContainment:
01364             case CustomPanelContainment:
01365                 d->positionPanel();
01366                 break;
01367             default:
01368                 d->positionContainments();
01369                 break;
01370         }
01371     }
01372 
01373     return Applet::itemChange(change, value);
01374 }
01375 
01376 void Containment::enableAction(const QString &name, bool enable)
01377 {
01378     QAction *action = this->action(name);
01379     if (action) {
01380         action->setEnabled(enable);
01381         action->setVisible(enable);
01382     }
01383 }
01384 
01385 void Containment::addToolBoxAction(QAction *action)
01386 {
01387     if (!d->toolBox && (d->type == CustomPanelContainment || d->type >= CustomContainment)) {
01388         d->createToolBox();
01389     }
01390 
01391     if (d->toolBox) {
01392         d->toolBox->addTool(action);
01393     }
01394 }
01395 
01396 void Containment::removeToolBoxAction(QAction *action)
01397 {
01398     if (d->toolBox) {
01399         d->toolBox->removeTool(action);
01400     }
01401 }
01402 
01403 void Containment::setToolBoxOpen(bool open)
01404 {
01405     if (open) {
01406         openToolBox();
01407     } else {
01408         closeToolBox();
01409     }
01410 }
01411 
01412 void Containment::openToolBox()
01413 {
01414     if (d->toolBox && !d->toolBox->showing()) {
01415         d->toolBox->showToolBox();
01416         emit toolBoxVisibilityChanged(true);
01417     }
01418 }
01419 
01420 void Containment::closeToolBox()
01421 {
01422     if (d->toolBox && d->toolBox->showing()) {
01423         d->toolBox->hideToolBox();
01424         emit toolBoxVisibilityChanged(false);
01425     }
01426 }
01427 
01428 void Containment::addAssociatedWidget(QWidget *widget)
01429 {
01430     Applet::addAssociatedWidget(widget);
01431     if (d->focusedApplet) {
01432         d->focusedApplet->addAssociatedWidget(widget);
01433     }
01434 
01435     foreach (const Applet *applet, d->applets) {
01436         if (applet->d->activationAction) {
01437             widget->addAction(applet->d->activationAction);
01438         }
01439     }
01440 }
01441 
01442 void Containment::removeAssociatedWidget(QWidget *widget)
01443 {
01444     Applet::removeAssociatedWidget(widget);
01445     if (d->focusedApplet) {
01446         d->focusedApplet->removeAssociatedWidget(widget);
01447     }
01448 
01449     foreach (const Applet *applet, d->applets) {
01450         if (applet->d->activationAction) {
01451             widget->removeAction(applet->d->activationAction);
01452         }
01453     }
01454 }
01455 
01456 void Containment::setDrawWallpaper(bool drawWallpaper)
01457 {
01458     d->drawWallpaper = drawWallpaper;
01459     if (drawWallpaper) {
01460         KConfigGroup cfg = config();
01461         QString wallpaper = cfg.readEntry("wallpaperplugin", defaultWallpaper);
01462         QString mode = cfg.readEntry("wallpaperpluginmode", defaultWallpaperMode);
01463         setWallpaper(wallpaper, mode);
01464     } else {
01465         delete d->wallpaper;
01466         d->wallpaper = 0;
01467     }
01468 }
01469 
01470 bool Containment::drawWallpaper()
01471 {
01472     return d->drawWallpaper;
01473 }
01474 
01475 void Containment::setWallpaper(const QString &pluginName, const QString &mode)
01476 {
01477     KConfigGroup cfg = config();
01478     bool newPlugin = true;
01479     bool newMode = true;
01480 
01481     if (d->drawWallpaper) {
01482         if (d->wallpaper) {
01483             // we have a wallpaper, so let's decide whether we need to swap it out
01484             if (d->wallpaper->pluginName() != pluginName) {
01485                 delete d->wallpaper;
01486                 d->wallpaper = 0;
01487             } else {
01488                 // it's the same plugin, so let's save its state now so when
01489                 // we call restore later on we're safe
01490                 newMode = d->wallpaper->renderingMode().name() != mode;
01491                 newPlugin = false;
01492             }
01493         }
01494 
01495         if (!pluginName.isEmpty() && !d->wallpaper) {
01496             d->wallpaper = Plasma::Wallpaper::load(pluginName);
01497         }
01498 
01499         if (d->wallpaper) {
01500             d->wallpaper->setParent(this);
01501             d->wallpaper->setBoundingRect(QRectF(QPointF(0, 0), size()));
01502             d->wallpaper->setRenderingMode(mode);
01503 
01504             if (newPlugin) {
01505                 connect(d->wallpaper, SIGNAL(update(const QRectF&)),
01506                         this, SLOT(updateRect(const QRectF&)));
01507                 cfg.writeEntry("wallpaperplugin", pluginName);
01508             }
01509 
01510             if (d->wallpaper->isInitialized()) {
01511                 KConfigGroup wallpaperConfig = KConfigGroup(&cfg, "Wallpaper");
01512                 wallpaperConfig = KConfigGroup(&wallpaperConfig, pluginName);
01513                 d->wallpaper->restore(wallpaperConfig);
01514             }
01515 
01516             if (newMode) {
01517                 cfg.writeEntry("wallpaperpluginmode", mode);
01518             }
01519         }
01520 
01521         update();
01522     }
01523 
01524     if (!d->wallpaper) {
01525         cfg.deleteEntry("wallpaperplugin");
01526         cfg.deleteEntry("wallpaperpluginmode");
01527     }
01528 
01529     if (newPlugin || newMode) {
01530         if (newPlugin && d->wallpaper) {
01531             connect(d->wallpaper, SIGNAL(configureRequested()), this, SLOT(requestConfiguration()));
01532             connect(d->wallpaper, SIGNAL(configNeedsSaving()), this, SIGNAL(configNeedsSaving()));
01533         }
01534 
01535         emit configNeedsSaving();
01536     }
01537 }
01538 
01539 Plasma::Wallpaper *Containment::wallpaper() const
01540 {
01541     return d->wallpaper;
01542 }
01543 
01544 void Containment::setActivity(const QString &activity)
01545 {
01546     Context *context = d->context();
01547     if (context->currentActivity() != activity) {
01548         context->setCurrentActivity(activity);
01549 
01550         foreach (Applet *a, d->applets) {
01551             a->updateConstraints(ContextConstraint);
01552         }
01553 
01554         KConfigGroup c = config();
01555         c.writeEntry("activity", activity);
01556         emit configNeedsSaving();
01557     }
01558 }
01559 
01560 QString Containment::activity() const
01561 {
01562     return d->context()->currentActivity();
01563 }
01564 
01565 Context *ContainmentPrivate::context()
01566 {
01567     if (!con) {
01568         con = new Context(q);
01569         q->connect(con, SIGNAL(changed(Plasma::Context*)),
01570                    q, SIGNAL(contextChanged(Plasma::Context*)));
01571     }
01572 
01573     return con;
01574 }
01575 
01576 KActionCollection* ContainmentPrivate::actions()
01577 {
01578     return static_cast<Applet*>(q)->d->actions;
01579 }
01580 
01581 void ContainmentPrivate::focusApplet(Plasma::Applet *applet)
01582 {
01583     if (focusedApplet == applet) {
01584         return;
01585     }
01586 
01587     QList<QWidget *> widgets = actions()->associatedWidgets();
01588     if (focusedApplet) {
01589         foreach (QWidget *w, widgets) {
01590             focusedApplet->removeAssociatedWidget(w);
01591         }
01592     }
01593 
01594     if (applet && applets.contains(applet)) {
01595         //kDebug() << "switching to" << applet->name();
01596         focusedApplet = applet;
01597         foreach (QWidget *w, widgets) {
01598             focusedApplet->addAssociatedWidget(w);
01599         }
01600 
01601         if (!focusedApplet->hasFocus()) {
01602             focusedApplet->setFocus(Qt::ShortcutFocusReason);
01603         }
01604     } else {
01605         focusedApplet = 0;
01606     }
01607 }
01608 
01609 void Containment::focusNextApplet()
01610 {
01611     if (d->applets.isEmpty()) {
01612         return;
01613     }
01614     int index = d->focusedApplet ? d->applets.indexOf(d->focusedApplet) + 1 : 0;
01615     if (index >= d->applets.size()) {
01616         index = 0;
01617     }
01618     kDebug() << "index" << index;
01619     d->focusApplet(d->applets.at(index));
01620 }
01621 
01622 void Containment::focusPreviousApplet()
01623 {
01624     if (d->applets.isEmpty()) {
01625         return;
01626     }
01627     int index = d->focusedApplet ? d->applets.indexOf(d->focusedApplet) - 1 : -1;
01628     if (index < 0) {
01629         index = d->applets.size() - 1;
01630     }
01631     kDebug() << "index" << index;
01632     d->focusApplet(d->applets.at(index));
01633 }
01634 
01635 void Containment::destroy()
01636 {
01637     destroy(true);
01638 }
01639 
01640 void Containment::showConfigurationInterface()
01641 {
01642     Applet::showConfigurationInterface();
01643 }
01644 
01645 void ContainmentPrivate::requestConfiguration()
01646 {
01647     emit q->configureRequested(q);
01648 }
01649 
01650 void Containment::destroy(bool confirm)
01651 {
01652     if (immutability() != Mutable || Applet::d->transient) {
01653         return;
01654     }
01655 
01656     if (isContainment()) {
01657         //don't remove a desktop that's in use
01658         //FIXME: this should probably be based on whether any views care or not!
01659         //       sth like: foreach (view) { view->requires(this); }
01660         Q_ASSERT(corona());
01661         if (d->type != PanelContainment && d->type != CustomPanelContainment &&
01662             (d->screen != -1 || d->screen >= corona()->numScreens())) {
01663             kDebug() << (QObject*)this << "containment has a screen number?" << d->screen;
01664             return;
01665         }
01666 
01667         //FIXME maybe that %1 should be the containment type not the name
01668         if (!confirm ||
01669             KMessageBox::warningContinueCancel(
01670                 view(),
01671                 i18nc("%1 is the name of the containment", "Do you really want to remove this %1?", name()),
01672                 i18nc("@title:window %1 is the name of the containment", "Remove %1", name()), KStandardGuiItem::remove()) == KMessageBox::Continue) {
01673             //clearApplets();
01674             Applet::destroy();
01675         }
01676     } else {
01677         Applet::destroy();
01678     }
01679 }
01680 
01681 void ContainmentPrivate::zoomIn()
01682 {
01683     emit q->zoomRequested(q, Plasma::ZoomIn);
01684     positionToolBox();
01685 }
01686 
01687 void ContainmentPrivate::zoomOut()
01688 {
01689     emit q->zoomRequested(q, Plasma::ZoomOut);
01690     positionToolBox();
01691 }
01692 
01693 ToolBox *ContainmentPrivate::createToolBox()
01694 {
01695     if (!toolBox) {
01696         switch (type) {
01697         case Containment::PanelContainment:
01698         case Containment::CustomPanelContainment:
01699             toolBox = new PanelToolBox(q);
01700             toolBox->setSize(KIconLoader::SizeSmallMedium);
01701             toolBox->setIconSize(QSize(KIconLoader::SizeSmall, KIconLoader::SizeSmall));
01702             if (q->immutability() != Mutable) {
01703                 toolBox->hide();
01704             }
01705             break;
01706         default:
01707             toolBox = new DesktopToolBox(q);
01708             toolBox->setSize(KIconLoader::SizeSmallMedium);
01709             toolBox->setIconSize(QSize(KIconLoader::SizeSmall, KIconLoader::SizeSmall));
01710             break;
01711         }
01712 
01713         if (toolBox) {
01714             QObject::connect(toolBox, SIGNAL(toggled()), q, SIGNAL(toolBoxToggled()));
01715             QObject::connect(toolBox, SIGNAL(toggled()), q, SLOT(updateToolBoxVisibility()));
01716             toolBox->load();
01717             positionToolBox();
01718         }
01719     }
01720 
01721     return toolBox;
01722 }
01723 
01724 void ContainmentPrivate::positionToolBox()
01725 {
01726     if (toolBox) {
01727         toolBox->reposition();
01728     }
01729 }
01730 
01731 void ContainmentPrivate::updateToolBoxVisibility()
01732 {
01733     emit q->toolBoxVisibilityChanged(toolBox->showing());
01734 }
01735 
01736 void ContainmentPrivate::triggerShowAddWidgets()
01737 {
01738     emit q->showAddWidgetsInterface(QPointF());
01739 }
01740 
01741 void ContainmentPrivate::handleDisappeared(AppletHandle *handle)
01742 {
01743     if (handles.contains(handle->applet())) {
01744         handles.remove(handle->applet());
01745         handle->detachApplet();
01746         if (q->scene()) {
01747             q->scene()->removeItem(handle);
01748         }
01749         handle->deleteLater();
01750     }
01751 }
01752 
01753 void ContainmentPrivate::checkRemoveAction()
01754 {
01755     q->enableAction("remove", (q->immutability() == Mutable &&
01756                               (screen == -1 ||
01757                                type == Plasma::Containment::PanelContainment ||
01758                                type == Plasma::Containment::CustomPanelContainment)));
01759 }
01760 
01761 void ContainmentPrivate::containmentConstraintsEvent(Plasma::Constraints constraints)
01762 {
01763     if (!q->isContainment()) {
01764         return;
01765     }
01766 
01767     //kDebug() << "got containmentConstraintsEvent" << constraints << (QObject*)toolBox;
01768     if (constraints & Plasma::ImmutableConstraint) {
01769         //update actions
01770         checkRemoveAction();
01771         bool unlocked = q->immutability() == Mutable;
01772         q->setAcceptDrops(unlocked);
01773         q->enableAction("add widgets", unlocked);
01774 
01775         // tell the applets too
01776         foreach (Applet *a, applets) {
01777             a->updateConstraints(ImmutableConstraint);
01778         }
01779 
01780         if (toolBox) {
01781             if (type == Containment::PanelContainment || type == Containment::CustomPanelContainment) {
01782                 toolBox->setVisible(unlocked);
01783             } else {
01784                 toolBox->setIsMovable(unlocked);
01785             }
01786         }
01787 
01788         //clear handles on lock
01789         if (!unlocked) {
01790             QMap<Applet*, AppletHandle*> h = handles;
01791             handles.clear();
01792 
01793             foreach (AppletHandle *handle, h) {
01794                 handle->disconnect(q);
01795 
01796                 if (q->scene()) {
01797                     q->scene()->removeItem(handle);
01798                 }
01799 
01800                 handle->deleteLater();
01801             }
01802         }
01803     }
01804 
01805     if (constraints & Plasma::FormFactorConstraint) {
01806         foreach (Applet *applet, applets) {
01807             applet->updateConstraints(Plasma::FormFactorConstraint);
01808         }
01809     }
01810 
01811     if (toolBox && (constraints & Plasma::SizeConstraint ||
01812                     constraints & Plasma::FormFactorConstraint ||
01813                     constraints & Plasma::ScreenConstraint ||
01814                     constraints & Plasma::StartupCompletedConstraint)) {
01815         //kDebug() << "Positioning toolbox";
01816         positionToolBox();
01817     }
01818 
01819     if (toolBox &&
01820         constraints & Plasma::StartupCompletedConstraint &&
01821         type < Containment::CustomContainment) {
01822         toolBox->addTool(q->action("remove"));
01823         checkRemoveAction();
01824     }
01825 }
01826 
01827 Applet *ContainmentPrivate::addApplet(const QString &name, const QVariantList &args,
01828                                       const QRectF &appletGeometry, uint id, bool delayInit)
01829 {
01830     if (!q->isContainment()) {
01831         return 0;
01832     }
01833 
01834     if (!delayInit && q->immutability() != Mutable) {
01835         kDebug() << "addApplet for" << name << "requested, but we're currently immutable!";
01836         return 0;
01837     }
01838 
01839     QGraphicsView *v = q->view();
01840     if (v) {
01841         v->setCursor(Qt::BusyCursor);
01842     }
01843 
01844     Applet *applet = Applet::load(name, id, args);
01845     if (v) {
01846         v->unsetCursor();
01847     }
01848 
01849     if (!applet) {
01850         kDebug() << "Applet" << name << "could not be loaded.";
01851         applet = new Applet(0, QString(), id);
01852         applet->setFailedToLaunch(true, i18n("Could not find requested component: %1", name));
01853     }
01854 
01855     //kDebug() << applet->name() << "sizehint:" << applet->sizeHint() << "geometry:" << applet->geometry();
01856 
01857     q->addApplet(applet, appletGeometry.topLeft(), delayInit);
01858     return applet;
01859 }
01860 
01861 bool ContainmentPrivate::regionIsEmpty(const QRectF &region, Applet *ignoredApplet) const
01862 {
01863     foreach (Applet *applet, applets) {
01864         if (applet != ignoredApplet && applet->geometry().intersects(region)) {
01865             return false;
01866         }
01867     }
01868     return true;
01869 }
01870 
01871 void ContainmentPrivate::appletDestroyed(Plasma::Applet *applet)
01872 {
01873     applets.removeAll(applet);
01874     if (focusedApplet == applet) {
01875         focusedApplet = 0;
01876     }
01877 
01878     if (handles.contains(applet)) {
01879         AppletHandle *handle = handles.value(applet);
01880         handles.remove(applet);
01881         if (q->scene()) {
01882             q->scene()->removeItem(handle);
01883         }
01884         handle->deleteLater();
01885     }
01886 
01887     emit q->appletRemoved(applet);
01888     emit q->configNeedsSaving();
01889 }
01890 
01891 void ContainmentPrivate::containmentAppletAnimationComplete(QGraphicsItem *item, Plasma::Animator::Animation anim)
01892 {
01893     if (anim == Animator::AppearAnimation &&
01894         item->parentItem() == q) {
01895         Applet *applet = qgraphicsitem_cast<Applet*>(item);
01896 
01897         if (applet) {
01898             if (type == Containment::DesktopContainment) {
01899                 applet->installSceneEventFilter(q);
01900             }
01901 
01902             KConfigGroup *cg = applet->d->mainConfigGroup();
01903             applet->save(*cg);
01904             emit q->configNeedsSaving();
01905             //applet->setWindowFlags(Qt::Window);
01906         }
01907     }
01908 }
01909 
01910 bool containmentSortByPosition(const Containment *c1, const Containment *c2)
01911 {
01912     return c1->id() < c2->id();
01913 }
01914 
01915 void ContainmentPrivate::positionContainments()
01916 {
01917     Corona *c = q->corona();
01918     if (!c || ContainmentPrivate::s_positioning) {
01919         return;
01920     }
01921 
01922     ContainmentPrivate::s_positioning = true;
01923 
01924     //TODO: we should avoid running this too often; consider compressing requests
01925     //      with a timer.
01926     QList<Containment*> containments = c->containments();
01927     QMutableListIterator<Containment*> it(containments);
01928 
01929     while (it.hasNext()) {
01930         Containment *containment = it.next();
01931         if (containment->d->type == Containment::PanelContainment ||
01932             containment->d->type == Containment::CustomPanelContainment ||
01933             q->corona()->offscreenWidgets().contains(containment)) {
01934             // weed out all containments we don't care about at all
01935             // e.g. Panels and ourself
01936             it.remove();
01937             continue;
01938         }
01939     }
01940 
01941     if (containments.isEmpty()) {
01942         ContainmentPrivate::s_positioning = false;
01943         return;
01944     }
01945 
01946     qSort(containments.begin(), containments.end(), containmentSortByPosition);
01947     it.toFront();
01948 
01949     int column = 0;
01950     int x = 0;
01951     int y = 0;
01952     int rowHeight = 0;
01953     //int count = 0;
01954 
01955     //kDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++" << containments.count();
01956     while (it.hasNext()) {
01957         Containment *containment = it.next();
01958         containment->setPos(x, y);
01959         //kDebug() << ++count << "setting to" << x << y;
01960 
01961         int height = containment->size().height();
01962         if (height > rowHeight) {
01963             rowHeight = height;
01964         }
01965 
01966         ++column;
01967 
01968         if (column == CONTAINMENT_COLUMNS) {
01969             column = 0;
01970             x = 0;
01971             y += rowHeight + INTER_CONTAINMENT_MARGIN + TOOLBOX_MARGIN;
01972             rowHeight = 0;
01973         } else {
01974             x += containment->size().width() + INTER_CONTAINMENT_MARGIN;
01975         }
01976         //kDebug() << "column: " << column << "; x " << x << "; y" << y << "; width was"
01977         //         << containment->size().width();
01978     }
01979     //kDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++";
01980 
01981     ContainmentPrivate::s_positioning = false;
01982 }
01983 
01984 void ContainmentPrivate::positionPanel(bool force)
01985 {
01986     if (!q->scene()) {
01987         kDebug() << "no scene yet";
01988         return;
01989     }
01990 
01991     // we position panels in negative coordinates, and stack all horizontal
01992     // and all vertical panels with each other.
01993 
01994 
01995     const QPointF p = q->pos();
01996 
01997     if (!force &&
01998         p.y() + q->size().height() < -INTER_CONTAINMENT_MARGIN &&
01999         q->scene()->collidingItems(q).isEmpty()) {
02000         // already positioned and not running into any other panels
02001         return;
02002     }
02003 
02004     //TODO: research how non-Horizontal, non-Vertical (e.g. Planar) panels behave here
02005     bool horiz = formFactor == Plasma::Horizontal;
02006     qreal bottom = horiz ? 0 : VERTICAL_STACKING_OFFSET;
02007     qreal lastHeight = 0;
02008 
02009     // this should be ok for small numbers of panels, but if we ever end
02010     // up managing hundreds of them, this simplistic alogrithm will
02011     // likely be too slow.
02012     foreach (const Containment *other, q->corona()->containments()) {
02013         if (other == q ||
02014             (other->d->type != Containment::PanelContainment &&
02015              other->d->type != Containment::CustomPanelContainment) ||
02016             horiz != (other->formFactor() == Plasma::Horizontal)) {
02017             // only line up with panels of the same orientation
02018             continue;
02019         }
02020 
02021         if (horiz) {
02022             qreal y = other->pos().y();
02023             if (y < bottom) {
02024                 lastHeight = other->size().height();
02025                 bottom = y;
02026             }
02027         } else {
02028             qreal width = other->size().width();
02029             qreal x = other->pos().x() + width;
02030             if (x > bottom) {
02031                 lastHeight = width;
02032                 bottom = x + lastHeight;
02033             }
02034         }
02035     }
02036 
02037     kDebug() << "positioning" << (horiz ? "" : "non-") << "horizontal panel; forced?" << force;
02038     // give a space equal to the height again of the last item so there is
02039     // room to grow.
02040     QPointF newPos;
02041     if (horiz) {
02042         bottom -= lastHeight + INTER_CONTAINMENT_MARGIN;
02043         //TODO: fix x position for non-flush-left panels
02044         kDebug() << "moved to" << QPointF(0, bottom - q->size().height());
02045         newPos = QPointF(0, bottom - q->size().height());
02046     } else {
02047         bottom += lastHeight + INTER_CONTAINMENT_MARGIN;
02048         //TODO: fix y position for non-flush-top panels
02049         kDebug() << "moved to" << QPointF(bottom + q->size().width(), -INTER_CONTAINMENT_MARGIN - q->size().height());
02050         newPos = QPointF(bottom + q->size().width(), -INTER_CONTAINMENT_MARGIN - q->size().height());
02051     }
02052 
02053     if (p != newPos) {
02054         ContainmentPrivate::s_positioning = true;
02055         q->setPos(newPos);
02056         ContainmentPrivate::s_positioning = false;
02057     }
02058 }
02059 
02060 } // Plasma namespace
02061 
02062 #include "containment.moc"
02063 

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
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
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