24 #include "private/corona_p.h"
26 #include <QApplication>
27 #include <QDesktopWidget>
28 #include <QGraphicsView>
29 #include <QGraphicsSceneDragDropEvent>
30 #include <QGraphicsGridLayout>
41 #include <kmimetype.h>
42 #include <kshortcutsdialog.h>
43 #include <kwindowsystem.h>
50 #include "private/animator_p.h"
51 #include "private/applet_p.h"
52 #include "private/containment_p.h"
56 using namespace Plasma;
61 bool CoronaPrivate::s_positioningContainments =
false;
65 d(new CoronaPrivate(this))
67 kDebug() <<
"!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) <<
"Corona ctor start";
75 KConfigGroup trans(KGlobal::config(),
"PlasmaTransientsConfig");
101 d->defaultContainmentPlugin = name;
106 return d->defaultContainmentPlugin;
113 if (configName.isEmpty() || configName == d->configName) {
116 c = KSharedConfig::openConfig(configName, KConfig::SimpleConfig);
124 foreach (
const QString &group, config.groupList()) {
125 KConfigGroup cg(&config, group);
133 KConfigGroup dest(&config,
"Containments");
137 c->
config().reparent(&dest);
150 d->immutability = oldImm;
159 static const int CONFIG_SYNC_TIMEOUT = 10000;
168 if (!d->configSyncTimer.isActive()) {
169 d->configSyncTimer.start(CONFIG_SYNC_TIMEOUT);
183 if (d->containments.isEmpty()) {
185 if (!d->containments.isEmpty()) {
190 if (
config()->isImmutable()) {
193 KConfigGroup coronaConfig(
config(),
"General");
200 return c1->
id() < c2->
id();
205 if (CoronaPrivate::s_positioningContainments) {
209 CoronaPrivate::s_positioningContainments =
true;
214 QMutableListIterator<Containment*> it(c);
216 while (it.hasNext()) {
231 CoronaPrivate::s_positioningContainments =
false;
241 while (it.hasNext()) {
243 containment->setPos(x, y);
246 int height = containment->size().height();
247 if (height > rowHeight) {
253 if (column == CONTAINMENT_COLUMNS) {
256 y += rowHeight + INTER_CONTAINMENT_MARGIN + TOOLBOX_MARGIN;
259 x += containment->size().width() + INTER_CONTAINMENT_MARGIN;
265 CoronaPrivate::s_positioningContainments =
false;
271 if (!configName.isEmpty() && configName != d->configName) {
274 d->configName = configName;
277 KSharedConfigPtr conf =
config();
278 d->importLayout(*conf,
false);
283 return d->importLayout(conf,
true);
286 #ifndef KDE_NO_DEPRECATED
289 return d->importLayout(conf,
true);
295 foreach (
Containment *containment, d->containments) {
296 if (containment->
screen() == screen &&
297 (desktop < 0 || containment->
desktop() == desktop) &&
308 const QString &defaultPluginIfNonExistent,
const QVariantList &defaultArgs)
311 if (!containment && !defaultPluginIfNonExistent.isEmpty()) {
314 desktop >= -1 && desktop < KWindowSystem::numberOfDesktops()) {
315 containment = d->addContainment(defaultPluginIfNonExistent, defaultArgs, 0,
false);
327 return d->containments;
332 foreach (
Containment *containment, d->containments) {
340 d->config = KSharedConfig::openConfig(d->configName, KConfig::SimpleConfig);
348 if (d->immutability ==
Mutable) {
349 return d->addContainment(name, args, 0,
false);
357 if (d->immutability ==
Mutable) {
358 return d->addContainment(name, args, 0,
true);
366 AnimatorPrivate::mapAnimation(from, to);
371 AnimatorPrivate::mapAnimation(from, to);
378 kDebug() <<
"widget is already an offscreen widget!";
386 while (d->offscreenWidgets.contains(i)) {
390 d->offscreenWidgets[i] = widget;
391 widget->setPos((-i - 1) * QWIDGETSIZE_MAX, -QWIDGETSIZE_MAX);
394 widget->setParentItem(0);
396 widget->setParent(pw);
400 if (!widget->scene()) {
404 connect(widget, SIGNAL(destroyed(
QObject*)),
this, SLOT(offscreenWidgetDestroyed(
QObject*)));
409 QMutableHashIterator<uint, QGraphicsWidget *> it(d->offscreenWidgets);
411 while (it.hasNext()) {
412 if (it.next().value() == widget) {
421 return d->offscreenWidgets.values();
424 void CoronaPrivate::offscreenWidgetDestroyed(
QObject *o)
430 q->removeOffscreenWidget(widget);
443 QRect r = sceneRect().toRect();
444 r.moveTo(v->mapToGlobal(QPoint(0, 0)));
448 return sceneRect().toRect();
466 const QGraphicsItem *actualItem = item;
476 if (!v->isVisible()) {
477 actualItem = item->parentItem();
481 actualItem = qobject_cast<QGraphicsItem*>(widget->parent());
500 QTransform sceneTransform = actualItem->sceneTransform();
503 if (QApplication::isRightToLeft() && alignment != Qt::AlignCenter) {
504 if (alignment == Qt::AlignRight) {
505 alignment = Qt::AlignLeft;
507 alignment = Qt::AlignRight;
512 if (sceneTransform.isRotating()) {
513 qreal angle = acos(sceneTransform.m11());
514 QTransform newTransform;
515 QPointF center = actualItem->sceneBoundingRect().center();
517 newTransform.translate(center.x(), center.y());
518 newTransform.rotateRadians(-angle);
519 newTransform.translate(-center.x(), -center.y());
520 pos = v->mapFromScene(newTransform.inverted().map(actualItem->scenePos()));
522 pos = v->mapFromScene(actualItem->scenePos());
525 pos = v->mapToGlobal(pos);
537 if (alignment == Qt::AlignCenter) {
538 pos.setX(pos.x() + actualItem->boundingRect().width()/2 - s.width()/2);
539 }
else if (alignment == Qt::AlignRight) {
540 pos.setX(pos.x() + actualItem->boundingRect().width() - s.width());
543 if (pos.x() + s.width() > v->geometry().x() + v->geometry().width()) {
544 pos.setX((v->geometry().x() + v->geometry().width()) - s.width());
546 pos.setX(qMax(pos.x(), v->geometry().left()));
552 if (alignment == Qt::AlignCenter) {
553 pos.setY(pos.y() + actualItem->boundingRect().height()/2 - s.height()/2);
554 }
else if (alignment == Qt::AlignRight) {
555 pos.setY(pos.y() + actualItem->boundingRect().height() - s.height());
558 if (pos.y() + s.height() > v->geometry().y() + v->geometry().height()) {
559 pos.setY((v->geometry().y() + v->geometry().height()) - s.height());
561 pos.setY(qMax(pos.y(), v->geometry().top()));
566 if (alignment == Qt::AlignCenter) {
567 pos.setX(pos.x() + actualItem->boundingRect().width()/2 - s.width()/2);
568 }
else if (alignment == Qt::AlignRight) {
569 pos.setX(pos.x() + actualItem->boundingRect().width() - s.width());
583 screen = QApplication::desktop()->screenNumber(v);
591 pos.setY(v->geometry().y() - s.height());
594 pos.setY(v->geometry().y() + v->geometry().height());
597 pos.setX(v->geometry().x() + v->geometry().width());
600 pos.setX(v->geometry().x() - s.width());
603 if (pos.y() - s.height() > screenRect.top()) {
604 pos.ry() = pos.y() - s.height();
606 pos.ry() = pos.y() + (int)actualItem->boundingRect().size().height() + 1;
612 if (loc !=
LeftEdge && pos.x() + s.width() > screenRect.x() + screenRect.width()) {
613 pos.rx() -= ((pos.x() + s.width()) - (screenRect.x() + screenRect.width()));
616 if (loc !=
TopEdge && pos.y() + s.height() > screenRect.y() + screenRect.height()) {
617 pos.ry() -= ((pos.y() + s.height()) - (screenRect.y() + screenRect.height()));
620 pos.rx() = qMax(0, pos.x());
621 pos.ry() = qMax(0, pos.y());
631 d->toolBoxPlugins[
type] = plugin;
637 return d->toolBoxPlugins.value(type);
642 QGraphicsScene::dragEnterEvent(event);
647 QGraphicsScene::dragLeaveEvent(event);
652 QGraphicsScene::dragMoveEvent(event);
657 return d->immutability;
662 if (d->immutability == immutable || d->immutability ==
SystemImmutable) {
666 kDebug() <<
"setting immutability to" << immutable;
667 d->immutability = immutable;
668 d->updateContainmentImmutability();
673 QAction *
action = d->actions.action(
"lock widgets");
676 action->setEnabled(
false);
677 action->setVisible(
false);
679 bool unlocked = d->immutability ==
Mutable;
680 action->setText(unlocked ? i18n(
"Lock Widgets") : i18n(
"Unlock Widgets"));
681 action->setIcon(KIcon(unlocked ?
"object-locked" :
"object-unlocked"));
682 action->setEnabled(
true);
683 action->setVisible(
true);
688 KConfigGroup cg(
config(),
"General");
692 cg.writeEntry(
"immutability", (
int)d->immutability);
704 if (containment->
screen() == screen &&
705 freeEdges.contains(containment->
location())) {
706 freeEdges.removeAll(containment->
location());
715 return d->actions.action(name);
720 d->actions.addAction(name, action);
725 return d->actions.addAction(name);
730 return d->actions.actions();
735 QAction *
action = d->actions.action(name);
737 action->setEnabled(enable);
738 action->setVisible(enable);
744 QMutableListIterator<QWeakPointer<KActionCollection> > it(d->actionCollections);
745 while (it.hasNext()) {
747 KActionCollection *collection = it.value().data();
754 collection->readSettings();
755 if (d->shortcutsDlg) {
756 d->shortcutsDlg.data()->addCollection(collection);
763 d->actionCollections << newShortcuts;
764 if (d->shortcutsDlg) {
765 d->shortcutsDlg.data()->addCollection(newShortcuts);
771 d->containmentActionsDefaults.insert(containmentType, config);
776 return d->containmentActionsDefaults.value(containmentType);
786 return d->dialogManager.data();
789 CoronaPrivate::CoronaPrivate(
Corona *corona)
792 mimetype(
"text/x-plasmoidservicename"),
793 defaultContainmentPlugin(
"desktop"),
797 if (KGlobal::hasMainComponent()) {
798 configName = KGlobal::mainComponent().componentName() +
"-appletsrc";
800 configName =
"plasma-appletsrc";
804 CoronaPrivate::~CoronaPrivate()
806 qDeleteAll(containments);
809 void CoronaPrivate::init()
811 q->setStickyFocus(
true);
812 configSyncTimer.setSingleShot(
true);
813 QObject::connect(&configSyncTimer, SIGNAL(timeout()), q, SLOT(syncConfig()));
816 actions.setConfigGroup(
"Shortcuts");
818 KAction *lockAction = actions.addAction(
"lock widgets");
819 QObject::connect(lockAction, SIGNAL(triggered(
bool)), q, SLOT(toggleImmutability()));
820 lockAction->setText(i18n(
"Lock Widgets"));
821 lockAction->setAutoRepeat(
true);
822 lockAction->setIcon(KIcon(
"object-locked"));
824 lockAction->setShortcut(KShortcut(
"alt+d, l"));
825 lockAction->setShortcutContext(Qt::ApplicationShortcut);
830 KAction *action = actions.addAction(
"configure shortcuts");
831 QObject::connect(action, SIGNAL(triggered()), q, SLOT(showShortcutConfig()));
832 action->setText(i18n(
"Shortcut Settings"));
833 action->setIcon(KIcon(
"configure-shortcuts"));
834 action->setAutoRepeat(
false);
837 action->setShortcutContext(Qt::ApplicationShortcut);
840 KActionCollection *containmentActions = AppletPrivate::defaultActions(q);
841 ContainmentPrivate::addDefaultActions(containmentActions);
842 actionCollections << &actions << AppletPrivate::defaultActions(q) << containmentActions;
843 q->updateShortcuts();
846 void CoronaPrivate::showShortcutConfig()
849 KShortcutsDialog *dlg = shortcutsDlg.data();
851 dlg =
new KShortcutsDialog();
852 dlg->setModal(
false);
853 dlg->setAttribute(Qt::WA_DeleteOnClose,
true);
854 QObject::connect(dlg, SIGNAL(saved()), q, SIGNAL(shortcutsChanged()));
856 dlg->addCollection(&actions);
857 QMutableListIterator<QWeakPointer<KActionCollection> > it(actionCollections);
858 while (it.hasNext()) {
860 KActionCollection *collection = it.value().data();
867 dlg->addCollection(collection);
871 KWindowSystem::setOnDesktop(dlg->winId(), KWindowSystem::currentDesktop());
876 void CoronaPrivate::toggleImmutability()
885 void CoronaPrivate::saveLayout(KSharedConfigPtr cg)
const
887 KConfigGroup containmentsGroup(cg,
"Containments");
888 foreach (
const Containment *containment, containments) {
889 QString cid = QString::number(containment->
id());
890 KConfigGroup containmentConfig(&containmentsGroup, cid);
891 containment->
save(containmentConfig);
895 void CoronaPrivate::updateContainmentImmutability()
903 void CoronaPrivate::containmentDestroyed(
QObject *obj)
910 int index = containments.indexOf(containment);
913 containments.removeAt(index);
914 q->requestConfigSync();
918 void CoronaPrivate::syncConfig()
921 emit q->configSynced();
924 Containment *CoronaPrivate::addContainment(
const QString &name,
const QVariantList &args, uint
id,
bool delayedInit)
926 QString pluginName = name;
932 if (pluginName.isEmpty() || pluginName ==
"default") {
934 pluginName = defaultContainmentPlugin;
937 bool loadingNull = pluginName ==
"null";
945 kDebug() <<
"loading of containment" << name <<
"failed.";
955 q->removeItem(applet);
973 KConfigGroup conf(q->config(),
"Containments");
974 conf = KConfigGroup(&conf, QString::number(containment->
id()));
978 applet->d->isContainment =
true;
979 containment->setPos(containment->d->preferredPos(q));
980 q->addItem(containment);
981 applet->d->setIsContainment(
true,
true);
982 containments.append(containment);
986 KConfigGroup cg = containment->
config();
989 containment->
save(cg);
990 q->requestConfigSync();
994 QObject::connect(containment, SIGNAL(destroyed(
QObject*)),
995 q, SLOT(containmentDestroyed(
QObject*)));
996 QObject::connect(containment, SIGNAL(configNeedsSaving()),
997 q, SLOT(requestConfigSync()));
998 QObject::connect(containment, SIGNAL(releaseVisualFocus()),
999 q, SIGNAL(releaseVisualFocus()));
1004 emit q->containmentAdded(containment);
1010 QList<Plasma::Containment *> CoronaPrivate::importLayout(
const KConfigBase &conf,
bool mergeConfig)
1012 if (
const KConfigGroup *group = dynamic_cast<const KConfigGroup *>(&conf)) {
1013 if (!group->isValid()) {
1014 return QList<Containment *>();
1018 QList<Plasma::Containment *> newContainments;
1019 QSet<uint> containmentsIds;
1021 foreach (
Containment *containment, containments) {
1022 containmentsIds.insert(containment->
id());
1025 KConfigGroup containmentsGroup(&conf,
"Containments");
1027 foreach (
const QString &group, containmentsGroup.groupList()) {
1028 KConfigGroup containmentConfig(&containmentsGroup, group);
1030 if (containmentConfig.entryMap().isEmpty()) {
1034 uint cid = group.toUInt();
1035 if (containmentsIds.contains(cid)) {
1036 cid = ++AppletPrivate::s_maxAppletId;
1037 }
else if (cid > AppletPrivate::s_maxAppletId) {
1038 AppletPrivate::s_maxAppletId = cid;
1042 KConfigGroup realConf(q->config(),
"Containments");
1043 realConf = KConfigGroup(&realConf, QString::number(cid));
1045 realConf.deleteGroup();
1046 containmentConfig.copyTo(&realConf);
1050 kDebug() <<
"!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) <<
"Adding Containment" << containmentConfig.readEntry(
"plugin", QString());
1051 Containment *c = addContainment(containmentConfig.readEntry(
"plugin", QString()), QVariantList(), cid,
true);
1056 newContainments.append(c);
1057 containmentsIds.insert(c->
id());
1060 kDebug() <<
"!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) <<
"Init Containment" << c->
pluginName();
1061 c->
restore(containmentConfig);
1062 kDebug() <<
"!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) <<
"Restored Containment" << c->
pluginName();
1065 foreach (
Containment *containment, newContainments) {
1067 containment->d->initApplets();
1068 emit q->containmentAdded(containment);
1069 kDebug() <<
"!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) <<
"Containment" << containment->
name();
1072 return newContainments;
1077 #include "corona.moc"