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 #if defined(arm) || defined(__arm__)
392 widget->setPos((-i - 1) * 2000, -2000);
394 widget->setPos((-i - 1) * QWIDGETSIZE_MAX, -QWIDGETSIZE_MAX);
398 widget->setParentItem(0);
400 widget->setParent(pw);
404 if (!widget->scene()) {
408 connect(widget, SIGNAL(destroyed(
QObject*)),
this, SLOT(offscreenWidgetDestroyed(
QObject*)));
413 QMutableHashIterator<uint, QGraphicsWidget *> it(d->offscreenWidgets);
415 while (it.hasNext()) {
416 if (it.next().value() == widget) {
425 return d->offscreenWidgets.values();
428 void CoronaPrivate::offscreenWidgetDestroyed(
QObject *o)
434 q->removeOffscreenWidget(widget);
447 QRect r = sceneRect().toRect();
448 r.moveTo(v->mapToGlobal(QPoint(0, 0)));
452 return sceneRect().toRect();
470 const QGraphicsItem *actualItem = item;
480 if (!v->isVisible()) {
481 actualItem = item->parentItem();
485 actualItem = qobject_cast<QGraphicsItem*>(widget->parent());
504 QTransform sceneTransform = actualItem->sceneTransform();
507 if (QApplication::isRightToLeft() && alignment != Qt::AlignCenter) {
508 if (alignment == Qt::AlignRight) {
509 alignment = Qt::AlignLeft;
511 alignment = Qt::AlignRight;
516 if (sceneTransform.isRotating()) {
517 qreal angle = acos(sceneTransform.m11());
518 QTransform newTransform;
519 QPointF center = actualItem->sceneBoundingRect().center();
521 newTransform.translate(center.x(), center.y());
522 newTransform.rotateRadians(-angle);
523 newTransform.translate(-center.x(), -center.y());
524 pos = v->mapFromScene(newTransform.inverted().map(actualItem->scenePos()));
526 pos = v->mapFromScene(actualItem->scenePos());
529 pos = v->mapToGlobal(pos);
541 if (alignment == Qt::AlignCenter) {
542 pos.setX(pos.x() + actualItem->boundingRect().width()/2 - s.width()/2);
543 }
else if (alignment == Qt::AlignRight) {
544 pos.setX(pos.x() + actualItem->boundingRect().width() - s.width());
547 if (pos.x() + s.width() > v->geometry().x() + v->geometry().width()) {
548 pos.setX((v->geometry().x() + v->geometry().width()) - s.width());
550 pos.setX(qMax(pos.x(), v->geometry().left()));
556 if (alignment == Qt::AlignCenter) {
557 pos.setY(pos.y() + actualItem->boundingRect().height()/2 - s.height()/2);
558 }
else if (alignment == Qt::AlignRight) {
559 pos.setY(pos.y() + actualItem->boundingRect().height() - s.height());
562 if (pos.y() + s.height() > v->geometry().y() + v->geometry().height()) {
563 pos.setY((v->geometry().y() + v->geometry().height()) - s.height());
565 pos.setY(qMax(pos.y(), v->geometry().top()));
570 if (alignment == Qt::AlignCenter) {
571 pos.setX(pos.x() + actualItem->boundingRect().width()/2 - s.width()/2);
572 }
else if (alignment == Qt::AlignRight) {
573 pos.setX(pos.x() + actualItem->boundingRect().width() - s.width());
587 screen = QApplication::desktop()->screenNumber(v);
595 pos.setY(v->geometry().y() - s.height());
598 pos.setY(v->geometry().y() + v->geometry().height());
601 pos.setX(v->geometry().x() + v->geometry().width());
604 pos.setX(v->geometry().x() - s.width());
607 if (pos.y() - s.height() > screenRect.top()) {
608 pos.ry() = pos.y() - s.height();
610 pos.ry() = pos.y() + (int)actualItem->boundingRect().size().height() + 1;
616 if (loc !=
LeftEdge && pos.x() + s.width() > screenRect.x() + screenRect.width()) {
617 pos.rx() -= ((pos.x() + s.width()) - (screenRect.x() + screenRect.width()));
620 if (loc !=
TopEdge && pos.y() + s.height() > screenRect.y() + screenRect.height()) {
621 pos.ry() -= ((pos.y() + s.height()) - (screenRect.y() + screenRect.height()));
624 pos.rx() = qMax(0, pos.x());
625 pos.ry() = qMax(0, pos.y());
635 d->toolBoxPlugins[
type] = plugin;
641 return d->toolBoxPlugins.value(type);
646 QGraphicsScene::dragEnterEvent(event);
651 QGraphicsScene::dragLeaveEvent(event);
656 QGraphicsScene::dragMoveEvent(event);
661 return d->immutability;
666 if (d->immutability == immutable || d->immutability ==
SystemImmutable) {
670 kDebug() <<
"setting immutability to" << immutable;
671 d->immutability = immutable;
672 d->updateContainmentImmutability();
677 QAction *
action = d->actions.action(
"lock widgets");
680 action->setEnabled(
false);
681 action->setVisible(
false);
683 bool unlocked = d->immutability ==
Mutable;
684 action->setText(unlocked ? i18n(
"Lock Widgets") : i18n(
"Unlock Widgets"));
685 action->setIcon(KIcon(unlocked ?
"object-locked" :
"object-unlocked"));
686 action->setEnabled(
true);
687 action->setVisible(
true);
692 KConfigGroup cg(
config(),
"General");
696 cg.writeEntry(
"immutability", (
int)d->immutability);
708 if (containment->
screen() == screen &&
709 freeEdges.contains(containment->
location())) {
710 freeEdges.removeAll(containment->
location());
719 return d->actions.action(name);
724 d->actions.addAction(name, action);
729 return d->actions.addAction(name);
734 return d->actions.actions();
739 QAction *
action = d->actions.action(name);
741 action->setEnabled(enable);
742 action->setVisible(enable);
748 QMutableListIterator<QWeakPointer<KActionCollection> > it(d->actionCollections);
749 while (it.hasNext()) {
751 KActionCollection *collection = it.value().data();
758 collection->readSettings();
759 if (d->shortcutsDlg) {
760 d->shortcutsDlg.data()->addCollection(collection);
767 d->actionCollections << newShortcuts;
768 if (d->shortcutsDlg) {
769 d->shortcutsDlg.data()->addCollection(newShortcuts);
775 d->containmentActionsDefaults.insert(containmentType, config);
780 return d->containmentActionsDefaults.value(containmentType);
790 return d->dialogManager.data();
793 CoronaPrivate::CoronaPrivate(
Corona *corona)
796 mimetype(
"text/x-plasmoidservicename"),
797 defaultContainmentPlugin(
"desktop"),
801 if (KGlobal::hasMainComponent()) {
802 configName = KGlobal::mainComponent().componentName() +
"-appletsrc";
804 configName =
"plasma-appletsrc";
808 CoronaPrivate::~CoronaPrivate()
810 qDeleteAll(containments);
813 void CoronaPrivate::init()
815 q->setStickyFocus(
true);
816 configSyncTimer.setSingleShot(
true);
817 QObject::connect(&configSyncTimer, SIGNAL(timeout()), q, SLOT(syncConfig()));
820 actions.setConfigGroup(
"Shortcuts");
822 KAction *lockAction = actions.addAction(
"lock widgets");
823 QObject::connect(lockAction, SIGNAL(triggered(
bool)), q, SLOT(toggleImmutability()));
824 lockAction->setText(i18n(
"Lock Widgets"));
825 lockAction->setAutoRepeat(
true);
826 lockAction->setIcon(KIcon(
"object-locked"));
828 lockAction->setShortcut(KShortcut(
"alt+d, l"));
829 lockAction->setShortcutContext(Qt::ApplicationShortcut);
834 KAction *action = actions.addAction(
"configure shortcuts");
835 QObject::connect(action, SIGNAL(triggered()), q, SLOT(showShortcutConfig()));
836 action->setText(i18n(
"Shortcut Settings"));
837 action->setIcon(KIcon(
"configure-shortcuts"));
838 action->setAutoRepeat(
false);
841 action->setShortcutContext(Qt::ApplicationShortcut);
844 KActionCollection *containmentActions = AppletPrivate::defaultActions(q);
845 ContainmentPrivate::addDefaultActions(containmentActions);
846 actionCollections << &actions << AppletPrivate::defaultActions(q) << containmentActions;
847 q->updateShortcuts();
850 void CoronaPrivate::showShortcutConfig()
853 KShortcutsDialog *dlg = shortcutsDlg.data();
855 dlg =
new KShortcutsDialog();
856 dlg->setModal(
false);
857 dlg->setAttribute(Qt::WA_DeleteOnClose,
true);
858 QObject::connect(dlg, SIGNAL(saved()), q, SIGNAL(shortcutsChanged()));
860 dlg->addCollection(&actions);
861 QMutableListIterator<QWeakPointer<KActionCollection> > it(actionCollections);
862 while (it.hasNext()) {
864 KActionCollection *collection = it.value().data();
871 dlg->addCollection(collection);
875 KWindowSystem::setOnDesktop(dlg->winId(), KWindowSystem::currentDesktop());
880 void CoronaPrivate::toggleImmutability()
889 void CoronaPrivate::saveLayout(KSharedConfigPtr cg)
const
891 KConfigGroup containmentsGroup(cg,
"Containments");
892 foreach (
const Containment *containment, containments) {
893 QString cid = QString::number(containment->
id());
894 KConfigGroup containmentConfig(&containmentsGroup, cid);
895 containment->
save(containmentConfig);
899 void CoronaPrivate::updateContainmentImmutability()
907 void CoronaPrivate::containmentDestroyed(
QObject *obj)
914 int index = containments.indexOf(containment);
917 containments.removeAt(index);
918 q->requestConfigSync();
922 void CoronaPrivate::syncConfig()
925 emit q->configSynced();
928 Containment *CoronaPrivate::addContainment(
const QString &name,
const QVariantList &args, uint
id,
bool delayedInit)
930 QString pluginName = name;
936 if (pluginName.isEmpty() || pluginName ==
"default") {
938 pluginName = defaultContainmentPlugin;
941 bool loadingNull = pluginName ==
"null";
949 kDebug() <<
"loading of containment" << name <<
"failed.";
959 q->removeItem(applet);
977 KConfigGroup conf(q->config(),
"Containments");
978 conf = KConfigGroup(&conf, QString::number(containment->
id()));
982 applet->d->isContainment =
true;
983 containment->setPos(containment->d->preferredPos(q));
984 q->addItem(containment);
985 applet->d->setIsContainment(
true,
true);
986 containments.append(containment);
990 KConfigGroup cg = containment->
config();
993 containment->
save(cg);
994 q->requestConfigSync();
998 QObject::connect(containment, SIGNAL(destroyed(
QObject*)),
999 q, SLOT(containmentDestroyed(
QObject*)));
1000 QObject::connect(containment, SIGNAL(configNeedsSaving()),
1001 q, SLOT(requestConfigSync()));
1002 QObject::connect(containment, SIGNAL(releaseVisualFocus()),
1003 q, SIGNAL(releaseVisualFocus()));
1008 emit q->containmentAdded(containment);
1014 QList<Plasma::Containment *> CoronaPrivate::importLayout(
const KConfigBase &conf,
bool mergeConfig)
1016 if (
const KConfigGroup *group = dynamic_cast<const KConfigGroup *>(&conf)) {
1017 if (!group->isValid()) {
1018 return QList<Containment *>();
1022 QList<Plasma::Containment *> newContainments;
1023 QSet<uint> containmentsIds;
1025 foreach (
Containment *containment, containments) {
1026 containmentsIds.insert(containment->
id());
1029 KConfigGroup containmentsGroup(&conf,
"Containments");
1031 foreach (
const QString &group, containmentsGroup.groupList()) {
1032 KConfigGroup containmentConfig(&containmentsGroup, group);
1034 if (containmentConfig.entryMap().isEmpty()) {
1038 uint cid = group.toUInt();
1039 if (containmentsIds.contains(cid)) {
1040 cid = ++AppletPrivate::s_maxAppletId;
1041 }
else if (cid > AppletPrivate::s_maxAppletId) {
1042 AppletPrivate::s_maxAppletId = cid;
1046 KConfigGroup realConf(q->config(),
"Containments");
1047 realConf = KConfigGroup(&realConf, QString::number(cid));
1049 realConf.deleteGroup();
1050 containmentConfig.copyTo(&realConf);
1054 kDebug() <<
"!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) <<
"Adding Containment" << containmentConfig.readEntry(
"plugin", QString());
1055 Containment *c = addContainment(containmentConfig.readEntry(
"plugin", QString()), QVariantList(), cid,
true);
1060 newContainments.append(c);
1061 containmentsIds.insert(c->
id());
1064 kDebug() <<
"!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) <<
"Init Containment" << c->
pluginName();
1065 c->
restore(containmentConfig);
1066 kDebug() <<
"!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) <<
"Restored Containment" << c->
pluginName();
1069 foreach (
Containment *containment, newContainments) {
1071 containment->d->initApplets();
1072 emit q->containmentAdded(containment);
1073 kDebug() <<
"!!{} STARTUP TIME" << QTime().msecsTo(QTime::currentTime()) <<
"Containment" << containment->
name();
1076 return newContainments;
1081 #include "corona.moc"