plasma-framework/corona.cpp
Artur Duque de Souza 060bf4148f Let corona layout the containments
Now corona will layout it's containments instead of letting
them do this task. This was created as a slot so we could preserve
BC. Subclasses of Plasma::Corona must be sure to skip containments
of Panel type during layouting if they wish to reimplement it to
have their own layout.

If subclasses doesn't care about it, just leave it alone and
everything will work just as before. :)

Reviewed-by: aseigo, notmart

svn path=/trunk/KDE/kdelibs/; revision=1095549
2010-02-24 14:24:52 +00:00

899 lines
27 KiB
C++

/*
* Copyright 2007 Matt Broadstone <mbroadst@gmail.com>
* Copyright 2007 Aaron Seigo <aseigo@kde.org>
* Copyright 2007 Riccardo Iaconelli <riccardo@kde.org>
* Copyright (c) 2009 Chani Armitage <chani@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "corona.h"
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsSceneDragDropEvent>
#include <QGraphicsGridLayout>
#include <QMimeData>
#include <QPainter>
#include <QTimer>
#include <cmath>
#include <kdebug.h>
#include <kglobal.h>
#include <klocale.h>
#include <kmimetype.h>
#include <kactioncollection.h>
#include <kaction.h>
#include <kshortcutsdialog.h>
#include "abstracttoolbox.h"
#include "containment.h"
#include "containmentactionspluginsconfig.h"
#include "view.h"
#include "private/applet_p.h"
#include "private/containment_p.h"
#include "tooltipmanager.h"
using namespace Plasma;
namespace Plasma
{
// constant controlling how long between requesting a configuration sync
// and one happening should occur. currently 10 seconds
const int CONFIG_SYNC_TIMEOUT = 10000;
class CoronaPrivate
{
public:
CoronaPrivate(Corona *corona)
: q(corona),
immutability(Mutable),
mimetype("text/x-plasmoidservicename"),
config(0),
actions(corona)
{
if (KGlobal::hasMainComponent()) {
configName = KGlobal::mainComponent().componentName() + "-appletsrc";
} else {
configName = "plasma-appletsrc";
}
}
~CoronaPrivate()
{
qDeleteAll(containments);
}
void init()
{
configSyncTimer.setSingleShot(true);
QObject::connect(&configSyncTimer, SIGNAL(timeout()), q, SLOT(syncConfig()));
//some common actions
actions.setConfigGroup("Shortcuts");
KAction *lockAction = actions.addAction("lock widgets");
QObject::connect(lockAction, SIGNAL(triggered(bool)), q, SLOT(toggleImmutability()));
lockAction->setText(i18n("Lock Widgets"));
lockAction->setIcon(KIcon("object-locked"));
lockAction->setData(AbstractToolBox::ControlTool);
lockAction->setShortcut(KShortcut("alt+d, l"));
lockAction->setShortcutContext(Qt::ApplicationShortcut);
//FIXME this doesn't really belong here. desktop KCM maybe?
//but should the shortcuts be per-app or really-global?
//I don't know how to make kactioncollections use plasmarc
KAction *action = actions.addAction("configure shortcuts");
QObject::connect(action, SIGNAL(triggered()), q, SLOT(showShortcutConfig()));
action->setText(i18n("Shortcut Settings"));
action->setIcon(KIcon("configure"));
action->setAutoRepeat(false);
action->setData(AbstractToolBox::ConfigureTool);
//action->setShortcut(KShortcut("ctrl+h"));
action->setShortcutContext(Qt::ApplicationShortcut);
actions.readSettings();
//fake containment/applet actions
KActionCollection *aActions = AppletPrivate::defaultActions(q);
KActionCollection *cActions = AppletPrivate::defaultActions(q); //containment has to start with applet stuff
ContainmentPrivate::addDefaultActions(cActions); //now it's really containment
//grab the current stuff
cActions->readSettings();
aActions->readSettings();
shortcutsDlg.setModal(false);
shortcutsDlg.addCollection(aActions);
shortcutsDlg.addCollection(cActions);
QObject::connect(&shortcutsDlg, SIGNAL(saved()), q, SIGNAL(shortcutsChanged()));
}
void showShortcutConfig()
{
//show a kshortcutsdialog with the actions
shortcutsDlg.configure();
}
void toggleImmutability()
{
if (immutability == Mutable) {
q->setImmutability(UserImmutable);
} else {
q->setImmutability(Mutable);
}
}
void saveLayout(KSharedConfigPtr cg) const
{
KConfigGroup containmentsGroup(cg, "Containments");
foreach (const Containment *containment, containments) {
QString cid = QString::number(containment->id());
KConfigGroup containmentConfig(&containmentsGroup, cid);
containment->save(containmentConfig);
}
}
void updateContainmentImmutability()
{
foreach (Containment *c, containments) {
// we need to tell each containment that immutability has been altered
c->updateConstraints(ImmutableConstraint);
}
}
void containmentDestroyed(QObject *obj)
{
// we do a static_cast here since it really isn't an Containment by this
// point anymore since we are in the qobject dtor. we don't actually
// try and do anything with it, we just need the value of the pointer
// so this unsafe looking code is actually just fine.
Containment* containment = static_cast<Plasma::Containment*>(obj);
int index = containments.indexOf(containment);
if (index > -1) {
containments.removeAt(index);
q->requestConfigSync();
}
}
void syncConfig()
{
q->config()->sync();
emit q->configSynced();
}
Containment *addContainment(const QString &name, const QVariantList &args,
uint id, bool delayedInit)
{
QString pluginName = name;
Containment *containment = 0;
Applet *applet = 0;
//kDebug() << "Loading" << name << args << id;
if (pluginName.isEmpty()) {
// default to the desktop containment
pluginName = "desktop";
}
if (pluginName != "null") {
applet = Applet::load(pluginName, id, args);
containment = dynamic_cast<Containment*>(applet);
}
if (!containment) {
kDebug() << "loading of containment" << name << "failed.";
// in case we got a non-Containment from Applet::loadApplet or
// a null containment was requested
if (applet) {
// the applet probably doesn't know what's hit it, so let's pretend it can be
// initialized to make assumptions in the applet's dtor safer
q->addItem(applet);
applet->init();
q->removeItem(applet);
delete applet;
}
containment = new Containment(0, 0, id);
if (pluginName == "null") {
containment->setDrawWallpaper(false);
}
// we want to provide something and don't care about the failure to launch
containment->setFailedToLaunch(false);
containment->setFormFactor(Plasma::Planar);
}
static_cast<Applet*>(containment)->d->isContainment = true;
q->addItem(containment);
static_cast<Applet*>(containment)->d->setIsContainment(true, true);
containments.append(containment);
if (!delayedInit) {
containment->init();
containment->updateConstraints(Plasma::StartupCompletedConstraint);
KConfigGroup cg = containment->config();
containment->save(cg);
q->requestConfigSync();
containment->flushPendingConstraintsEvents();
}
QObject::connect(containment, SIGNAL(destroyed(QObject*)),
q, SLOT(containmentDestroyed(QObject*)));
QObject::connect(containment, SIGNAL(configNeedsSaving()),
q, SLOT(requestConfigSync()));
QObject::connect(containment, SIGNAL(releaseVisualFocus()),
q, SIGNAL(releaseVisualFocus()));
QObject::connect(containment, SIGNAL(screenChanged(int,int,Plasma::Containment*)),
q, SIGNAL(screenOwnerChanged(int,int,Plasma::Containment*)));
if (!delayedInit) {
emit q->containmentAdded(containment);
}
return containment;
}
void offscreenWidgetDestroyed(QObject *);
static bool s_positioningContainments;
Corona *q;
ImmutabilityType immutability;
QString mimetype;
QString configName;
KSharedConfigPtr config;
QTimer configSyncTimer;
QList<Containment*> containments;
QHash<uint, QGraphicsWidget*> offscreenWidgets;
KActionCollection actions;
KShortcutsDialog shortcutsDlg;
QMap<Containment::Type, ContainmentActionsPluginsConfig> containmentActionsDefaults;
};
bool CoronaPrivate::s_positioningContainments = false;
Corona::Corona(QObject *parent)
: QGraphicsScene(parent),
d(new CoronaPrivate(this))
{
kDebug() << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "Corona ctor start";
d->init();
ToolTipManager::self()->m_corona = this;
//setViewport(new QGLWidget(QGLFormat(QGL::StencilBuffer | QGL::AlphaChannel)));
}
Corona::~Corona()
{
KConfigGroup trans(KGlobal::config(), "PlasmaTransientsConfig");
trans.deleteGroup();
// FIXME: Same fix as in Plasma::View - make sure that when the focused widget is
// destroyed we don't try to transfer it to something that's already been
// deleted.
clearFocus();
delete d;
}
void Corona::setAppletMimeType(const QString &type)
{
d->mimetype = type;
}
QString Corona::appletMimeType()
{
return d->mimetype;
}
void Corona::saveLayout(const QString &configName) const
{
KSharedConfigPtr c;
if (configName.isEmpty() || configName == d->configName) {
c = config();
} else {
c = KSharedConfig::openConfig(configName);
}
d->saveLayout(c);
}
void Corona::requestConfigSync()
{
// TODO: should we check into our immutability before doing this?
//NOTE: this is a pretty simplistic model: we simply save no more than CONFIG_SYNC_TIMEOUT
// after the first time this is called. not much of a heuristic for save points, but
// it should at least compress these activities a bit and provide a way for applet
// authors to ween themselves from the sync() disease. A more interesting/dynamic
// algorithm for determining when to actually sync() to disk might be better, though.
if (!d->configSyncTimer.isActive()) {
d->configSyncTimer.start(CONFIG_SYNC_TIMEOUT);
}
}
void Corona::requireConfigSync()
{
d->syncConfig();
}
void Corona::initializeLayout(const QString &configName)
{
clearContainments();
loadLayout(configName);
if (d->containments.isEmpty()) {
loadDefaultLayout();
if (!d->containments.isEmpty()) {
requestConfigSync();
}
}
if (config()->isImmutable()) {
d->updateContainmentImmutability();
}
KConfigGroup coronaConfig(config(), "General");
setImmutability((ImmutabilityType)coronaConfig.readEntry("immutability", (int)Mutable));
}
bool containmentSortByPosition(const Containment *c1, const Containment *c2)
{
return c1->id() < c2->id();
}
void Corona::layoutContainments()
{
if (CoronaPrivate::s_positioningContainments) {
return;
}
CoronaPrivate::s_positioningContainments = true;
//TODO: we should avoid running this too often; consider compressing requests
// with a timer.
QList<Containment*> c = containments();
QMutableListIterator<Containment*> it(c);
while (it.hasNext()) {
Containment *containment = it.next();
if (containment->containmentType() == Containment::PanelContainment ||
containment->containmentType() == Containment::CustomPanelContainment ||
offscreenWidgets().contains(containment)) {
// weed out all containments we don't care about at all
// e.g. Panels and ourself
it.remove();
continue;
}
}
qSort(c.begin(), c.end(), containmentSortByPosition);
if (c.isEmpty()) {
CoronaPrivate::s_positioningContainments = false;
return;
}
int column = 0;
int x = 0;
int y = 0;
int rowHeight = 0;
it.toFront();
while (it.hasNext()) {
Containment *containment = it.next();
containment->setPos(x, y);
//kDebug() << ++count << "setting to" << x << y;
int height = containment->size().height();
if (height > rowHeight) {
rowHeight = height;
}
++column;
if (column == CONTAINMENT_COLUMNS) {
column = 0;
x = 0;
y += rowHeight + INTER_CONTAINMENT_MARGIN + TOOLBOX_MARGIN;
rowHeight = 0;
} else {
x += containment->size().width() + INTER_CONTAINMENT_MARGIN;
}
//kDebug() << "column: " << column << "; x " << x << "; y" << y << "; width was"
// << containment->size().width();
}
CoronaPrivate::s_positioningContainments = false;
}
void Corona::loadLayout(const QString &configName)
{
KSharedConfigPtr c;
bool mergeConfig = false;
if (configName.isEmpty() || configName == d->configName) {
c = config();
} else {
c = KSharedConfig::openConfig(configName);
mergeConfig = true;
}
QList<uint> containmentsIds;
if (mergeConfig) {
foreach (Plasma::Containment *cont, d->containments) {
containmentsIds.append(cont->id());
}
}
KConfigGroup containments(c, "Containments");
foreach (const QString &group, containments.groupList()) {
KConfigGroup containmentConfig(&containments, group);
if (containmentConfig.entryMap().isEmpty()) {
continue;
}
uint cid = group.toUInt();
if (mergeConfig) {
if (containmentsIds.contains(cid)) {
cid = 0;
} else if (cid > AppletPrivate::s_maxAppletId) {
AppletPrivate::s_maxAppletId = cid;
}
}
//kDebug() << "got a containment in the config, trying to make a" << containmentConfig.readEntry("plugin", QString()) << "from" << group;
Containment *c = d->addContainment(containmentConfig.readEntry("plugin", QString()), QVariantList(),
cid, true);
if (!c) {
continue;
}
if (mergeConfig) {
containmentsIds.append(c->id());
}
c->init();
c->restore(containmentConfig);
}
foreach (Containment *containment, d->containments) {
QString cid = QString::number(containment->id());
KConfigGroup *appletsConfigGroup = 0;
if (mergeConfig) {
KConfigGroup containmentConfig(&containments, cid);
appletsConfigGroup = new KConfigGroup(&containmentConfig, "Applets");
}
foreach (Applet *applet, containment->applets()) {
if (mergeConfig) {
KConfigGroup externalAppletConfig(appletsConfigGroup, QString::number(applet->id()));
externalAppletConfig.copyTo(applet->d->mainConfigGroup());
}
applet->init();
// We have to flush the applet constraints manually
applet->flushPendingConstraintsEvents();
kDebug() << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "Applet" << applet->name();
}
delete appletsConfigGroup;
containment->updateConstraints(Plasma::StartupCompletedConstraint);
containment->flushPendingConstraintsEvents();
emit containmentAdded(containment);
kDebug() << "!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) << "Containment" << containment->name();
}
}
Containment *Corona::containmentForScreen(int screen, int desktop) const
{
foreach (Containment *containment, d->containments) {
if (containment->screen() == screen &&
(desktop < 0 || containment->desktop() == desktop) &&
(containment->containmentType() == Containment::DesktopContainment ||
containment->containmentType() == Containment::CustomContainment)) {
return containment;
}
}
return 0;
}
QList<Containment*> Corona::containments() const
{
return d->containments;
}
void Corona::clearContainments()
{
foreach (Containment *containment, d->containments) {
containment->clearApplets();
}
}
KSharedConfigPtr Corona::config() const
{
if (!d->config) {
d->config = KSharedConfig::openConfig(d->configName);
}
return d->config;
}
Containment *Corona::addContainment(const QString &name, const QVariantList &args)
{
return d->addContainment(name, args, 0, false);
}
Containment *Corona::addContainmentDelayed(const QString &name, const QVariantList &args)
{
return d->addContainment(name, args, 0, true);
}
void Corona::addOffscreenWidget(QGraphicsWidget *widget)
{
foreach (QGraphicsWidget *w, d->offscreenWidgets) {
if (w == widget) {
kDebug() << "widget is already an offscreen widget!";
return;
}
}
//search for an empty spot in the topleft quadrant of the scene. each 'slot' is QWIDGETSIZE_MAX
//x QWIDGETSIZE_MAX, so we're guaranteed to never have to move widgets once they're placed here.
int i = 0;
while (d->offscreenWidgets.contains(i)) {
i++;
}
d->offscreenWidgets[i] = widget;
widget->setPos((-i - 1) * QWIDGETSIZE_MAX, -QWIDGETSIZE_MAX);
QGraphicsWidget *pw = widget->parentWidget();
widget->setParentItem(0);
widget->setParent(pw);
//kDebug() << "adding offscreen widget at slot " << i;
if (!widget->scene()) {
addItem(widget);
}
connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(offscreenWidgetDestroyed(QObject*)));
}
void Corona::removeOffscreenWidget(QGraphicsWidget *widget)
{
QMutableHashIterator<uint, QGraphicsWidget *> it(d->offscreenWidgets);
while (it.hasNext()) {
if (it.next().value() == widget) {
it.remove();
return;
}
}
}
QList <QGraphicsWidget *> Corona::offscreenWidgets() const
{
return d->offscreenWidgets.values();
}
void CoronaPrivate::offscreenWidgetDestroyed(QObject *o)
{
// at this point, it's just a QObject, not a QGraphicsWidget, but we still need
// a pointer of the appropriate type.
// WARNING: DO NOT USE THE WIDGET POINTER FOR ANYTHING OTHER THAN POINTER COMPARISONS
QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(o);
q->removeOffscreenWidget(widget);
}
int Corona::numScreens() const
{
return 1;
}
QRect Corona::screenGeometry(int id) const
{
Q_UNUSED(id);
if (views().isEmpty()) {
return sceneRect().toRect();
} else {
QGraphicsView *v = views()[0];
QRect r = sceneRect().toRect();
r.moveTo(v->mapToGlobal(v->pos()));
return r;
}
}
QRegion Corona::availableScreenRegion(int id) const
{
return QRegion(screenGeometry(id));
}
QPoint Corona::popupPosition(const QGraphicsItem *item, const QSize &s)
{
return popupPosition(item, s, Qt::AlignLeft);
}
QPoint Corona::popupPosition(const QGraphicsItem *item, const QSize &s, Qt::AlignmentFlag alignment)
{
// TODO: merge both methods (also these in Applet) into one (with optional alignment) when we can break compatibility
// TODO: add support for more flags in the future?
QGraphicsView *v = viewFor(item);
if (!v) {
return QPoint(0, 0);
}
QPoint pos;
QTransform sceneTransform = item->sceneTransform();
//swap direction if necessary
if (QApplication::isRightToLeft() && alignment != Qt::AlignCenter) {
if (alignment == Qt::AlignRight) {
alignment = Qt::AlignLeft;
} else {
alignment = Qt::AlignRight;
}
}
//if the applet is rotated the popup position has to be un-transformed
if (sceneTransform.isRotating()) {
qreal angle = acos(sceneTransform.m11());
QTransform newTransform;
QPointF center = item->sceneBoundingRect().center();
newTransform.translate(center.x(), center.y());
newTransform.rotateRadians(-angle);
newTransform.translate(-center.x(), -center.y());
pos = v->mapFromScene(newTransform.inverted().map(item->scenePos()));
} else {
pos = v->mapFromScene(item->scenePos());
}
pos = v->mapToGlobal(pos);
//kDebug() << "==> position is" << item->scenePos() << v->mapFromScene(item->scenePos()) << pos;
Plasma::View *pv = dynamic_cast<Plasma::View *>(v);
Plasma::Location loc = Floating;
if (pv && pv->containment()) {
loc = pv->containment()->location();
}
switch (loc) {
case BottomEdge:
case TopEdge: {
if (alignment == Qt::AlignCenter) {
pos.setX(pos.x() + item->boundingRect().width()/2 - s.width()/2);
} else if (alignment == Qt::AlignRight) {
pos.setX(pos.x() + item->boundingRect().width() - s.width());
}
if (pos.x() + s.width() > v->geometry().right()) {
pos.setX(v->geometry().right() - s.width());
} else {
pos.setX(qMax(pos.x(), v->geometry().left()));
}
break;
}
case LeftEdge:
case RightEdge: {
if (alignment == Qt::AlignCenter) {
pos.setY(pos.y() + item->boundingRect().height()/2 - s.height()/2);
} else if (alignment == Qt::AlignRight) {
pos.setY(pos.y() + item->boundingRect().height() - s.height());
}
if (pos.y() + s.height() > v->geometry().bottom()) {
pos.setY(v->geometry().bottom() - s.height());
} else {
pos.setY(qMax(pos.y(), v->geometry().top()));
}
break;
}
default:
if (alignment == Qt::AlignCenter) {
pos.setX(pos.x() + item->boundingRect().width()/2 - s.width()/2);
} else if (alignment == Qt::AlignRight) {
pos.setX(pos.x() + item->boundingRect().width() - s.width());
}
break;
}
switch (loc) {
case BottomEdge:
pos.setY(v->geometry().y() - s.height());
break;
case TopEdge:
pos.setY(v->geometry().bottom());
break;
case LeftEdge:
pos.setX(v->geometry().right());
break;
case RightEdge:
pos.setX(v->geometry().x() - s.width());
break;
default:
if (pos.y() - s.height() > 0) {
pos.ry() = pos.y() - s.height();
} else {
pos.ry() = pos.y() + (int)item->boundingRect().size().height() + 1;
}
}
//are we out of screen?
int screen = ((pv && pv->containment()) ? pv->containment()->screen() : -1);
if (pv && screen == -1) {
screen = pv->screen();
}
QRect screenRect = screenGeometry(screen);
//kDebug() << "==> rect for" << screen << "is" << screenRect;
if (loc != LeftEdge && pos.x() + s.width() > screenRect.right()) {
pos.rx() -= ((pos.x() + s.width()) - screenRect.right());
}
if (loc != TopEdge && pos.y() + s.height() > screenRect.bottom()) {
pos.ry() -= ((pos.y() + s.height()) - screenRect.bottom());
}
pos.rx() = qMax(0, pos.x());
return pos;
}
void Corona::loadDefaultLayout()
{
}
void Corona::dragEnterEvent(QGraphicsSceneDragDropEvent *event)
{
QGraphicsScene::dragEnterEvent(event);
}
void Corona::dragLeaveEvent(QGraphicsSceneDragDropEvent *event)
{
QGraphicsScene::dragLeaveEvent(event);
}
void Corona::dragMoveEvent(QGraphicsSceneDragDropEvent *event)
{
QGraphicsScene::dragMoveEvent(event);
}
ImmutabilityType Corona::immutability() const
{
return d->immutability;
}
void Corona::setImmutability(const ImmutabilityType immutable)
{
if (d->immutability == immutable ||
d->immutability == SystemImmutable) {
return;
}
kDebug() << "setting immutability to" << immutable;
d->immutability = immutable;
d->updateContainmentImmutability();
//tell non-containments that might care (like plasmaapp or a custom corona)
emit immutabilityChanged(immutable);
//update our actions
QAction *action = d->actions.action("lock widgets");
if (action) {
if (d->immutability == SystemImmutable) {
action->setEnabled(false);
action->setVisible(false);
} else {
bool unlocked = d->immutability == Mutable;
action->setText(unlocked ? i18n("Lock Widgets") : i18n("Unlock Widgets"));
action->setIcon(KIcon(unlocked ? "object-locked" : "object-unlocked"));
action->setEnabled(true);
action->setVisible(true);
}
}
KConfigGroup cg(config(), "General");
// we call the dptr member directly for locked since isImmutable()
// also checks kiosk and parent containers
cg.writeEntry("immutability", (int)d->immutability);
requestConfigSync();
}
QList<Plasma::Location> Corona::freeEdges(int screen) const
{
QList<Plasma::Location> freeEdges;
freeEdges << Plasma::TopEdge << Plasma::BottomEdge
<< Plasma::LeftEdge << Plasma::RightEdge;
foreach (Containment *containment, containments()) {
if (containment->screen() == screen &&
freeEdges.contains(containment->location())) {
freeEdges.removeAll(containment->location());
}
}
return freeEdges;
}
QAction *Corona::action(QString name) const
{
return d->actions.action(name);
}
void Corona::addAction(QString name, QAction *action)
{
d->actions.addAction(name, action);
}
KAction* Corona::addAction(QString name)
{
return d->actions.addAction(name);
}
QList<QAction*> Corona::actions() const
{
return d->actions.actions();
}
void Corona::enableAction(const QString &name, bool enable)
{
QAction *action = d->actions.action(name);
if (action) {
action->setEnabled(enable);
action->setVisible(enable);
}
}
void Corona::updateShortcuts()
{
d->actions.readSettings();
d->shortcutsDlg.addCollection(&d->actions);
}
void Corona::addShortcuts(KActionCollection *newShortcuts)
{
d->shortcutsDlg.addCollection(newShortcuts);
}
void Corona::setContainmentActionsDefaults(Containment::Type containmentType, const ContainmentActionsPluginsConfig &config)
{
d->containmentActionsDefaults.insert(containmentType, config);
}
ContainmentActionsPluginsConfig Corona::containmentActionsDefaults(Containment::Type containmentType)
{
return d->containmentActionsDefaults.value(containmentType);
}
} // namespace Plasma
#include "corona.moc"