24#include "private/corona_p.h"
26#include <QApplication>
27#include <QDesktopWidget>
28#include <QGraphicsView>
29#include <QGraphicsSceneDragDropEvent>
30#include <QGraphicsGridLayout>
38#include <kauthorized.h>
43#include <kshortcutsdialog.h>
44#include <kwindowsystem.h>
51#include "private/animator_p.h"
52#include "private/applet_p.h"
53#include "private/containment_p.h"
62bool CoronaPrivate::s_positioningContainments =
false;
68 kDebug() <<
"!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) <<
"Corona ctor start";
76 KConfigGroup trans(KGlobal::config(),
"PlasmaTransientsConfig");
102 d->defaultContainmentPlugin = name;
107 return d->defaultContainmentPlugin;
114 if (configName.isEmpty() || configName == d->configName) {
117 c = KSharedConfig::openConfig(configName, KConfig::SimpleConfig);
125 foreach (
const QString &group,
config.groupList()) {
126 KConfigGroup cg(&
config, group);
134 KConfigGroup dest(&
config,
"Containments");
138 c->
config().reparent(&dest);
151 d->immutability = oldImm;
160 static const int CONFIG_SYNC_TIMEOUT = 10000;
169 if (!d->configSyncTimer.isActive()) {
170 d->configSyncTimer.start(CONFIG_SYNC_TIMEOUT);
184 if (d->containments.isEmpty()) {
186 if (!d->containments.isEmpty()) {
191 if (
config()->isImmutable() ||
192 !KAuthorized::authorize(
"plasma/" + KGlobal::mainComponent().aboutData()->appName() +
193 "/unlockedDesktop")) {
196 KConfigGroup coronaConfig(
config(),
"General");
203 return c1->
id() < c2->
id();
208 if (CoronaPrivate::s_positioningContainments) {
212 CoronaPrivate::s_positioningContainments =
true;
217 QMutableListIterator<Containment*> it(c);
219 while (it.hasNext()) {
234 CoronaPrivate::s_positioningContainments =
false;
244 while (it.hasNext()) {
246 containment->setPos(x, y);
249 int height = containment->size().height();
250 if (height > rowHeight) {
256 if (column == CONTAINMENT_COLUMNS) {
259 y += rowHeight + INTER_CONTAINMENT_MARGIN + TOOLBOX_MARGIN;
262 x += containment->size().width() + INTER_CONTAINMENT_MARGIN;
268 CoronaPrivate::s_positioningContainments =
false;
274 if (!configName.isEmpty() && configName != d->configName) {
277 d->configName = configName;
280 KSharedConfigPtr conf =
config();
281 d->importLayout(*conf,
false);
286 return d->importLayout(conf,
true);
289#ifndef KDE_NO_DEPRECATED
292 return d->importLayout(conf,
true);
298 foreach (
Containment *containment, d->containments) {
299 if (containment->
screen() == screen &&
300 (desktop < 0 || containment->desktop() == desktop) &&
311 const QString &defaultPluginIfNonExistent,
const QVariantList &defaultArgs)
314 if (!containment && !defaultPluginIfNonExistent.isEmpty()) {
317 desktop >= -1 && desktop < KWindowSystem::numberOfDesktops()) {
318 containment = d->addContainment(defaultPluginIfNonExistent, defaultArgs, 0,
false);
330 return d->containments;
335 foreach (
Containment *containment, d->containments) {
343 d->config = KSharedConfig::openConfig(d->configName, KConfig::SimpleConfig);
351 if (d->immutability ==
Mutable) {
352 return d->addContainment(name, args, 0,
false);
360 if (d->immutability ==
Mutable) {
361 return d->addContainment(name, args, 0,
true);
369 AnimatorPrivate::mapAnimation(from, to);
374 AnimatorPrivate::mapAnimation(from, to);
381 kDebug() <<
"widget is already an offscreen widget!";
389 while (d->offscreenWidgets.contains(i)) {
393 d->offscreenWidgets[i] = widget;
394#if defined(arm) || defined(__arm__)
395 widget->setPos((-i - 1) * 2000, -2000);
397 widget->setPos((-i - 1) * QWIDGETSIZE_MAX, -QWIDGETSIZE_MAX);
401 widget->setParentItem(0);
403 widget->setParent(pw);
407 if (!widget->scene()) {
411 connect(widget, SIGNAL(destroyed(
QObject*)),
this, SLOT(offscreenWidgetDestroyed(
QObject*)));
416 QMutableHashIterator<uint, QGraphicsWidget *> it(d->offscreenWidgets);
418 while (it.hasNext()) {
419 if (it.next().value() == widget) {
428 return d->offscreenWidgets.values();
431void CoronaPrivate::offscreenWidgetDestroyed(
QObject *o)
437 q->removeOffscreenWidget(widget);
450 QRect r = sceneRect().toRect();
451 r.moveTo(v->mapToGlobal(QPoint(0, 0)));
455 return sceneRect().toRect();
473 const QGraphicsItem *actualItem = item;
483 if (!v->isVisible()) {
484 actualItem = item->parentItem();
486 const QGraphicsWidget *widget = qgraphicsitem_cast<const QGraphicsWidget*>(item);
488 actualItem = qobject_cast<QGraphicsItem*>(widget->parent());
507 QTransform sceneTransform = actualItem->sceneTransform();
510 if (QApplication::isRightToLeft() && alignment != Qt::AlignCenter) {
511 if (alignment == Qt::AlignRight) {
512 alignment = Qt::AlignLeft;
514 alignment = Qt::AlignRight;
519 if (sceneTransform.isRotating()) {
520 qreal angle = acos(sceneTransform.m11());
521 QTransform newTransform;
522 QPointF center = actualItem->sceneBoundingRect().center();
524 newTransform.translate(center.x(), center.y());
525 newTransform.rotateRadians(-angle);
526 newTransform.translate(-center.x(), -center.y());
527 pos = v->mapFromScene(newTransform.inverted().map(actualItem->scenePos()));
529 pos = v->mapFromScene(actualItem->scenePos());
532 pos = v->mapToGlobal(pos);
534 const Plasma::View *pv = qobject_cast<const Plasma::View *>(v);
544 if (alignment == Qt::AlignCenter) {
545 pos.setX(pos.x() + actualItem->boundingRect().width()/2 - s.width()/2);
546 }
else if (alignment == Qt::AlignRight) {
547 pos.setX(pos.x() + actualItem->boundingRect().width() - s.width());
550 if (pos.x() + s.width() > v->geometry().x() + v->geometry().width()) {
551 pos.setX((v->geometry().x() + v->geometry().width()) - s.width());
553 pos.setX(qMax(pos.x(), v->geometry().left()));
559 if (alignment == Qt::AlignCenter) {
560 pos.setY(pos.y() + actualItem->boundingRect().height()/2 - s.height()/2);
561 }
else if (alignment == Qt::AlignRight) {
562 pos.setY(pos.y() + actualItem->boundingRect().height() - s.height());
565 if (pos.y() + s.height() > v->geometry().y() + v->geometry().height()) {
566 pos.setY((v->geometry().y() + v->geometry().height()) - s.height());
568 pos.setY(qMax(pos.y(), v->geometry().top()));
573 if (alignment == Qt::AlignCenter) {
574 pos.setX(pos.x() + actualItem->boundingRect().width()/2 - s.width()/2);
575 }
else if (alignment == Qt::AlignRight) {
576 pos.setX(pos.x() + actualItem->boundingRect().width() - s.width());
590 screen = QApplication::desktop()->screenNumber(v);
598 pos.setY(v->geometry().y() - s.height());
601 pos.setY(v->geometry().y() + v->geometry().height());
604 pos.setX(v->geometry().x() + v->geometry().width());
607 pos.setX(v->geometry().x() - s.width());
610 if (pos.y() - s.height() > screenRect.top()) {
611 pos.ry() = pos.y() - s.height();
613 pos.ry() = pos.y() + (int)actualItem->boundingRect().size().height() + 1;
619 if (loc !=
LeftEdge && pos.x() + s.width() > screenRect.x() + screenRect.width()) {
620 pos.rx() -= ((pos.x() + s.width()) - (screenRect.x() + screenRect.width()));
623 if (loc !=
TopEdge && pos.y() + s.height() > screenRect.y() + screenRect.height()) {
624 pos.ry() -= ((pos.y() + s.height()) - (screenRect.y() + screenRect.height()));
627 pos.rx() = qMax(0, pos.x());
628 pos.ry() = qMax(0, pos.y());
638 d->toolBoxPlugins[
type] = plugin;
644 return d->toolBoxPlugins.value(
type);
649 QGraphicsScene::dragEnterEvent(event);
654 QGraphicsScene::dragLeaveEvent(event);
659 QGraphicsScene::dragMoveEvent(event);
664 return d->immutability;
669 if (d->immutability == immutable || d->immutability ==
SystemImmutable) {
673 kDebug() <<
"setting immutability to" << immutable;
674 d->immutability = immutable;
675 d->updateContainmentImmutability();
680 QAction *
action = d->actions.action(
"lock widgets");
683 action->setEnabled(
false);
684 action->setVisible(
false);
686 bool unlocked = d->immutability ==
Mutable;
687 action->setText(unlocked ? i18n(
"Lock Widgets") : i18n(
"Unlock Widgets"));
688 action->setIcon(KIcon(unlocked ?
"object-locked" :
"object-unlocked"));
695 KConfigGroup cg(
config(),
"General");
699 cg.writeEntry(
"immutability", (
int)d->immutability);
711 if (containment->
screen() == screen &&
722 return d->actions.action(name);
727 d->actions.addAction(name,
action);
732 return d->actions.addAction(name);
737 return d->actions.actions();
742 QAction *
action = d->actions.action(name);
744 action->setEnabled(enable);
745 action->setVisible(enable);
751 QMutableListIterator<QWeakPointer<KActionCollection> > it(d->actionCollections);
752 while (it.hasNext()) {
754 KActionCollection *collection = it.value().data();
761 collection->readSettings();
762 if (d->shortcutsDlg) {
763 d->shortcutsDlg.data()->addCollection(collection);
770 d->actionCollections << newShortcuts;
771 if (d->shortcutsDlg) {
772 d->shortcutsDlg.data()->addCollection(newShortcuts);
778 d->containmentActionsDefaults.insert(containmentType,
config);
783 return d->containmentActionsDefaults.value(containmentType);
793 return d->dialogManager.data();
796CoronaPrivate::CoronaPrivate(
Corona *corona)
799 mimetype(
"text/x-plasmoidservicename"),
800 defaultContainmentPlugin(
"desktop"),
804 if (KGlobal::hasMainComponent()) {
805 configName = KGlobal::mainComponent().componentName() +
"-appletsrc";
807 configName =
"plasma-appletsrc";
811CoronaPrivate::~CoronaPrivate()
813 qDeleteAll(containments);
816void CoronaPrivate::init()
818 q->setStickyFocus(
true);
819 configSyncTimer.setSingleShot(
true);
820 QObject::connect(&configSyncTimer, SIGNAL(timeout()), q, SLOT(syncConfig()));
823 actions.setConfigGroup(
"Shortcuts");
825 KAction *lockAction = actions.addAction(
"lock widgets");
826 QObject::connect(lockAction, SIGNAL(triggered(
bool)), q, SLOT(toggleImmutability()));
827 lockAction->setText(i18n(
"Lock Widgets"));
828 lockAction->setAutoRepeat(
true);
829 lockAction->setIcon(KIcon(
"object-locked"));
831 lockAction->setShortcut(KShortcut(
"alt+d, l"));
832 lockAction->setShortcutContext(Qt::ApplicationShortcut);
837 KAction *action = actions.addAction(
"configure shortcuts");
838 QObject::connect(action, SIGNAL(triggered()), q, SLOT(showShortcutConfig()));
839 action->setText(i18n(
"Shortcut Settings"));
840 action->setIcon(KIcon(
"configure-shortcuts"));
841 action->setAutoRepeat(
false);
844 action->setShortcutContext(Qt::ApplicationShortcut);
847 KActionCollection *containmentActions = AppletPrivate::defaultActions(q);
848 ContainmentPrivate::addDefaultActions(containmentActions);
849 actionCollections << &actions << AppletPrivate::defaultActions(q) << containmentActions;
850 q->updateShortcuts();
853void CoronaPrivate::showShortcutConfig()
856 KShortcutsDialog *dlg = shortcutsDlg.data();
858 dlg =
new KShortcutsDialog();
859 dlg->setModal(
false);
860 dlg->setAttribute(Qt::WA_DeleteOnClose,
true);
861 QObject::connect(dlg, SIGNAL(saved()), q, SIGNAL(shortcutsChanged()));
863 dlg->addCollection(&actions);
864 QMutableListIterator<QWeakPointer<KActionCollection> > it(actionCollections);
865 while (it.hasNext()) {
867 KActionCollection *collection = it.value().data();
874 dlg->addCollection(collection);
878 KWindowSystem::setOnDesktop(dlg->winId(), KWindowSystem::currentDesktop());
883void CoronaPrivate::toggleImmutability()
892void CoronaPrivate::saveLayout(KSharedConfigPtr cg)
const
894 KConfigGroup containmentsGroup(cg,
"Containments");
895 foreach (
const Containment *containment, containments) {
896 QString cid = QString::number(containment->
id());
897 KConfigGroup containmentConfig(&containmentsGroup, cid);
898 containment->
save(containmentConfig);
902void CoronaPrivate::updateContainmentImmutability()
910void CoronaPrivate::containmentDestroyed(QObject *obj)
916 Containment* containment =
static_cast<Plasma::Containment*
>(obj);
917 int index = containments.indexOf(containment);
920 containments.removeAt(index);
921 q->requestConfigSync();
925void CoronaPrivate::syncConfig()
928 emit q->configSynced();
931Containment *CoronaPrivate::addContainment(
const QString &name,
const QVariantList &args, uint
id,
bool delayedInit)
933 QString pluginName = name;
939 if (pluginName.isEmpty() || pluginName ==
"default") {
941 pluginName = defaultContainmentPlugin;
944 bool loadingNull = pluginName ==
"null";
952 kDebug() <<
"loading of containment" << name <<
"failed.";
962 q->removeItem(applet);
980 KConfigGroup conf(q->config(),
"Containments");
981 conf = KConfigGroup(&conf, QString::number(containment->
id()));
985 applet->d->isContainment =
true;
986 containment->setPos(containment->d->preferredPos(q));
987 q->addItem(containment);
988 applet->d->setIsContainment(
true,
true);
989 containments.append(containment);
993 KConfigGroup cg = containment->
config();
996 containment->
save(cg);
997 q->requestConfigSync();
1001 QObject::connect(containment, SIGNAL(destroyed(QObject*)),
1002 q, SLOT(containmentDestroyed(QObject*)));
1003 QObject::connect(containment, SIGNAL(configNeedsSaving()),
1004 q, SLOT(requestConfigSync()));
1005 QObject::connect(containment, SIGNAL(releaseVisualFocus()),
1006 q, SIGNAL(releaseVisualFocus()));
1007 QObject::connect(containment, SIGNAL(screenChanged(
int,
int,Plasma::Containment*)),
1008 q, SIGNAL(screenOwnerChanged(
int,
int,Plasma::Containment*)));
1011 emit q->containmentAdded(containment);
1017QList<Plasma::Containment *> CoronaPrivate::importLayout(
const KConfigBase &conf,
bool mergeConfig)
1019 if (
const KConfigGroup *group =
dynamic_cast<const KConfigGroup *
>(&conf)) {
1020 if (!group->isValid()) {
1021 return QList<Containment *>();
1025 QList<Plasma::Containment *> newContainments;
1026 QSet<uint> containmentsIds;
1028 foreach (
Containment *containment, containments) {
1029 containmentsIds.insert(containment->
id());
1032 KConfigGroup containmentsGroup(&conf,
"Containments");
1034 foreach (
const QString &group, containmentsGroup.groupList()) {
1035 KConfigGroup containmentConfig(&containmentsGroup, group);
1037 if (containmentConfig.entryMap().isEmpty()) {
1041 uint cid = group.toUInt();
1042 if (containmentsIds.contains(cid)) {
1043 cid = ++AppletPrivate::s_maxAppletId;
1044 }
else if (cid > AppletPrivate::s_maxAppletId) {
1045 AppletPrivate::s_maxAppletId = cid;
1049 KConfigGroup realConf(q->config(),
"Containments");
1050 realConf = KConfigGroup(&realConf, QString::number(cid));
1052 realConf.deleteGroup();
1053 containmentConfig.copyTo(&realConf);
1057 kDebug() <<
"!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) <<
"Adding Containment" << containmentConfig.readEntry(
"plugin", QString());
1058 Containment *c = addContainment(containmentConfig.readEntry(
"plugin", QString()), QVariantList(), cid,
true);
1063 newContainments.append(c);
1064 containmentsIds.insert(c->
id());
1067 kDebug() <<
"!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) <<
"Init Containment" << c->
pluginName();
1068 c->
restore(containmentConfig);
1069 kDebug() <<
"!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) <<
"Restored Containment" << c->
pluginName();
1072 foreach (
Containment *containment, newContainments) {
1074 containment->d->initApplets();
1075 emit q->containmentAdded(containment);
1076 kDebug() <<
"!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) <<
"Containment" << containment->
name();
1079 return newContainments;
1084#include "corona.moc"
The AbstractDialogManager class shows the dialogs shown by applets and the rest of the shell.
static Applet * load(const QString &name, uint appletId=0, const QVariantList &args=QVariantList())
Attempts to load an applet.
KConfigGroup config() const
Returns the KConfigGroup to access the applets configuration.
ImmutabilityType immutability
virtual void init()
This method is called once the applet is loaded and added to a Corona.
virtual Location location() const
Returns the location of the scene which is displaying applet.
void updateConstraints(Plasma::Constraints constraints=Plasma::AllConstraints)
Called when any of the geometry constraints have been updated.
void flushPendingConstraintsEvents()
Sends all pending contraints updates to the applet.
void setFailedToLaunch(bool failed, const QString &reason=QString())
Call this method when the applet fails to launch properly.
A class that holds a map of triggers to plugin names.
The base class for plugins that provide backgrounds and applet grouping containers.
void clearApplets()
Removes all applets from this Containment.
void setFormFactor(Plasma::FormFactor formFactor)
Sets the form factor for this Containment.
void destroy()
Destroys this containment and all its applets (after a confirmation dialog); it will be removed nicel...
@ CustomPanelContainment
A customized desktop panel.
@ DesktopContainment
A desktop containment.
@ PanelContainment
A desktop panel.
@ CustomContainment
A containment that is neither a desktop nor a panel but something application specific.
void setScreen(int screen, int desktop=-1)
Sets the physical screen this Containment is associated with.
void save(KConfigGroup &group) const
void setDrawWallpaper(bool drawWallpaper)
Sets whether wallpaper is painted or not.
Applet::List applets() const
void init()
Reimplemented from Applet.
void restore(KConfigGroup &group)
Type containmentType() const
Returns the type of containment.
A QGraphicsScene for Plasma::Applets.
void setDialogManager(AbstractDialogManager *manager)
virtual int numScreens() const
Returns the number of screens available to plasma.
void setContainmentActionsDefaults(Containment::Type containmentType, const ContainmentActionsPluginsConfig &config)
QAction * action(QString name) const
Returns the QAction with the given name from our collection.
QList< QGraphicsWidget * > offscreenWidgets() const
void immutabilityChanged(Plasma::ImmutabilityType immutability)
emitted when immutability changes.
virtual void loadDefaultLayout()
Loads the default (system wide) layout for this user.
void layoutContainments()
void requestConfigSync()
Schedules a flush-to-disk synchronization of the configuration state at the next convenient moment.
void setAppletMimeType(const QString &mimetype)
Sets the mimetype of Drag/Drop items.
QString preferredToolBoxPlugin(const Containment::Type type) const
Returns the name of the preferred plugin to be used as containment toolboxes.
void setImmutability(const ImmutabilityType immutable)
Sets the immutability type for this Corona (not immutable, user immutable or system immutable)
void initializeLayout(const QString &config=QString())
Initializes the layout from a config file.
void dragMoveEvent(QGraphicsSceneDragDropEvent *event)
Containment * addContainment(const QString &name, const QVariantList &args=QVariantList())
Adds a Containment to the Corona.
void exportLayout(KConfigGroup &config, QList< Containment * > containments)
Exports a set of containments to a config file.
void clearContainments()
Clear the Corona from all applets.
void removeOffscreenWidget(QGraphicsWidget *widget)
Removes a widget from the topleft quadrant in the scene.
void loadLayout(const QString &config=QString())
Load applet layout from a config file.
void setPreferredToolBoxPlugin(const Containment::Type type, const QString &plugin)
void dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
QPoint popupPosition(const QGraphicsItem *item, const QSize &size)
Recommended position for a popup window like a menu or a tooltip given its size.
virtual QRegion availableScreenRegion(int id) const
Returns the available region for a given screen.
QList< Containment * > containments() const
Containment * addContainmentDelayed(const QString &name, const QVariantList &args=QVariantList())
Loads a containment with delayed initialization, primarily useful for implementations of loadDefaultL...
void addAction(QString name, QAction *action)
Adds the action to our collection under the given name.
void mapAnimation(Animator::Animation from, Animator::Animation to)
Maps a stock animation to one of the semantic animations.
ImmutabilityType immutability() const
QList< QAction * > actions() const
Returns all the actions in our collection.
QList< Plasma::Containment * > importLayout(const KConfigBase &config)
Imports an applet layout from a config file.
KSharedConfig::Ptr config() const
Returns the config file used to store the configuration for this Corona.
Corona(QObject *parent=0)
void setDefaultContainmentPlugin(const QString &name)
Sets the default containment plugin to try and load.
void requireConfigSync()
Schedules a time sensitive flush-to-disk synchronization of the configuration state.
QString appletMimeType()
The current mime type of Drag/Drop items.
virtual QRect screenGeometry(int id) const
Returns the geometry of a given screen.
void addShortcuts(KActionCollection *newShortcuts)
QString defaultContainmentPlugin() const
AbstractDialogManager * dialogManager()
friend class CoronaPrivate
ContainmentActionsPluginsConfig containmentActionsDefaults(Containment::Type containmentType)
void enableAction(const QString &name, bool enable)
convenience function - enables or disables an action by name
QList< Plasma::Location > freeEdges(int screen) const
This method is useful in order to retrieve the list of available screen edges for panel type containm...
Containment * containmentForScreen(int screen, int desktop=-1) const
Returns the Containment, if any, for a given physical screen and desktop.
void addOffscreenWidget(QGraphicsWidget *widget)
Adds a widget in the topleft quadrant in the scene.
void dragEnterEvent(QGraphicsSceneDragDropEvent *event)
void saveLayout(const QString &config=QString()) const
Save applets layout to file.
A QGraphicsView for a single Containment.
Containment * containment() const
int screen() const
Returns the screen this view is associated with.
Namespace for everything in libplasma.
ImmutabilityType
Defines the immutability of items like applets, corona and containments they can be free to modify,...
@ Mutable
The item can be modified in any way.
@ SystemImmutable
the item is locked down by the system, the user can't unlock it
@ UserImmutable
The user has requested a lock down, and can undo the lock down at any time.
QGraphicsView * viewFor(const QGraphicsItem *item)
Returns the most appropriate QGraphicsView for the item.
Location
The Location enumeration describes where on screen an element, such as an Applet or its managing cont...
@ LeftEdge
Along the left side of the screen.
@ TopEdge
Along the top of the screen.
@ RightEdge
Along the right side of the screen.
@ BottomEdge
Along the bottom of the screen.
bool containmentSortByPosition(const Containment *c1, const Containment *c2)
static QScriptValue type(QScriptContext *ctx, QScriptEngine *eng)
@ StartupCompletedConstraint
application startup has completed
@ ImmutableConstraint
the immutability (locked) nature of the applet changed
@ Planar
The applet lives in a plane and has two degrees of freedom to grow.