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 *oldGraphicObject = containment.data()->property("graphicObject").value<QObject *>();
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";

View File

@ -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) {

View File

@ -31,7 +31,9 @@
#include <klocalizedstring.h>
#include <Plasma/Package>
#include <Plasma/PluginLoader>
#include <kactivities/controller.h>
#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 <DesktopView *> views;
WidgetExplorerView * widgetExplorerView;
KActivities::Controller *activityController;
QHash <Plasma::Containment *, PanelView *> panelViews;
KConfigGroup desktopDefaultsConfig;
WorkspaceScripting::DesktopScriptEngine * scriptEngine;
QList<Plasma::Containment *> waitingPanels;
QSet<Plasma::Containment *> loadingDesktops;
QHash<QString, Activity*> 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;

View File

@ -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;