make activity switching work

there is a problem in ownership of containment graphics objects, we can't reparent to 0 at the moment or it crashes
This commit is contained in:
Marco Martin 2013-10-17 20:03:44 +02:00
parent 800e5ec91c
commit 76260be71f
4 changed files with 189 additions and 15 deletions

View File

@ -69,8 +69,11 @@ void PlasmaQuickViewPrivate::setContainment(Plasma::Containment *cont)
QObject::disconnect(containment.data(), 0, q, 0); QObject::disconnect(containment.data(), 0, q, 0);
QObject *oldGraphicObject = containment.data()->property("graphicObject").value<QObject *>(); QObject *oldGraphicObject = containment.data()->property("graphicObject").value<QObject *>();
if (oldGraphicObject) { if (oldGraphicObject) {
qDebug() << "Old graphics Object:" << oldGraphicObject << "Old containment" << containment.data();
//make sure the graphic object won't die with us //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::DesktopContainment ||
cont->containmentType() == Plasma::Types::CustomContainment)); cont->containmentType() == Plasma::Types::CustomContainment));
graphicObject->setProperty("parent", QVariant::fromValue(q->rootObject())); graphicObject->setProperty("parent", QVariant::fromValue(q->rootObject()));
graphicObject->setProperty("visible", true);
q->rootObject()->setProperty("containment", QVariant::fromValue(graphicObject)); q->rootObject()->setProperty("containment", QVariant::fromValue(graphicObject));
} else { } else {
qWarning() << "Containment graphic object not valid"; qWarning() << "Containment graphic object not valid";

View File

@ -42,7 +42,7 @@
Activity::Activity(const QString &id, Plasma::Corona *parent) Activity::Activity(const QString &id, Plasma::Corona *parent)
: QObject(parent), : QObject(parent),
m_id(id), m_id(id),
m_plugin("default"), m_plugin("org.kde.desktopcontainment"),
m_info(new KActivities::Info(id, this)), m_info(new KActivities::Info(id, this)),
m_activityConsumer(new KActivities::Consumer(this)), m_activityConsumer(new KActivities::Consumer(this)),
m_corona(parent), m_corona(parent),
@ -62,8 +62,9 @@ Activity::Activity(const QString &id, Plasma::Corona *parent)
//find your containments //find your containments
foreach (Plasma::Containment *cont, m_corona->containments()) { foreach (Plasma::Containment *cont, m_corona->containments()) {
if (cont->containmentType() == Plasma::Types::DesktopContainment || if ((cont->containmentType() == Plasma::Types::DesktopContainment ||
cont->containmentType() == Plasma::Types::CustomContainment) { cont->containmentType() == Plasma::Types::CustomContainment) &&
cont->activity() == id) {
insertContainment(cont); insertContainment(cont);
} }
} }
@ -172,7 +173,7 @@ Plasma::Containment* Activity::containmentForScreen(int screen)
if (!containment || !containment->activity().isEmpty()) { if (!containment || !containment->activity().isEmpty()) {
// possibly a plugin failure, let's go for the default // 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 //we don't want to steal contaiments from other activities
@ -191,7 +192,7 @@ Plasma::Containment* Activity::containmentForScreen(int screen)
if (!containment) { if (!containment) {
// possibly a plugin failure, let's go for the default // 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) { if (containment) {

View File

@ -31,7 +31,9 @@
#include <klocalizedstring.h> #include <klocalizedstring.h>
#include <Plasma/Package> #include <Plasma/Package>
#include <Plasma/PluginLoader> #include <Plasma/PluginLoader>
#include <kactivities/controller.h>
#include "activity.h"
#include "desktopview.h" #include "desktopview.h"
#include "panelview.h" #include "panelview.h"
#include "scripting/desktopscriptengine.h" #include "scripting/desktopscriptengine.h"
@ -40,9 +42,11 @@
class ShellCorona::Private { class ShellCorona::Private {
public: public:
Private() Private(ShellCorona *corona)
: desktopWidget(QApplication::desktop()), : q(corona),
widgetExplorerView(nullptr) desktopWidget(QApplication::desktop()),
widgetExplorerView(nullptr),
activityController(new KActivities::Controller(q))
{ {
appConfigSyncTimer.setSingleShot(true); appConfigSyncTimer.setSingleShot(true);
// constant controlling how long between requesting a configuration sync // constant controlling how long between requesting a configuration sync
@ -50,15 +54,18 @@ public:
appConfigSyncTimer.setInterval(10000); appConfigSyncTimer.setInterval(10000);
} }
ShellCorona *q;
QString shell; QString shell;
QDesktopWidget * desktopWidget; QDesktopWidget * desktopWidget;
QList <DesktopView *> views; QList <DesktopView *> views;
WidgetExplorerView * widgetExplorerView; WidgetExplorerView * widgetExplorerView;
KActivities::Controller *activityController;
QHash <Plasma::Containment *, PanelView *> panelViews; QHash <Plasma::Containment *, PanelView *> panelViews;
KConfigGroup desktopDefaultsConfig; KConfigGroup desktopDefaultsConfig;
WorkspaceScripting::DesktopScriptEngine * scriptEngine; WorkspaceScripting::DesktopScriptEngine * scriptEngine;
QList<Plasma::Containment *> waitingPanels; QList<Plasma::Containment *> waitingPanels;
QSet<Plasma::Containment *> loadingDesktops; QSet<Plasma::Containment *> loadingDesktops;
QHash<QString, Activity*> activities;
QTimer appConfigSyncTimer; QTimer appConfigSyncTimer;
}; };
@ -70,7 +77,8 @@ WorkspaceScripting::DesktopScriptEngine * ShellCorona::scriptEngine() const
ShellCorona::ShellCorona(QObject *parent) 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"); d->desktopDefaultsConfig = KConfigGroup(KSharedConfig::openConfig(package().filePath("defaults")), "Desktop");
@ -107,6 +115,15 @@ ShellCorona::ShellCorona(QObject *parent)
dashboardAction->setShortcut(QKeySequence("ctrl+f12")); dashboardAction->setShortcut(QKeySequence("ctrl+f12"));
dashboardAction->setShortcutContext(Qt::ApplicationShortcut); 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() ShellCorona::~ShellCorona()
@ -146,6 +163,7 @@ void ShellCorona::load()
} }
processUpdateScripts(); processUpdateScripts();
checkActivities();
checkScreens(); 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) 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) //buggy (sometimes the containment thinks it's already on the screen, so no view is created)
//TODO: restore activities //TODO: restore activities
//Activity *currentActivity = activity(d->activityController->currentActivity()); Activity *currentActivity = activity(d->activityController->currentActivity());
//ensure the desktop(s) have a containment and view //ensure the desktop(s) have a containment and view
checkDesktop(/*currentActivity,*/ signalWhenExists, screen); checkDesktop(currentActivity, signalWhenExists, screen);
//ensure the panels get views too //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 //TODO: remove following when activities are restored
if (!c) { 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) void ShellCorona::printScriptError(const QString &error)
{ {
qWarning() << error; qWarning() << error;

View File

@ -28,11 +28,16 @@ namespace Plasma
class Applet; class Applet;
} // namespace Plasma } // namespace Plasma
class Activity;
class PanelView; class PanelView;
namespace WorkspaceScripting { namespace WorkspaceScripting {
class DesktopScriptEngine; class DesktopScriptEngine;
} }
namespace KActivities {
class Controller;
}
class ShellCorona : public Plasma::Corona class ShellCorona : public Plasma::Corona
{ {
Q_OBJECT Q_OBJECT
@ -58,7 +63,7 @@ public:
*/ */
void checkScreen(int screen, bool signalWhenExists = false); 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; int numScreens() const;
QRect screenGeometry(int id) const; QRect screenGeometry(int id) const;
@ -114,6 +119,9 @@ protected Q_SLOTS:
*/ */
void processUpdateScripts(); void processUpdateScripts();
Activity* activity(const QString &id);
KActivities::Controller *activityController();
private Q_SLOTS: private Q_SLOTS:
void checkLoadingDesktopsComplete(); void checkLoadingDesktopsComplete();
@ -121,6 +129,10 @@ private Q_SLOTS:
void showWidgetExplorer(); void showWidgetExplorer();
void syncAppConfig(); void syncAppConfig();
void setDashboardShown(bool show); void setDashboardShown(bool show);
void checkActivities();
void currentActivityChanged(const QString &newActivity);
void activityAdded(const QString &id);
void activityRemoved(const QString &id);
private: private:
class Private; class Private;