diff --git a/src/plasmaquick/plasmaquickview.cpp b/src/plasmaquick/plasmaquickview.cpp index b178279fe..d6433f891 100644 --- a/src/plasmaquick/plasmaquickview.cpp +++ b/src/plasmaquick/plasmaquickview.cpp @@ -69,8 +69,11 @@ void PlasmaQuickViewPrivate::setContainment(Plasma::Containment *cont) QObject::disconnect(containment.data(), 0, q, 0); QObject *oldGraphicObject = containment.data()->property("graphicObject").value(); if (oldGraphicObject) { + qDebug() << "Old graphics Object:" << oldGraphicObject << "Old containment" << containment.data(); //make sure the graphic object won't die with us - oldGraphicObject->setParent(cont); + //FIXME:we need a way to reparent to *NO* graphics item, but this makes Qt crash + oldGraphicObject->setProperty("visible", false); + oldGraphicObject->setParent(containment.data()); } } @@ -109,6 +112,7 @@ void PlasmaQuickViewPrivate::setContainment(Plasma::Containment *cont) (cont->containmentType() == Plasma::Types::DesktopContainment || cont->containmentType() == Plasma::Types::CustomContainment)); graphicObject->setProperty("parent", QVariant::fromValue(q->rootObject())); + graphicObject->setProperty("visible", true); q->rootObject()->setProperty("containment", QVariant::fromValue(graphicObject)); } else { qWarning() << "Containment graphic object not valid"; diff --git a/src/shell/activity.cpp b/src/shell/activity.cpp index e1f26ca4a..50dfe1e2a 100644 --- a/src/shell/activity.cpp +++ b/src/shell/activity.cpp @@ -42,7 +42,7 @@ Activity::Activity(const QString &id, Plasma::Corona *parent) : QObject(parent), m_id(id), - m_plugin("default"), + m_plugin("org.kde.desktopcontainment"), m_info(new KActivities::Info(id, this)), m_activityConsumer(new KActivities::Consumer(this)), m_corona(parent), @@ -62,8 +62,9 @@ Activity::Activity(const QString &id, Plasma::Corona *parent) //find your containments foreach (Plasma::Containment *cont, m_corona->containments()) { - if (cont->containmentType() == Plasma::Types::DesktopContainment || - cont->containmentType() == Plasma::Types::CustomContainment) { + if ((cont->containmentType() == Plasma::Types::DesktopContainment || + cont->containmentType() == Plasma::Types::CustomContainment) && + cont->activity() == id) { insertContainment(cont); } } @@ -172,7 +173,7 @@ Plasma::Containment* Activity::containmentForScreen(int screen) if (!containment || !containment->activity().isEmpty()) { // possibly a plugin failure, let's go for the default - containment = m_corona->containmentForScreen(screen, "default"); + containment = m_corona->containmentForScreen(screen, "org.kde.desktopcontainment"); } //we don't want to steal contaiments from other activities @@ -191,7 +192,7 @@ Plasma::Containment* Activity::containmentForScreen(int screen) if (!containment) { // possibly a plugin failure, let's go for the default - containment = m_corona->containmentForScreen(screen, "default"); + containment = m_corona->containmentForScreen(screen, "org.kde.desktopcontainment"); } if (containment) { diff --git a/src/shell/shellcorona.cpp b/src/shell/shellcorona.cpp index e7942e264..751b8aa41 100644 --- a/src/shell/shellcorona.cpp +++ b/src/shell/shellcorona.cpp @@ -31,7 +31,9 @@ #include #include #include +#include +#include "activity.h" #include "desktopview.h" #include "panelview.h" #include "scripting/desktopscriptengine.h" @@ -40,9 +42,11 @@ class ShellCorona::Private { public: - Private() - : desktopWidget(QApplication::desktop()), - widgetExplorerView(nullptr) + Private(ShellCorona *corona) + : q(corona), + desktopWidget(QApplication::desktop()), + widgetExplorerView(nullptr), + activityController(new KActivities::Controller(q)) { appConfigSyncTimer.setSingleShot(true); // constant controlling how long between requesting a configuration sync @@ -50,15 +54,18 @@ public: appConfigSyncTimer.setInterval(10000); } + ShellCorona *q; QString shell; QDesktopWidget * desktopWidget; QList views; WidgetExplorerView * widgetExplorerView; + KActivities::Controller *activityController; QHash panelViews; KConfigGroup desktopDefaultsConfig; WorkspaceScripting::DesktopScriptEngine * scriptEngine; QList waitingPanels; QSet loadingDesktops; + QHash activities; QTimer appConfigSyncTimer; }; @@ -70,7 +77,8 @@ WorkspaceScripting::DesktopScriptEngine * ShellCorona::scriptEngine() const ShellCorona::ShellCorona(QObject *parent) - : Plasma::Corona(parent), d(new Private()) + : Plasma::Corona(parent), + d(new Private(this)) { d->desktopDefaultsConfig = KConfigGroup(KSharedConfig::openConfig(package().filePath("defaults")), "Desktop"); @@ -107,6 +115,15 @@ ShellCorona::ShellCorona(QObject *parent) dashboardAction->setShortcut(QKeySequence("ctrl+f12")); dashboardAction->setShortcutContext(Qt::ApplicationShortcut); + //Activity stuff + + + connect(this, SIGNAL(immutabilityChanged(Plasma::ImmutabilityType)), + this, SLOT(updateImmutability(Plasma::ImmutabilityType))); + + connect(d->activityController, SIGNAL(currentActivityChanged(QString)), this, SLOT(currentActivityChanged(QString))); + connect(d->activityController, SIGNAL(activityAdded(QString)), this, SLOT(activityAdded(QString))); + connect(d->activityController, SIGNAL(activityRemoved(QString)), this, SLOT(activityRemoved(QString))); } ShellCorona::~ShellCorona() @@ -146,6 +163,7 @@ void ShellCorona::load() } processUpdateScripts(); + checkActivities(); checkScreens(); } @@ -186,6 +204,20 @@ void ShellCorona::processUpdateScripts() } } +Activity* ShellCorona::activity(const QString &id) +{ + if (!d->activities.contains(id)) { + //the add signal comes late sometimes + activityAdded(id); + } + return d->activities.value(id); +} + +KActivities::Controller *ShellCorona::activityController() +{ + return d->activityController; +} + void ShellCorona::checkScreens(bool signalWhenExists) { @@ -213,9 +245,9 @@ void ShellCorona::checkScreen(int screen, bool signalWhenExists) //buggy (sometimes the containment thinks it's already on the screen, so no view is created) //TODO: restore activities - //Activity *currentActivity = activity(d->activityController->currentActivity()); + Activity *currentActivity = activity(d->activityController->currentActivity()); //ensure the desktop(s) have a containment and view - checkDesktop(/*currentActivity,*/ signalWhenExists, screen); + checkDesktop(currentActivity, signalWhenExists, screen); //ensure the panels get views too @@ -234,9 +266,9 @@ void ShellCorona::checkScreen(int screen, bool signalWhenExists) } } -void ShellCorona::checkDesktop(/*Activity *activity,*/ bool signalWhenExists, int screen) +void ShellCorona::checkDesktop(Activity *activity, bool signalWhenExists, int screen) { - Plasma::Containment *c = /*activity->*/containmentForScreen(screen); + Plasma::Containment *c = activity->containmentForScreen(screen); //TODO: remove following when activities are restored if (!c) { @@ -443,6 +475,131 @@ void ShellCorona::setDashboardShown(bool show) } } +void ShellCorona::checkActivities() +{ + qDebug() << "containments to start with" << containments().count(); + + KActivities::Consumer::ServiceStatus status = d->activityController->serviceStatus(); + //qDebug() << "$%$%$#%$%$%Status:" << status; + if (status == KActivities::Consumer::NotRunning) { + //panic and give up - better than causing a mess + qDebug() << "No ActivityManager? Help, I've fallen and I can't get up!"; + return; + } + + QStringList existingActivities = d->activityController->listActivities(); + foreach (const QString &id, existingActivities) { + activityAdded(id); + } + + QStringList newActivities; + QString newCurrentActivity; + //migration checks: + //-containments with an invalid id are deleted. + //-containments that claim they were on a screen are kept together, and are preferred if we + //need to initialize the current activity. + //-containments that don't know where they were or who they were with just get made into their + //own activity. + foreach (Plasma::Containment *cont, containments()) { + if ((cont->containmentType() == Plasma::Types::DesktopContainment || + cont->containmentType() == Plasma::Types::CustomContainment)) { + const QString oldId = cont->activity(); + if (!oldId.isEmpty()) { + if (existingActivities.contains(oldId)) { + continue; //it's already claimed + } + qDebug() << "invalid id" << oldId; + //byebye + cont->destroy(); + continue; + } + + if (cont->screen() > -1 && !newCurrentActivity.isEmpty()) { + //it belongs on the new current activity + cont->setActivity(newCurrentActivity); + continue; + } + + /*//discourage blank names + if (context->currentActivity().isEmpty()) { + context->setCurrentActivity(i18nc("Default name for a new activity", "New Activity")); + }*/ + + //create a new activity for the containment + const QString id = d->activityController->addActivity(cont->activity()); + cont->setActivity(id); + newActivities << id; + if (cont->screen() > -1) { + newCurrentActivity = id; + } + qDebug() << "migrated" << cont->id() << cont->activity(); + } + } + + qDebug() << "migrated?" << !newActivities.isEmpty() << containments().count(); + if (!newActivities.isEmpty()) { + requestConfigSync(); + } + + //init the newbies + foreach (const QString &id, newActivities) { + activityAdded(id); + } + + //ensure the current activity is initialized + if (d->activityController->currentActivity().isEmpty()) { + qDebug() << "guessing at current activity"; + if (existingActivities.isEmpty()) { + if (newCurrentActivity.isEmpty()) { + if (newActivities.isEmpty()) { + qDebug() << "no activities!?! Bad activitymanager, no cookie!"; + QString id = d->activityController->addActivity(i18nc("Default name for a new activity", "New Activity")); + activityAdded(id); + d->activityController->setCurrentActivity(id); + qDebug() << "created emergency activity" << id; + } else { + d->activityController->setCurrentActivity(newActivities.first()); + } + } else { + d->activityController->setCurrentActivity(newCurrentActivity); + } + } else { + d->activityController->setCurrentActivity(existingActivities.first()); + } + } +} + +void ShellCorona::currentActivityChanged(const QString &newActivity) +{ + Activity *act = activity(newActivity); + qDebug() << "Activity changed:" << newActivity << act; + + if (act) { + act->ensureActive(); + } +} + +void ShellCorona::activityAdded(const QString &id) +{ + //TODO more sanity checks + if (d->activities.contains(id)) { + qDebug() << "you're late." << id; + return; + } + + Activity *a = new Activity(id, this); + if (a->isCurrent()) { + a->ensureActive(); + } + d->activities.insert(id, a); +} + +void ShellCorona::activityRemoved(const QString &id) +{ + Activity *a = d->activities.take(id); + a->deleteLater(); +} + void ShellCorona::printScriptError(const QString &error) { qWarning() << error; diff --git a/src/shell/shellcorona.h b/src/shell/shellcorona.h index 17c00848a..f2e29642f 100644 --- a/src/shell/shellcorona.h +++ b/src/shell/shellcorona.h @@ -28,11 +28,16 @@ namespace Plasma class Applet; } // namespace Plasma +class Activity; class PanelView; namespace WorkspaceScripting { class DesktopScriptEngine; } +namespace KActivities { + class Controller; +} + class ShellCorona : public Plasma::Corona { Q_OBJECT @@ -58,7 +63,7 @@ public: */ void checkScreen(int screen, bool signalWhenExists = false); - void checkDesktop(/*Activity *activity,*/ bool signalWhenExists, int screen); + void checkDesktop(Activity *activity, bool signalWhenExists, int screen); int numScreens() const; QRect screenGeometry(int id) const; @@ -114,6 +119,9 @@ protected Q_SLOTS: */ void processUpdateScripts(); + Activity* activity(const QString &id); + + KActivities::Controller *activityController(); private Q_SLOTS: void checkLoadingDesktopsComplete(); @@ -121,6 +129,10 @@ private Q_SLOTS: void showWidgetExplorer(); void syncAppConfig(); void setDashboardShown(bool show); + void checkActivities(); + void currentActivityChanged(const QString &newActivity); + void activityAdded(const QString &id); + void activityRemoved(const QString &id); private: class Private;