SVN commit 1216838 by aseigo: move all launcher config reading/saving into GroupManager GroupManager can now have a config group provided by a subclass; a siple set/get method pair wasn't enough as Applet::config() can change without notice (principle: Applets should never hang on to the results of config(), but call it, use it, then discard the value upon returning from the method it is used in) upsides: * this is all in one neat, centralized place allowing launcher config to be used amongst multiple implementations * less code duplication just to satisfy config * the launcher[Added|Removed] signals are now gone, which gets rid of the somewhat ugly implementation detail that there were multiple ways to find out when a launcher was added, some more direct than others also, adds a configChanged signal which allows launchers to be saved immediately to the config, safe(r) against interuptions / crashes M +125 -16 libs/taskmanager/groupmanager.cpp M +16 -5 libs/taskmanager/groupmanager.h M +0 -2 plasma/desktop/applets/tasks/taskitemlayout.h M +23 -42 plasma/desktop/applets/tasks/tasks.cpp M +7 -5 plasma/desktop/applets/tasks/tasks.h --- trunk/KDE/kdebase/workspace/libs/taskmanager/groupmanager.cpp #1216837:1216838 @@ -23,6 +23,7 @@ #include "groupmanager.h" +#include #include #include #include @@ -64,7 +65,8 @@ showOnlyCurrentScreen(false), showOnlyMinimized(false), onlyGroupWhenFull(false), - changingGroupingStrategy(false) + changingGroupingStrategy(false), + readingLauncherConfig(false) { } @@ -89,6 +91,10 @@ void removeStartup(StartupPtr); void launcherVisibilityChange(); void checkLauncherVisibility(LauncherItem *launcher); + void saveLauncher(LauncherItem *launcher); + void saveLauncher(LauncherItem *launcher, KConfigGroup &group); + void unsaveLauncher(LauncherItem *launcher); + KConfigGroup launcherConfig(const KConfigGroup &config = KConfigGroup()); TaskGroup *currentRootGroup(); @@ -105,18 +111,20 @@ QTimer checkIfFullTimer; QSet geometryTasks; int groupIsFullLimit; + QUuid configToken; + + QHash > rootGroups; //container for groups + QHash launchers; + int currentDesktop; + QString currentActivity; + bool showOnlyCurrentDesktop : 1; bool showOnlyCurrentActivity : 1; bool showOnlyCurrentScreen : 1; bool showOnlyMinimized : 1; bool onlyGroupWhenFull : 1; bool changingGroupingStrategy : 1; - QUuid configToken; - - QHash > rootGroups; //container for groups - QHash launchers; - int currentDesktop; - QString currentActivity; + bool readingLauncherConfig : 1; }; @@ -145,7 +153,6 @@ d->checkIfFullTimer.setSingleShot(true); d->checkIfFullTimer.setInterval(0); connect(&d->checkIfFullTimer, SIGNAL(timeout()), this, SLOT(actuallyCheckIfFull())); - } GroupManager::~GroupManager() @@ -535,7 +542,7 @@ void GroupManager::reconnect() { - kDebug(); + //kDebug(); disconnect(TaskManager::self(), SIGNAL(desktopChanged(int)), this, SLOT(currentDesktopChanged(int))); disconnect(TaskManager::self(), SIGNAL(activityChanged(QString)), @@ -566,6 +573,11 @@ d->reloadTasks(); } +KConfigGroup GroupManager::config() const +{ + return KConfigGroup(); +} + bool GroupManager::addLauncher(const KUrl &url, QIcon icon, QString name, QString genericName) { if (url.isEmpty()) { @@ -605,7 +617,7 @@ d->launchers.insert(url, launcher); connect(launcher, SIGNAL(show(bool)), this, SLOT(launcherVisibilityChange())); d->checkLauncherVisibility(launcher); - emit launcherAdded(launcher); + d->saveLauncher(launcher); } return launcher; @@ -627,7 +639,7 @@ } } - emit launcherRemoved(launcher); + d->unsaveLauncher(launcher); launcher->deleteLater(); } @@ -638,7 +650,6 @@ void GroupManagerPrivate::checkLauncherVisibility(LauncherItem *launcher) { - kDebug() << "booyah, bitches!" << launcher; if (!launcher) { return; } @@ -660,10 +671,18 @@ return d->launchers.value(url); } -void GroupManager::readLauncherConfig(const KConfigGroup &config) +void GroupManager::readLauncherConfig(const KConfigGroup &cg) { - foreach (const QString &key, config.keyList()) { - QStringList item = config.readEntry(key, QStringList()); + KConfigGroup conf = d->launcherConfig(cg); + if (!conf.isValid()) { + return; + } + + // prevents re-writing the results out + d->readingLauncherConfig = true; + QSet urls; + foreach (const QString &key, conf.keyList()) { + QStringList item = conf.readEntry(key, QStringList()); if (item.length() >= 4) { KUrl url(item.at(0)); KIcon icon; @@ -677,11 +696,101 @@ } QString name(item.at(2)); QString genericName(item.at(3)); - addLauncher(url, icon, name, genericName); + + if (addLauncher(url, icon, name, genericName)) { + urls << url; } } } + d->readingLauncherConfig = false; + + // a bit paranoiac, perhaps, but we check the removals first and then + // remove the launchers after that scan because Qt's iterators operate + // on a copy of the list and/or don't like multiple iterators messing + // with the same list. we might get away with just calling removeLauncher + // immediately without the removals KUrl::List, but this is known safe + // and not a performance bottleneck + KUrl::List removals; + foreach (LauncherItem *launcher, d->launchers) { + if (!urls.contains(launcher->launcherUrl())) { + removals << launcher->launcherUrl(); + } + } + + foreach (const KUrl &url, removals) { + removeLauncher(url); + } +} + +void GroupManager::exportLauncherConfig(const KConfigGroup &cg) +{ + KConfigGroup conf = d->launcherConfig(cg); + if (!conf.isValid()) { + return; + } + + foreach (LauncherItem *launcher, d->launchers) { + d->saveLauncher(launcher, conf); + } +} + +KConfigGroup GroupManagerPrivate::launcherConfig(const KConfigGroup &config) +{ + KConfigGroup cg = config.isValid() ? config : q->config(); + if (!cg.isValid()) { + return cg; + } + + return KConfigGroup(&cg, "Launchers"); +} + +void GroupManagerPrivate::saveLauncher(LauncherItem *launcher) +{ + if (readingLauncherConfig) { + return; + } + + KConfigGroup cg = launcherConfig(); + if (!cg.isValid()) { + return; + } + + saveLauncher(launcher, cg); + emit q->configChanged(); +} + +void GroupManagerPrivate::saveLauncher(LauncherItem *launcher, KConfigGroup &cg) +{ + QVariantList launcherProperties; + launcherProperties.append(launcher->launcherUrl().url()); + launcherProperties.append(launcher->icon().name()); + launcherProperties.append(launcher->name()); + launcherProperties.append(launcher->genericName()); + + if (launcher->icon().name().isEmpty()) { + QPixmap pixmap = launcher->icon().pixmap(QSize(64,64)); + QByteArray bytes; + QBuffer buffer(&bytes); + buffer.open(QIODevice::WriteOnly); + pixmap.save(&buffer, "PNG"); + launcherProperties.append(bytes.toBase64()); + } + + cg.writeEntry(launcher->name(), launcherProperties); +} + +void GroupManagerPrivate::unsaveLauncher(LauncherItem *launcher) +{ + KConfigGroup cg = launcherConfig(); + if (!cg.isValid()) { + return; + } + + cg.deleteEntry(launcher->name()); + emit q->configChanged(); +} + bool GroupManager::onlyGroupWhenFull() const { return d->onlyGroupWhenFull; --- trunk/KDE/kdebase/workspace/libs/taskmanager/groupmanager.h #1216837:1216838 @@ -132,21 +132,32 @@ /** Adds a Launcher for the executable/.desktop-file at url and returns a reference to the launcher*/ bool addLauncher(const KUrl &url, QIcon icon = QIcon(), QString name = QString(), QString genericName = QString()); + /** Removes the given launcher*/ void removeLauncher(const KUrl &url); + /** @return true if there is a matching launcher */ bool launcherExists(const KUrl &url) const; bool launcherExistsForUrl(const KUrl &url) const; - void readLauncherConfig(const KConfigGroup &config); + /** call when the launcher config should be read or re-read */ + void readLauncherConfig(const KConfigGroup &config = KConfigGroup()); + + /** exports the launcher config to a given config group; usually not needed + if config() is reimplemented to provide a valid config group */ + void exportLauncherConfig(const KConfigGroup &config); + +protected: + // reimplement to provide a config group to read/write settings to + virtual KConfigGroup config() const; + Q_SIGNALS: /** Signal that the rootGroup has to be reloaded in the visualization */ void reload(); - /** Signal that a Launcher has been added*/ - void launcherAdded(LauncherItem*); - /** Signal that a Launcher has been removed*/ - void launcherRemoved(LauncherItem*); + /** Signal that the configuration writen to the config file has changed */ + void configChanged(); + private: Q_PRIVATE_SLOT(d, void currentDesktopChanged(int)) Q_PRIVATE_SLOT(d, void currentActivityChanged(QString)) --- trunk/KDE/kdebase/workspace/plasma/desktop/applets/tasks/taskitemlayout.h #1216837:1216838 @@ -34,9 +34,7 @@ using TaskManager::StartupPtr; using TaskManager::TaskPtr; -using TaskManager::GroupManager; - /** * A Layout for the expanded group */ --- trunk/KDE/kdebase/workspace/plasma/desktop/applets/tasks/tasks.cpp #1216837:1216838 @@ -25,6 +25,7 @@ #include "ui_tasksConfig.h" //Taskmanager +#include #include #include @@ -44,6 +45,25 @@ #include #include +class GroupManager : public TaskManager::GroupManager +{ +public: + GroupManager(Plasma::Applet *applet) + : TaskManager::GroupManager(applet), + m_applet(applet) + { + } + +protected: + KConfigGroup config() const + { + return m_applet->config(); + } + +private: + Plasma::Applet *m_applet; +}; + Tasks::Tasks(QObject* parent, const QVariantList &arguments) : Plasma::Applet(parent, arguments), m_showTooltip(false), @@ -79,18 +99,14 @@ void Tasks::init() { - m_groupManager = new TaskManager::GroupManager(this); + m_groupManager = new GroupManager(this); Plasma::Containment* appletContainment = containment(); if (appletContainment) { m_groupManager->setScreen(appletContainment->screen()); } - //FIXME: the order of creation and setting of items in this method is both fragile (from - // personal experience tinking with it) and convoluted. It should be possible to - // set up the GroupManager firt, and *then* create the root TaskGroupItem. - connect(m_groupManager, SIGNAL(reload()), this, SLOT(reload())); - //connect(this, SIGNAL(settingsChanged()), m_groupManager, SLOT(reconnect())); + connect(m_groupManager, SIGNAL(configChanged()), this, SIGNAL(configNeedsSaving())); m_rootGroupItem = new TaskGroupItem(this, this); m_rootGroupItem->expand(); @@ -105,18 +121,14 @@ connect(m_rootGroupItem, SIGNAL(sizeHintChanged(Qt::SizeHint)), this, SLOT(changeSizeHint(Qt::SizeHint))); setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding)); - //like in Qt's designer - //TODO : Qt's bug?? setMaximumSize(INT_MAX,INT_MAX); layout = new QGraphicsLinearLayout(this); layout->setContentsMargins(0,0,0,0); layout->setSizePolicy(QSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding)); - //TODO : Qt's bug?? layout->setMaximumSize(INT_MAX,INT_MAX); layout->setOrientation(Qt::Vertical); layout->addItem(m_rootGroupItem); - setLayout(layout); configChanged(); @@ -201,8 +213,7 @@ changed = true; } - KConfigGroup launcherCg(&cg, "Launchers"); - m_groupManager->readLauncherConfig(launcherCg); + m_groupManager->readLauncherConfig(); if (changed) { emit settingsChanged(); @@ -210,36 +221,6 @@ } } -void Tasks::launcherAdded(LauncherItem *launcher) -{ - KConfigGroup cg = config(); - KConfigGroup launcherCg(&cg, "Launchers"); - - QVariantList launcherProperties; - launcherProperties.append(launcher->launcherUrl().url()); - launcherProperties.append(launcher->icon().name()); - launcherProperties.append(launcher->name()); - launcherProperties.append(launcher->genericName()); - - if (launcher->icon().name().isEmpty()) { - QPixmap pixmap = launcher->icon().pixmap(QSize(64,64)); - QByteArray bytes; - QBuffer buffer(&bytes); - buffer.open(QIODevice::WriteOnly); - pixmap.save(&buffer, "PNG"); - launcherProperties.append(bytes.toBase64()); - } - - launcherCg.writeEntry(launcher->name(), launcherProperties); -} - -void Tasks::launcherRemoved(LauncherItem *launcher ) -{ - KConfigGroup cg = config(); - KConfigGroup launcherCg(&cg, "Launchers"); - launcherCg.deleteEntry(launcher->name()); -} - void Tasks::reload() { TaskGroup *newGroup = m_groupManager->rootGroup(); --- trunk/KDE/kdebase/workspace/plasma/desktop/applets/tasks/tasks.h #1216837:1216838 @@ -48,18 +48,23 @@ class FrameSvg; } // namespace Plasma -class TaskGroupItem; +namespace TaskManager +{ + class GroupManager; +} // namespace TaskManager using TaskManager::StartupPtr; using TaskManager::TaskPtr; using TaskManager::StartupPtr; using TaskManager::GroupPtr; using TaskManager::AbstractGroupableItem; -using TaskManager::GroupManager; using TaskManager::TaskItem; using TaskManager::TaskGroup; using TaskManager::LauncherItem; +class TaskGroupItem; +class GroupManager; + /** * An applet which provides a visual representation of running * graphical tasks (ie. tasks that have some form of visual interface), @@ -95,7 +100,6 @@ void resizeItemBackground(const QSizeF &newSize); TaskGroupItem* rootGroupItem(); - TaskManager::GroupManager &groupManager() const; Qt::KeyboardModifiers groupModifierKey() const; @@ -135,8 +139,6 @@ void reload(); void changeSizeHint(Qt::SizeHint which); void dialogGroupingChanged(int index); - void launcherAdded(LauncherItem *launcher); - void launcherRemoved(LauncherItem *launcher); private: bool m_showTooltip;