diff --git a/src/kcmodulecontainer.cpp b/src/kcmodulecontainer.cpp index 7576cf7..c5dba5c 100644 --- a/src/kcmodulecontainer.cpp +++ b/src/kcmodulecontainer.cpp @@ -1,189 +1,189 @@ /* This file is part of the KDE libraries Copyright (C) 2004 Frans Englich This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kcmodulecontainer.h" #include #include #include #include #include #include #include #include #include typedef QList ModuleList; /***********************************************************************/ class KCModuleContainer::KCModuleContainerPrivate { public: KCModuleContainerPrivate(const QStringList &mods) : modules(mods) - , tabWidget(0) - , topLayout(0) + , tabWidget(nullptr) + , topLayout(nullptr) {} QStringList modules; QTabWidget *tabWidget; KCModule::Buttons buttons; QVBoxLayout *topLayout; /** * A list containing KCModuleProxy objects which * have changed and must be saved. */ ModuleList changedModules; /** * A list of all modules which are encapsulated. */ ModuleList allModules; }; /***********************************************************************/ // The KCModuleContainer is only a wrapper around real KCModules. /***********************************************************************/ KCModuleContainer::KCModuleContainer(QWidget *parent, const QString &mods) : KCModule(parent), d(new KCModuleContainerPrivate(QString(mods).remove(QLatin1Char(' ')).split(QLatin1Char(','), QString::SkipEmptyParts))) { init(); } KCModuleContainer::KCModuleContainer(QWidget *parent, const QStringList &mods) : KCModule(parent), d(new KCModuleContainerPrivate(mods)) { init(); } void KCModuleContainer::init() { d->topLayout = new QVBoxLayout(this); d->topLayout->setMargin(0); d->topLayout->setObjectName(QStringLiteral("topLayout")); d->tabWidget = new QTabWidget(this); d->tabWidget->setObjectName(QStringLiteral("tabWidget")); connect(d->tabWidget, &QTabWidget::currentChanged, this, &KCModuleContainer::tabSwitched); d->topLayout->addWidget(d->tabWidget); if (!d->modules.isEmpty()) { /* Add our modules */ for (QStringList::const_iterator it = d->modules.constBegin(); it != d->modules.constEnd(); ++it) { addModule((*it)); } } } void KCModuleContainer::addModule(const QString &module) { /* In case it doesn't exist we just silently drop it. * This allows people to easily extend containers. * For example, KCM monitor gamma can be in kdegraphics. */ KService::Ptr service = KService::serviceByDesktopName(module); if (!service) { // qDebug() << "KCModuleContainer: module '" << // module << "' was not found and thus not loaded" << endl; return; } if (service->noDisplay()) { return; } KCModuleProxy *proxy = new KCModuleProxy(service, d->tabWidget); d->allModules.append(proxy); proxy->setObjectName(module); d->tabWidget->addTab(proxy, QIcon::fromTheme(proxy->moduleInfo().icon()), /* Qt eats ampersands for dinner. But not this time. */ proxy->moduleInfo().moduleName().replace(QLatin1Char('&'), QStringLiteral("&&"))); d->tabWidget->setTabToolTip(d->tabWidget->indexOf(proxy), proxy->moduleInfo().comment()); connect(proxy, SIGNAL(changed(KCModuleProxy*)), SLOT(moduleChanged(KCModuleProxy*))); /* Collect our buttons - we go for the common deliminator */ setButtons(buttons() | proxy->realModule()->buttons()); } void KCModuleContainer::tabSwitched(int index) { KCModuleProxy *mod = static_cast(d->tabWidget->widget(index)); setQuickHelp(mod->quickHelp()); setAboutData(mod->aboutData()); } void KCModuleContainer::save() { ModuleList list = d->changedModules; ModuleList::iterator it; for (it = list.begin(); it != list.end(); ++it) { (*it)->save(); } emit changed(false); } void KCModuleContainer::load() { ModuleList list = d->allModules; ModuleList::iterator it; for (it = list.begin(); it != list.end(); ++it) { (*it)->load(); } emit changed(false); } void KCModuleContainer::defaults() { ModuleList list = d->allModules; ModuleList::iterator it; for (it = list.begin(); it != list.end(); ++it) { (*it)->defaults(); } emit changed(true); } void KCModuleContainer::moduleChanged(KCModuleProxy *proxy) { d->changedModules.append(proxy); if (d->changedModules.isEmpty()) { return; } emit changed(true); } KCModuleContainer::~KCModuleContainer() { delete d; } /***********************************************************************/ diff --git a/src/kcmoduleloader.cpp b/src/kcmoduleloader.cpp index 4090ac1..db52f29 100644 --- a/src/kcmoduleloader.cpp +++ b/src/kcmoduleloader.cpp @@ -1,170 +1,170 @@ /* Copyright (c) 1999 Matthias Hoelzer-Kluepfel Copyright (c) 2000 Matthias Elter Copyright (c) 2003,2004,2006 Matthias Kretz Copyright (c) 2004 Frans Englich This file is part of the KDE project This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2, as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kcmoduleloader.h" #include "kcmoduleqml_p.h" #include #include #include #include #include #include #include #include #include #include using namespace KCModuleLoader; /***************************************************************/ /** * When something goes wrong in loading the module, this one * jumps in as a "dummy" module. */ class KCMError : public KCModule { public: KCMError(const QString &msg, const QString &details, QWidget *parent) : KCModule(parent) { QVBoxLayout *topLayout = new QVBoxLayout(this); QLabel *lab = new QLabel(msg, this); lab->setWordWrap(true); topLayout->addWidget(lab); lab = new QLabel(details, this); lab->setWordWrap(true); topLayout->addWidget(lab); } }; /***************************************************************/ KCModule *KCModuleLoader::loadModule(const QString &module, ErrorReporting report, QWidget *parent, const QStringList &args) { return loadModule(KCModuleInfo(module), report, parent, args); } KCModule *KCModuleLoader::loadModule(const KCModuleInfo &mod, ErrorReporting report, QWidget *parent, const QStringList &args) { /* * Simple libraries as modules are the easiest case: * We just have to load the library and get the module * from the factory. */ if (!mod.service()) return reportError(report, i18n("The module %1 could not be found.", mod.moduleName()), i18n("

The diagnosis is:
The desktop file %1 could not be found.

", mod.fileName()), parent); if (mod.service()->noDisplay()) return reportError(report, i18n("The module %1 is disabled.", mod.moduleName()), i18n("

Either the hardware/software the module configures is not available or the module has been disabled by the administrator.

"), parent); if (!mod.library().isEmpty()) { QString error; QVariantList args2; foreach (const QString &arg, args) { args2 << arg; } KCModule *module = mod.service()->createInstance(parent, args2, &error); if (module) { return module; } else { KPluginLoader loader(KPluginLoader::findPlugin(QLatin1String("kcms/") + mod.service()->library())); KPluginFactory* factory = loader.factory(); if (!factory) { qWarning() << "Error loading plugin:" << loader.errorString(); } else { KQuickAddons::ConfigModule *cm = factory->create(); if (!cm) { qWarning() << "Error creating object from plugin" << loader.fileName(); } module = new KCModuleQml(cm, parent, args2); return module; } } //#ifndef NDEBUG { // get the create_ function QLibrary lib(KPluginLoader::findPlugin(mod.library())); if (lib.load()) { KCModule *(*create)(QWidget *, const char *); QByteArray factorymethod("create_"); factorymethod += mod.handle().toLatin1(); create = reinterpret_cast(lib.resolve(factorymethod.constData())); if (create) { return create(parent, mod.handle().toLatin1().constData()); qFatal("This module still uses a custom factory method (%s). This is not supported anymore. Please fix the module.", factorymethod.constData()); } else { qWarning() << "This module has no valid entry symbol at all. The reason could be that it's still using K_EXPORT_COMPONENT_FACTORY with a custom X-KDE-FactoryName which is not supported anymore"; } lib.unload(); } } //#endif // NDEBUG return reportError(report, error, QString(), parent); } /* * Ok, we could not load the library. * Try to run it as an executable. * This must not be done when calling from kcmshell, or you'll * have infinite recursion * (startService calls kcmshell which calls modloader which calls startService...) * */ return reportError(report, i18n("The module %1 is not a valid configuration module.", mod.moduleName()), i18n("The diagnosis is:
The desktop file %1 does not specify a library.
", mod.fileName()), parent); } void KCModuleLoader::unloadModule(const KCModuleInfo &mod) { // get the library loader instance KPluginLoader loader(mod.library()); loader.unload(); } KCModule *KCModuleLoader::reportError(ErrorReporting report, const QString &text, const QString &details, QWidget *parent) { QString realDetails = details; if (realDetails.isNull()) { realDetails = i18n("

Possible reasons:

  • An error occurred during your last " "KDE upgrade leaving an orphaned control module
  • You have old third party " "modules lying around.

Check these points carefully and try to remove " "the module mentioned in the error message. If this fails, consider contacting " "your distributor or packager.

"); } if (report & KCModuleLoader::Dialog) { KMessageBox::detailedError(parent, text, realDetails); } if (report & KCModuleLoader::Inline) { return new KCMError(text, realDetails, parent); } - return 0; + return nullptr; } diff --git a/src/kcmoduleloader.h b/src/kcmoduleloader.h index ada449b..dbcd1d5 100644 --- a/src/kcmoduleloader.h +++ b/src/kcmoduleloader.h @@ -1,109 +1,109 @@ /* Copyright (c) 1999 Matthias Hoelzer-Kluepfel Copyright (c) 2002-2003 Daniel Molkentin Copyright (c) 2006 Matthias Kretz This file is part of the KDE project This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2, as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KCMODULELOADER_H #define KCMODULELOADER_H #include #include class QWidget; /** * @short Loads a KControl Module. * * KCModuleLoader tries in several ways * to locate and load a KCModule. If loading fails a * zero pointer is returned. \n * It is very unlikely KCModuleLoader is what you want * and @ref KCModuleProxy suits your needs. * * @author Matthias Hoelzer-Kluepfel * @author Frans Englich * @internal **/ namespace KCModuleLoader { /** * Determines the way errors are reported */ enum ErrorReporting { /** * no error reporting is done * */ None = 0, /** * the error report is shown instead of the * KCModule that should have * been loaded */ Inline = 1, /** * shows a dialog with the error report */ Dialog = 2, /** * does both Inline and Dialog */ Both = 3 }; /** * Loads a @ref KCModule. If loading fails a zero pointer is returned. * @param module what module to load * @param report see ErrorReporting * * @return a pointer to the loaded @ref KCModule */ KCMUTILS_EXPORT KCModule *loadModule(const KCModuleInfo &module, ErrorReporting - report, QWidget *parent = 0, const QStringList &args = QStringList()); + report, QWidget *parent = nullptr, const QStringList &args = QStringList()); /** * Loads a @ref KCModule. If loading fails a zero pointer is returned. * * @param module what module to load * @param report see ErrorReporting * * @return a pointer to the loaded @ref KCModule */ KCMUTILS_EXPORT KCModule *loadModule(const QString &module, ErrorReporting report, - QWidget *parent = 0, const QStringList &args = QStringList()); + QWidget *parent = nullptr, const QStringList &args = QStringList()); /** * Unloads the module's library * @param mod What module to unload for */ KCMUTILS_EXPORT void unloadModule(const KCModuleInfo &mod); /** * Returns a KCModule containing the messages @p report and @p text. * * @param report the type of error reporting, see ErrorReporting * @param text the main message * @param details any additional details * * @internal */ KCMUTILS_EXPORT KCModule *reportError(ErrorReporting report, const QString &text, const QString &details, QWidget *parent); } #endif // KCMODULELOADER_H diff --git a/src/kcmoduleproxy.cpp b/src/kcmoduleproxy.cpp index 9cfaa06..82327ac 100644 --- a/src/kcmoduleproxy.cpp +++ b/src/kcmoduleproxy.cpp @@ -1,339 +1,339 @@ /* This file is part of the KDE project Copyright (C) 2004 Frans Englich Copyright (C) 2003 Matthias Kretz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kcmoduleproxy.h" #include "kcmoduleproxy_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kcolorscheme.h" #include "ksettingswidgetadaptor.h" /* TODO: - Two Layout problems in runAsRoot: * lblBusy doesn't show * d->kcm/d->rootInfo doesn't get it right when the user presses cancel in the kdesu dialog - Resizing horizontally is contrained; minimum size is set somewhere. It appears to be somehow derived from the module's size. - Prettify: set icon in KCMultiDialog. */ /***************************************************************/ KCModule *KCModuleProxy::realModule() const { Q_D(const KCModuleProxy); /* * Note, don't call any function that calls realModule() since * that leads to an infinite loop. */ /* Already loaded */ if (!d->kcm) { QApplication::setOverrideCursor(Qt::WaitCursor); const_cast(d)->loadModule(); QApplication::restoreOverrideCursor(); } return d->kcm; } void KCModuleProxyPrivate::loadModule() { if (!topLayout) { topLayout = new QVBoxLayout(parent); topLayout->setMargin(0); QString name = modInfo.handle(); name.replace(QLatin1Char('-'), QLatin1Char('_')); // hyphen is not allowed in dbus, only [A-Z][a-z][0-9]_ name.replace(QLatin1Char('/'), QLatin1Char('_')); // same goes for '/' dbusService = QLatin1String("org.kde.internal.KSettingsWidget_") + name; // for dbus path, we also need to convert '.' characters name.replace(QLatin1Char('.'), QLatin1Char('_')); dbusPath = QLatin1String("/internal/KSettingsWidget/") + name; } if (QDBusConnection::sessionBus().registerService(dbusService) || bogusOccupier) { /* We got the name we requested, because no one was before us, * or, it was an random application which had picked that name */ // qDebug() << "Module not already loaded, loading module " << modInfo.moduleName() << " from library " << modInfo.library() << " using symbol " << modInfo.handle(); kcm = KCModuleLoader::loadModule(modInfo, KCModuleLoader::Inline, parent, args); QObject::connect(kcm, SIGNAL(changed(bool)), parent, SLOT(_k_moduleChanged(bool))); QObject::connect(kcm, SIGNAL(destroyed()), parent, SLOT(_k_moduleDestroyed())); QObject::connect(kcm, &KCModule::quickHelpChanged, parent, &KCModuleProxy::quickHelpChanged); parent->setWhatsThis(kcm->quickHelp()); if (kcm->layout()) { kcm->layout()->setMargin(0); } topLayout->addWidget(kcm); if (!modInfo.handle().isEmpty()) { QDBusConnection::sessionBus().registerObject(dbusPath, new KSettingsWidgetAdaptor(parent), QDBusConnection::ExportAllSlots); } if (!rootInfo && /* If it's not already done */ kcm->useRootOnlyMessage() && /* kcm wants root message */ !KUser().isSuperUser()) { /* Not necessary if we're root */ /*rootInfo = new QLabel( parent ); topLayout->insertWidget( 0, rootInfo ); QPalette palette = rootInfo->palette(); KStatefulBrush stbrush(KColorScheme::Window, KColorScheme::NeutralBackground); qDebug() << stbrush.brush(rootInfo); palette.setBrush(QPalette::Window, stbrush.brush(rootInfo)); rootInfo->setPalette(palette); rootInfo->setAutoFillBackground(true); const QString message = kcm->rootOnlyMessage(); if( message.isEmpty() ) rootInfo->setText( i18n( "Changes in this section require root access.
" "On applying your changes you will have to supply your root " "password." ) ); else rootInfo->setText(message); rootInfo->setWhatsThis( i18n( "This section requires special permissions, probably " "for system-wide changes; therefore, it is " "required that you provide the root password to be " "able to change the module's properties. If " "you cannot provide the password, the changes of the " "module cannot be saved " ) );*/ } } else { // qDebug() << "Module already loaded, loading KCMError"; /* Figure out the name of where the module is already loaded */ QDBusInterface proxy(dbusService, dbusPath, QStringLiteral("org.kde.internal.KSettingsWidget")); QDBusReply reply = proxy.call(QStringLiteral("applicationName")); if (reply.isValid()) { QObject::connect(QDBusConnection::sessionBus().interface(), SIGNAL(serviceOwnerChanged(QString,QString,QString)), parent, SLOT(_k_ownerChanged(QString,QString,QString))); kcm = KCModuleLoader::reportError(KCModuleLoader::Inline, i18nc("Argument is application name", "This configuration section is " "already opened in %1", reply.value()), QStringLiteral(" "), parent); topLayout->addWidget(kcm); } else { // qDebug() << "Calling KCModuleProxy's DBus interface for fetching the name failed."; bogusOccupier = true; loadModule(); } } } void KCModuleProxyPrivate::_k_ownerChanged(const QString &service, const QString &oldOwner, const QString &) { if (service == dbusService && !oldOwner.isEmpty()) { // Violence: Get rid of KCMError & CO, so that // realModule() attempts to reload the module delete kcm; - kcm = 0; + kcm = nullptr; Q_Q(KCModuleProxy); q->realModule(); Q_ASSERT(kcm); kcm->show(); } } void KCModuleProxy::showEvent(QShowEvent *ev) { Q_D(KCModuleProxy); (void)realModule(); /* We have no kcm, if we're in root mode */ if (d->kcm) { d->kcm->showEvent(ev); } QWidget::showEvent(ev); } KCModuleProxy::~KCModuleProxy() { deleteClient(); KCModuleLoader::unloadModule(moduleInfo()); delete d_ptr; } void KCModuleProxy::deleteClient() { Q_D(KCModuleProxy); delete d->kcm; - d->kcm = 0; + d->kcm = nullptr; } void KCModuleProxyPrivate::_k_moduleChanged(bool c) { if (changed == c) { return; } Q_Q(KCModuleProxy); changed = c; emit q->changed(c); emit q->changed(q); } void KCModuleProxyPrivate::_k_moduleDestroyed() { - kcm = 0; + kcm = nullptr; } KCModuleProxy::KCModuleProxy(const KService::Ptr &service, QWidget *parent, const QStringList &args) : QWidget(parent), d_ptr(new KCModuleProxyPrivate(this, KCModuleInfo(service), args)) { d_ptr->q_ptr = this; } KCModuleProxy::KCModuleProxy(const KCModuleInfo &info, QWidget *parent, const QStringList &args) : QWidget(parent), d_ptr(new KCModuleProxyPrivate(this, info, args)) { d_ptr->q_ptr = this; } KCModuleProxy::KCModuleProxy(const QString &serviceName, QWidget *parent, const QStringList &args) : QWidget(parent), d_ptr(new KCModuleProxyPrivate(this, KCModuleInfo(serviceName), args)) { d_ptr->q_ptr = this; } void KCModuleProxy::load() { Q_D(KCModuleProxy); if (realModule()) { d->kcm->load(); d->_k_moduleChanged(false); } } void KCModuleProxy::save() { Q_D(KCModuleProxy); if (d->changed && realModule()) { d->kcm->save(); d->_k_moduleChanged(false); } } void KCModuleProxy::defaults() { Q_D(KCModuleProxy); if (realModule()) { d->kcm->defaults(); } } QString KCModuleProxy::quickHelp() const { return realModule() ? realModule()->quickHelp() : QString(); } const KAboutData *KCModuleProxy::aboutData() const { - return realModule() ? realModule()->aboutData() : 0; + return realModule() ? realModule()->aboutData() : nullptr; } KCModule::Buttons KCModuleProxy::buttons() const { if (realModule()) { return realModule()->buttons(); } return KCModule::Buttons(KCModule::Help | KCModule::Default | KCModule::Apply); } bool KCModuleProxy::changed() const { Q_D(const KCModuleProxy); return d->changed; } KCModuleInfo KCModuleProxy::moduleInfo() const { Q_D(const KCModuleProxy); return d->modInfo; } QString KCModuleProxy::dbusService() const { Q_D(const KCModuleProxy); return d->dbusService; } QString KCModuleProxy::dbusPath() const { Q_D(const KCModuleProxy); return d->dbusPath; } QSize KCModuleProxy::minimumSizeHint() const { return QWidget::minimumSizeHint(); } //X void KCModuleProxy::emitQuickHelpChanged() //X { //X emit quickHelpChanged(); //X } /***************************************************************/ #include "moc_kcmoduleproxy.cpp" diff --git a/src/kcmoduleproxy.h b/src/kcmoduleproxy.h index feedf48..59b9b90 100644 --- a/src/kcmoduleproxy.h +++ b/src/kcmoduleproxy.h @@ -1,232 +1,232 @@ /* This file is part of the KDE project Copyright (C) 2003 Matthias Kretz Copyright (C) 2004 Frans Englich This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KCMUTILS_KCMODULEPROXY_H #define KCMUTILS_KCMODULEPROXY_H #include #include #include #include #include class KAboutData; class KCModuleInfo; class KCModuleProxyPrivate; /** * * @brief Encapsulates a KCModule for embedding. * * KCModuleProxy is a wrapper for KCModule intended for cases where * modules are to be displayed. It ensures layout is consistent * and in general takes care of the details * needed for making a module available in an interface. A KCModuleProxy * can be treated as a QWidget, without worrying about the details specific * for modules such as library loading. KCModuleProxy is not a sub class of KCModule * but its API closely resembles KCModule's.\n * Usually, an instance is created by passing one of the constructors a KService::Ptr, * KCModuleInfo or simply the name of the module and then added to the layout as any * other widget. \n * When the user has changed the module, changed(bool) as well as changed(KCModuleProxy *) * is emitted. KCModuleProxy does not take care of prompting for saving - if the object is deleted while * changes is not saved the changes will be lost. changed() returns true if changes are unsaved. \n * \n * KCModuleProxy does not take care of authorization of KCModules. \n * KCModuleProxy implements lazy loading, meaning the library will not be loaded or * any other initialization done before its show() function is called. This means * modules will only be loaded when they are actually needed as well as it is possible to * load many KCModuleProxy without any speed penalty. * * KCModuleProxy should be used in all cases where modules are embedded in order to * promote code efficiency and usability consistency. * * @author Frans Englich * @author Matthias Kretz * */ class KCMUTILS_EXPORT KCModuleProxy : public QWidget { Q_DECLARE_PRIVATE(KCModuleProxy) Q_OBJECT public: /** * Constructs a KCModuleProxy from a KCModuleInfo class. * * @param info The KCModuleInfo to construct the module from. * @param parent the parent QWidget. * @param args This is used in the implementation and is internal. * Use the default. */ - explicit KCModuleProxy(const KCModuleInfo &info, QWidget *parent = 0, + explicit KCModuleProxy(const KCModuleInfo &info, QWidget *parent = nullptr, const QStringList &args = QStringList()); /** * Constructs a KCModuleProxy from a module's service name, which is * equivalent to the desktop file for the kcm without the ".desktop" part. * Otherwise equal to the one above. * * @param serviceName The module's service name to construct from. * @param parent the parent QWidget. * @param args This is used in the implementation and is internal. * Use the default. */ - explicit KCModuleProxy(const QString &serviceName, QWidget *parent = 0, + explicit KCModuleProxy(const QString &serviceName, QWidget *parent = nullptr, const QStringList &args = QStringList()); /** * Constructs a KCModuleProxy from KService. Otherwise equal to the one above. * * @param service The KService to construct from. * @param parent the parent QWidget. * @param args This is used in the implementation and is internal. * Use the default. */ - explicit KCModuleProxy(const KService::Ptr &service, QWidget *parent = 0, + explicit KCModuleProxy(const KService::Ptr &service, QWidget *parent = nullptr, const QStringList &args = QStringList()); /** * Default destructor */ ~KCModuleProxy(); /** * Calling it will cause the contained module to * run its load() routine. */ void load(); /** * Calling it will cause the contained module to * run its save() routine. * * If the module was not modified, it will not be asked * to save. */ void save(); /** * @return the module's quickHelp(); */ QString quickHelp() const; /** * @return the module's aboutData() */ const KAboutData *aboutData() const; /** * @return what buttons the module * needs */ KCModule::Buttons buttons() const; /** * @return true if the module is modified * and needs to be saved. */ bool changed() const; /** * Access to the actual module. * It may return NULL if anything goes wrong. * * @return the encapsulated module. */ KCModule *realModule() const; /** * @return a KCModuleInfo for the encapsulated * module */ KCModuleInfo moduleInfo() const; /** * Returns the DBUS Service name */ QString dbusService() const; /** * Returns the DBUS Path */ QString dbusPath() const; /** * Returns the recommended minimum size for the widget */ QSize minimumSizeHint() const Q_DECL_OVERRIDE; public Q_SLOTS: /** * Calling it will cause the contained module to * load its default values. */ void defaults(); /** * Calling this, results in deleting the contained * module, and unregistering from DCOP. A similar result is achieved * by deleting the KCModuleProxy itself. */ void deleteClient(); Q_SIGNALS: /* * This signal is emitted when the contained module is changed. */ void changed(bool state); /** * This is emitted in the same situations as in the one above. Practical * when several KCModuleProxys are loaded. */ void changed(KCModuleProxy *mod); /** * When a module running with root privileges and exits, returns to normal mode, the * childClosed() signal is emitted. */ void childClosed(); /* * This signal is relayed from the encapsulated module, and * is equivalent to the module's own quickHelpChanged() signal. */ void quickHelpChanged(); protected: /** * Reimplemented for internal purposes. Makes sure the encapsulated * module is loaded before the show event is taken care of. */ void showEvent(QShowEvent *) Q_DECL_OVERRIDE; protected: KCModuleProxyPrivate *const d_ptr; private: Q_PRIVATE_SLOT(d_func(), void _k_moduleChanged(bool)) Q_PRIVATE_SLOT(d_func(), void _k_moduleDestroyed()) Q_PRIVATE_SLOT(d_func(), void _k_ownerChanged(const QString &service, const QString &oldOwner, const QString &newOwner)) }; #endif // KUTILS_KCMODULEPROXY_H diff --git a/src/kcmoduleproxy_p.h b/src/kcmoduleproxy_p.h index 9f555da..924b663 100644 --- a/src/kcmoduleproxy_p.h +++ b/src/kcmoduleproxy_p.h @@ -1,76 +1,76 @@ /* This file is part of the KDE project Copyright (C) 2007 Matthias Kretz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KCMUTILS_KCMODULEPROXY_P_H #define KCMUTILS_KCMODULEPROXY_P_H #include "kcmoduleinfo.h" #include "kcmoduleproxy.h" #include class QVBoxLayout; class KCModuleProxyPrivate { Q_DECLARE_PUBLIC(KCModuleProxy) protected: KCModuleProxyPrivate(KCModuleProxy *_parent, const KCModuleInfo &info, const QStringList &_args) - : args(_args), kcm(0), topLayout(0), rootInfo(0), modInfo(info), + : args(_args), kcm(nullptr), topLayout(nullptr), rootInfo(nullptr), modInfo(info), changed(false), bogusOccupier(false), parent(_parent) { } ~KCModuleProxyPrivate() { delete rootInfo; // Delete before embedWidget! delete kcm; } void loadModule(); /** * Makes sure the proper variables is set and signals are emitted. */ void _k_moduleChanged(bool); /** * Zeroes d->kcm */ void _k_moduleDestroyed(); /** * Gets called by DCOP when an application closes. * Is used to (try to) reload a KCM which previously * was loaded. */ void _k_ownerChanged(const QString &service, const QString &oldOwner, const QString &newOwner); QStringList args; KCModule *kcm; QVBoxLayout *topLayout; /* Contains QScrollView view, and root stuff */ QLabel *rootInfo; QString dbusService; QString dbusPath; KCModuleInfo modInfo; bool changed; bool bogusOccupier; KCModuleProxy *parent; KCModuleProxy *q_ptr; }; #endif // KCMUTILS_KCMODULEPROXY_P_H diff --git a/src/kcmultidialog.cpp b/src/kcmultidialog.cpp index 22592c4..301d24f 100644 --- a/src/kcmultidialog.cpp +++ b/src/kcmultidialog.cpp @@ -1,521 +1,521 @@ /* Copyright (c) 2000 Matthias Elter Copyright (c) 2003 Daniel Molkentin Copyright (c) 2003,2006 Matthias Kretz Copyright (c) 2004 Frans Englich Copyright (c) 2006 Tobias Koenig This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kcmultidialog.h" #include "kcmultidialog_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "kauthaction.h" #include "kauthobjectdecorator.h" #include "kcmoduleproxy.h" bool KCMultiDialogPrivate::resolveChanges(KCModuleProxy *currentProxy) { Q_Q(KCMultiDialog); if (!currentProxy || !currentProxy->changed()) { return true; } // Let the user decide const int queryUser = KMessageBox::warningYesNoCancel( q, i18n("The settings of the current module have changed.\n" "Do you want to apply the changes or discard them?"), i18n("Apply Settings"), KStandardGuiItem::apply(), KStandardGuiItem::discard(), KStandardGuiItem::cancel()); switch (queryUser) { case KMessageBox::Yes: return moduleSave(currentProxy); case KMessageBox::No: currentProxy->load(); return true; case KMessageBox::Cancel: return false; default: Q_ASSERT(false); return false; } } void KCMultiDialogPrivate::_k_slotCurrentPageChanged(KPageWidgetItem *current, KPageWidgetItem *previous) { Q_Q(KCMultiDialog); // qDebug(); q->blockSignals(true); q->setCurrentPage(previous); - KCModuleProxy *previousModule = 0; + KCModuleProxy *previousModule = nullptr; for (int i = 0; i < modules.count(); ++i) { if (modules[ i ].item == previous) { previousModule = modules[ i ].kcm; break; } } if (resolveChanges(previousModule)) { q->setCurrentPage(current); } q->blockSignals(false); // We need to get the state of the now active module _k_clientChanged(); } void KCMultiDialogPrivate::_k_clientChanged() { Q_Q(KCMultiDialog); // qDebug(); // Get the current module - KCModuleProxy *activeModule = 0; + KCModuleProxy *activeModule = nullptr; for (int i = 0; i < modules.count(); ++i) { if (modules[ i ].item == q->currentPage()) { activeModule = modules[ i ].kcm; break; } } bool change = false; if (activeModule) { change = activeModule->changed(); QPushButton *applyButton = q->buttonBox()->button(QDialogButtonBox::Apply); if (applyButton) { q->disconnect(applyButton, &QAbstractButton::clicked, q, &KCMultiDialog::slotApplyClicked); delete applyButton->findChild(); applyButton->setEnabled(change); } QPushButton *okButton = q->buttonBox()->button(QDialogButtonBox::Ok); if (okButton) { q->disconnect(okButton, &QAbstractButton::clicked, q, &KCMultiDialog::slotOkClicked); delete okButton->findChild(); } if (activeModule->realModule()->needsAuthorization()) { if (applyButton) { KAuth::ObjectDecorator *decorator = new KAuth::ObjectDecorator(applyButton); decorator->setAuthAction(activeModule->realModule()->authAction()); activeModule->realModule()->authAction().setParentWidget(activeModule->realModule()); q->connect(decorator, &KAuth::ObjectDecorator::authorized, q, &KCMultiDialog::slotApplyClicked); } if (okButton) { KAuth::ObjectDecorator *decorator = new KAuth::ObjectDecorator(okButton); decorator->setAuthAction(activeModule->realModule()->authAction()); activeModule->realModule()->authAction().setParentWidget(activeModule->realModule()); q->connect(decorator, &KAuth::ObjectDecorator::authorized, q, &KCMultiDialog::slotOkClicked); } } else { if (applyButton) { q->connect(applyButton, &QAbstractButton::clicked, q, &KCMultiDialog::slotApplyClicked); delete applyButton->findChild(); } if (okButton) { q->connect(okButton, &QAbstractButton::clicked, q, &KCMultiDialog::slotOkClicked); delete okButton->findChild(); } } } QPushButton *resetButton = q->buttonBox()->button(QDialogButtonBox::Reset); if (resetButton) { resetButton->setEnabled(change); } QPushButton *applyButton = q->buttonBox()->button(QDialogButtonBox::Apply); if (applyButton) { applyButton->setEnabled(change); } if (activeModule) { QPushButton *helpButton = q->buttonBox()->button(QDialogButtonBox::Help); if (helpButton) { helpButton->setEnabled(activeModule->buttons() & KCModule::Help); } QPushButton *defaultButton = q->buttonBox()->button(QDialogButtonBox::RestoreDefaults); if (defaultButton) { defaultButton->setEnabled(activeModule->buttons() & KCModule::Default); } } } void KCMultiDialogPrivate::_k_updateHeader(bool use, const QString &message) { Q_Q(KCMultiDialog); KPageWidgetItem *item = q->currentPage(); KCModuleProxy *kcm = qobject_cast(item->widget()); if (use) { item->setHeader(QStringLiteral("") + kcm->moduleInfo().comment() + QStringLiteral("
") + message + QStringLiteral("")); item->setIcon(KDE::icon(kcm->moduleInfo().icon(), QStringList() << QStringLiteral("dialog-warning"))); } else { item->setHeader(kcm->moduleInfo().comment()); item->setIcon(QIcon::fromTheme(kcm->moduleInfo().icon())); } } void KCMultiDialogPrivate::init() { Q_Q(KCMultiDialog); q->setFaceType(KPageDialog::Auto); q->setWindowTitle(i18n("Configure")); q->setModal(false); QDialogButtonBox *buttonBox = new QDialogButtonBox(q); buttonBox->setStandardButtons(QDialogButtonBox::Help | QDialogButtonBox::RestoreDefaults | QDialogButtonBox::Cancel | QDialogButtonBox::Apply | QDialogButtonBox::Ok | QDialogButtonBox::Reset); KGuiItem::assign(buttonBox->button(QDialogButtonBox::Ok), KStandardGuiItem::ok()); KGuiItem::assign(buttonBox->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel()); KGuiItem::assign(buttonBox->button(QDialogButtonBox::RestoreDefaults), KStandardGuiItem::defaults()); KGuiItem::assign(buttonBox->button(QDialogButtonBox::Apply), KStandardGuiItem::apply()); KGuiItem::assign(buttonBox->button(QDialogButtonBox::Reset), KStandardGuiItem::reset()); KGuiItem::assign(buttonBox->button(QDialogButtonBox::Help), KStandardGuiItem::help()); buttonBox->button(QDialogButtonBox::Reset)->setEnabled(false); buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false); q->connect(buttonBox->button(QDialogButtonBox::Apply), &QAbstractButton::clicked, q, &KCMultiDialog::slotApplyClicked); q->connect(buttonBox->button(QDialogButtonBox::Ok), &QAbstractButton::clicked, q, &KCMultiDialog::slotOkClicked); q->connect(buttonBox->button(QDialogButtonBox::RestoreDefaults), &QAbstractButton::clicked, q, &KCMultiDialog::slotDefaultClicked); q->connect(buttonBox->button(QDialogButtonBox::Help), &QAbstractButton::clicked, q, &KCMultiDialog::slotHelpClicked); q->connect(buttonBox->button(QDialogButtonBox::Reset), &QAbstractButton::clicked, q, &KCMultiDialog::slotUser1Clicked); q->setButtonBox(buttonBox); q->connect(q, SIGNAL(currentPageChanged(KPageWidgetItem*,KPageWidgetItem*)), SLOT(_k_slotCurrentPageChanged(KPageWidgetItem*,KPageWidgetItem*))); } KCMultiDialog::KCMultiDialog(QWidget *parent) : KPageDialog(parent) , d_ptr(new KCMultiDialogPrivate(this)) { d_func()->init(); } KCMultiDialog::KCMultiDialog(KPageWidget *pageWidget, QWidget *parent, Qt::WindowFlags flags) : KPageDialog(pageWidget, parent, flags) , d_ptr(new KCMultiDialogPrivate(this)) { d_func()->init(); } KCMultiDialog::KCMultiDialog(KCMultiDialogPrivate &dd, KPageWidget *pageWidget, QWidget *parent, Qt::WindowFlags flags) : KPageDialog(pageWidget, parent, flags) , d_ptr(&dd) { d_func()->init(); } KCMultiDialog::~KCMultiDialog() { delete d_ptr; } void KCMultiDialog::showEvent(QShowEvent *ev) { resize(QSize(800, 550)); adjustSize(); KPageDialog::showEvent(ev); } void KCMultiDialog::slotDefaultClicked() { Q_D(KCMultiDialog); const KPageWidgetItem *item = currentPage(); if (!item) { return; } for (int i = 0; i < d->modules.count(); ++i) { if (d->modules[ i ].item == item) { d->modules[ i ].kcm->defaults(); d->_k_clientChanged(); return; } } } void KCMultiDialog::slotUser1Clicked() { const KPageWidgetItem *item = currentPage(); if (!item) { return; } Q_D(KCMultiDialog); for (int i = 0; i < d->modules.count(); ++i) { if (d->modules[ i ].item == item) { d->modules[ i ].kcm->load(); d->_k_clientChanged(); return; } } } bool KCMultiDialogPrivate::moduleSave(KCModuleProxy *module) { if (!module) { return false; } module->save(); return true; } void KCMultiDialogPrivate::apply() { Q_Q(KCMultiDialog); QStringList updatedComponents; foreach (const CreatedModule &module, modules) { KCModuleProxy *proxy = module.kcm; if (proxy->changed()) { proxy->save(); /** * Add name of the components the kcm belongs to the list * of updated components. */ const QStringList componentNames = module.componentNames; foreach (const QString &componentName, module.componentNames) { if (!updatedComponents.contains(componentName)) { updatedComponents.append(componentName); } } } } // Send the configCommitted signal for every updated component. foreach (const QString &name, updatedComponents) { emit q->configCommitted(name.toLatin1()); } emit q->configCommitted(); } void KCMultiDialog::slotApplyClicked() { QPushButton *applyButton = buttonBox()->button(QDialogButtonBox::Apply); applyButton->setFocus(); d_func()->apply(); } void KCMultiDialog::slotOkClicked() { QPushButton *okButton = buttonBox()->button(QDialogButtonBox::Ok); okButton->setFocus(); d_func()->apply(); accept(); } void KCMultiDialog::slotHelpClicked() { const KPageWidgetItem *item = currentPage(); if (!item) { return; } Q_D(KCMultiDialog); QString docPath; for (int i = 0; i < d->modules.count(); ++i) { if (d->modules[ i ].item == item) { docPath = d->modules[ i ].kcm->moduleInfo().docPath(); break; } } QUrl docUrl = QUrl(QStringLiteral("help:/")).resolved(QUrl(docPath)); // same code as in KHelpClient::invokeHelp if (docUrl.scheme() == QLatin1String("help") || docUrl.scheme() == QLatin1String("man") || docUrl.scheme() == QLatin1String("info")) { QProcess::startDetached(QStringLiteral("khelpcenter"), QStringList() << docUrl.toString()); } else { QDesktopServices::openUrl(docUrl); } } void KCMultiDialog::closeEvent(QCloseEvent *event) { Q_D(KCMultiDialog); KPageDialog::closeEvent(event); /** * If we don't delete them, the DBUS registration stays, and trying to load the KCMs * in other situations will lead to "module already loaded in Foo," while to the user * doesn't appear so(the dialog is hidden) */ Q_FOREACH(auto &proxy, d->modules) { proxy.kcm->deleteClient(); } } KPageWidgetItem *KCMultiDialog::addModule(const QString &path, const QStringList &args) { QString complete = path; if (!path.endsWith(QLatin1String(".desktop"))) { complete += QStringLiteral(".desktop"); } KService::Ptr service = KService::serviceByStorageId(complete); - return addModule(KCModuleInfo(service), 0, args); + return addModule(KCModuleInfo(service), nullptr, args); } KPageWidgetItem *KCMultiDialog::addModule(const KCModuleInfo &moduleInfo, KPageWidgetItem *parentItem, const QStringList &args) { if (!moduleInfo.service()) { - return 0; + return nullptr; } //KAuthorized::authorizeControlModule( moduleInfo.service()->menuId() ) is //checked in noDisplay already if (moduleInfo.service()->noDisplay()) { - return 0; + return nullptr; } - KCModuleProxy *kcm = new KCModuleProxy(moduleInfo, 0, args); + KCModuleProxy *kcm = new KCModuleProxy(moduleInfo, nullptr, args); // qDebug() << moduleInfo.moduleName(); KPageWidgetItem *item = new KPageWidgetItem(kcm, moduleInfo.moduleName()); if (kcm->realModule() && kcm->realModule()->useRootOnlyMessage()) { item->setHeader(QStringLiteral("") + moduleInfo.comment() + QStringLiteral("
") + kcm->realModule()->rootOnlyMessage() + QStringLiteral("")); item->setIcon(KDE::icon(moduleInfo.icon(), QStringList() << QStringLiteral("dialog-warning"))); } else { item->setHeader(moduleInfo.comment()); item->setIcon(QIcon::fromTheme(moduleInfo.icon())); } item->setProperty("_k_weight", moduleInfo.weight()); bool updateCurrentPage = false; const KPageWidgetModel *model = qobject_cast(pageWidget()->model()); Q_ASSERT(model); if (parentItem) { const QModelIndex parentIndex = model->index(parentItem); const int siblingCount = model->rowCount(parentIndex); int row = 0; for (; row < siblingCount; ++row) { KPageWidgetItem *siblingItem = model->item(parentIndex.child(row, 0)); if (siblingItem->property("_k_weight").toInt() > moduleInfo.weight()) { // the item we found is heavier than the new module // qDebug() << "adding KCM " << item->name() << " before " << siblingItem->name(); insertPage(siblingItem, item); break; } } if (row >= siblingCount) { // the new module is either the first or the heaviest item // qDebug() << "adding KCM " << item->name() << " with parent " << parentItem->name(); addSubPage(parentItem, item); } } else { const int siblingCount = model->rowCount(); int row = 0; for (; row < siblingCount; ++row) { KPageWidgetItem *siblingItem = model->item(model->index(row, 0)); if (siblingItem->property("_k_weight").toInt() > moduleInfo.weight()) { // the item we found is heavier than the new module // qDebug() << "adding KCM " << item->name() << " before " << siblingItem->name(); insertPage(siblingItem, item); if (siblingItem == currentPage()) { updateCurrentPage = true; } break; } } if (row == siblingCount) { // the new module is either the first or the heaviest item // qDebug() << "adding KCM " << item->name() << " at the top level"; addPage(item); } } connect(kcm, SIGNAL(changed(bool)), this, SLOT(_k_clientChanged())); connect(kcm->realModule(), SIGNAL(rootOnlyMessageChanged(bool,QString)), this, SLOT(_k_updateHeader(bool,QString))); Q_D(KCMultiDialog); KCMultiDialogPrivate::CreatedModule cm; cm.kcm = kcm; cm.item = item; cm.componentNames = moduleInfo.service()->property(QStringLiteral("X-KDE-ParentComponents")).toStringList(); d->modules.append(cm); if (d->modules.count() == 1 || updateCurrentPage) { setCurrentPage(item); d->_k_clientChanged(); } return item; } void KCMultiDialog::clear() { Q_D(KCMultiDialog); // qDebug() ; for (int i = 0; i < d->modules.count(); ++i) { removePage(d->modules[ i ].item); delete d->modules[ i ].kcm; } d->modules.clear(); d->_k_clientChanged(); } #include "moc_kcmultidialog.cpp" diff --git a/src/kcmultidialog.h b/src/kcmultidialog.h index c2ff3d2..102c7b4 100644 --- a/src/kcmultidialog.h +++ b/src/kcmultidialog.h @@ -1,183 +1,183 @@ /* Copyright (c) 2000 Matthias Elter Copyright (c) 2003 Daniel Molkentin Copyright (c) 2003,2006 Matthias Kretz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KCMULTIDIALOG_H #define KCMULTIDIALOG_H #include #include class KCMultiDialogPrivate; /** * @short A class that offers a KPageDialog containing arbitrary * KControl Modules. * * @author Matthias Elter , Daniel Molkentin */ class KCMUTILS_EXPORT KCMultiDialog : public KPageDialog { Q_OBJECT Q_DECLARE_PRIVATE(KCMultiDialog) public: /** * Constructs a new KCMultiDialog * * @param parent The parent widget **/ - KCMultiDialog(QWidget *parent = 0); + KCMultiDialog(QWidget *parent = nullptr); /** * Destructor **/ virtual ~KCMultiDialog(); /** * Add a module. * * The module is added according to its KCModuleInfo::weight(). The weight determines where in the list * the module will appear. Lighter modules on top, heavier modules at the bottom. * * @param module Specify the name of the module that is to be added * to the list of modules the dialog will show. * * @param args The arguments that should be given to the KCModule when it is created * * @returns The @see KPageWidgetItem associated with the new dialog page. **/ KPageWidgetItem *addModule(const QString &module, const QStringList & args = QStringList()); /** * Add a module. * * The module is added according to its KCModuleInfo::weight(). The weight determines where in the list * the module will appear. Lighter modules on top, heavier modules at the bottom. * * @param moduleinfo Pass a KCModuleInfo object which will be * used for creating the module. It will be added * to the list of modules the dialog will show. * * @param parent The @see KPageWidgetItem that should appear as parents * in the tree view or a 0 pointer if there is no parent. * * @param args The arguments that should be given to the KCModule when it is created **/ - KPageWidgetItem *addModule(const KCModuleInfo &moduleinfo, KPageWidgetItem *parent = 0, + KPageWidgetItem *addModule(const KCModuleInfo &moduleinfo, KPageWidgetItem *parent = nullptr, const QStringList &args = QStringList()); /** * Removes all modules from the dialog. */ void clear(); Q_SIGNALS: /** * Emitted after all KCModules have been told to save their configuration. * * The applyClicked and okClicked signals are emitted before the * configuration is saved. */ void configCommitted(); /** * Emitted after the KCModules have been told to save their configuration. * It is emitted once for every instance the KCMs that were changed belong * to. * * You can make use of this if you have more than one component in your * application. componentName tells you the instance that has to reload its * configuration. * * The applyClicked and okClicked signals are emitted before the * configuration is saved. * * @param componentName The name of the instance that needs to reload its * configuration. */ void configCommitted(const QByteArray &componentName); protected: /** * This constructor can be used by subclasses to provide a custom KPageWidget. */ - KCMultiDialog(KPageWidget *pageWidget, QWidget *parent, Qt::WindowFlags flags = 0); - KCMultiDialog(KCMultiDialogPrivate &dd, KPageWidget *pageWidget, QWidget *parent, Qt::WindowFlags flags = 0); + KCMultiDialog(KPageWidget *pageWidget, QWidget *parent, Qt::WindowFlags flags = nullptr); + KCMultiDialog(KCMultiDialogPrivate &dd, KPageWidget *pageWidget, QWidget *parent, Qt::WindowFlags flags = nullptr); KCMultiDialogPrivate *const d_ptr; void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; void showEvent(QShowEvent *event) Q_DECL_OVERRIDE; protected Q_SLOTS: /** * This slot is called when the user presses the "Default" Button. * You can reimplement it if needed. * * @note Make sure you call the original implementation. **/ void slotDefaultClicked(); /** * This slot is called when the user presses the "Reset" Button. * You can reimplement it if needed. * * @note Make sure you call the original implementation. */ void slotUser1Clicked(); /** * This slot is called when the user presses the "Apply" Button. * You can reimplement it if needed. * * @note Make sure you call the original implementation. **/ void slotApplyClicked(); /** * This slot is called when the user presses the "OK" Button. * You can reimplement it if needed. * * @note Make sure you call the original implementation. **/ void slotOkClicked(); /** * This slot is called when the user presses the "Help" Button. * It reads the X-DocPath field of the currently selected KControl * module's .desktop file to find the path to the documentation, * which it then attempts to load. * * You can reimplement this slot if needed. * * @note Make sure you call the original implementation. **/ void slotHelpClicked(); private: Q_PRIVATE_SLOT(d_func(), void _k_slotCurrentPageChanged(KPageWidgetItem *, KPageWidgetItem *)) Q_PRIVATE_SLOT(d_func(), void _k_clientChanged()) Q_PRIVATE_SLOT(d_func(), void _k_updateHeader(bool use, const QString &message)) }; #endif diff --git a/src/kcmultidialog_p.h b/src/kcmultidialog_p.h index f2e7e23..b595e98 100644 --- a/src/kcmultidialog_p.h +++ b/src/kcmultidialog_p.h @@ -1,65 +1,65 @@ /* This file is part of the KDE project Copyright (C) 2007 Matthias Kretz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KCMULTIDIALOG_P_H #define KCMULTIDIALOG_P_H #include "kcmultidialog.h" #include #include class KCModuleProxy; class KPageWidgetItem; class KCMultiDialogPrivate { Q_DECLARE_PUBLIC(KCMultiDialog) protected: KCMultiDialogPrivate(KCMultiDialog *parent) - : currentModule(0), q_ptr(parent) + : currentModule(nullptr), q_ptr(parent) { } virtual ~KCMultiDialogPrivate() {} KCModuleProxy *currentModule; struct CreatedModule { KCModuleProxy *kcm; KPageWidgetItem *item; QStringList componentNames; }; typedef QList ModuleList; ModuleList modules; void _k_slotCurrentPageChanged(KPageWidgetItem *current, KPageWidgetItem *previous); virtual void _k_clientChanged(); void _k_dialogClosed(); void _k_updateHeader(bool use, const QString &message); KCMultiDialog *q_ptr; private: void init(); void apply(); bool resolveChanges(KCModuleProxy *currentProxy); bool moduleSave(KCModuleProxy *module); }; #endif // KCMULTIDIALOG_P_H diff --git a/src/kpluginselector.cpp b/src/kpluginselector.cpp index 91d76bb..2ea2591 100644 --- a/src/kpluginselector.cpp +++ b/src/kpluginselector.cpp @@ -1,906 +1,906 @@ /** * This file is part of the KDE project * Copyright (C) 2007, 2006 Rafael Fernández López * Copyright (C) 2002-2003 Matthias Kretz * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License version 2 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kpluginselector.h" #include "kpluginselector_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MARGIN 5 KPluginSelector::Private::Private(KPluginSelector *parent) : QObject(parent) , parent(parent) - , listView(0) - , categoryDrawer(0) + , listView(nullptr) + , categoryDrawer(nullptr) , showIcons(false) { } KPluginSelector::Private::~Private() { } void KPluginSelector::Private::updateDependencies(PluginEntry *pluginEntry, bool added) { if (added) { QStringList dependencyList = pluginEntry->pluginInfo.dependencies(); if (!dependencyList.count()) { return; } for (int i = 0; i < pluginModel->rowCount(); i++) { const QModelIndex index = pluginModel->index(i, 0); PluginEntry *pe = static_cast(index.internalPointer()); if ((pe->pluginInfo.pluginName() != pluginEntry->pluginInfo.pluginName()) && dependencyList.contains(pe->pluginInfo.pluginName()) && !pe->checked) { dependenciesWidget->addDependency(pe->pluginInfo.name(), pluginEntry->pluginInfo.name(), added); const_cast(index.model())->setData(index, added, Qt::CheckStateRole); updateDependencies(pe, added); } } } else { for (int i = 0; i < pluginModel->rowCount(); i++) { const QModelIndex index = pluginModel->index(i, 0); PluginEntry *pe = static_cast(index.internalPointer()); if ((pe->pluginInfo.pluginName() != pluginEntry->pluginInfo.pluginName()) && pe->pluginInfo.dependencies().contains(pluginEntry->pluginInfo.pluginName()) && pe->checked) { dependenciesWidget->addDependency(pe->pluginInfo.name(), pluginEntry->pluginInfo.name(), added); const_cast(index.model())->setData(index, added, Qt::CheckStateRole); updateDependencies(pe, added); } } } } int KPluginSelector::Private::dependantLayoutValue(int value, int width, int totalWidth) const { if (listView->layoutDirection() == Qt::LeftToRight) { return value; } return totalWidth - width - value; } KPluginSelector::Private::DependenciesWidget::DependenciesWidget(QWidget *parent) : QWidget(parent) , addedByDependencies(0) , removedByDependencies(0) { setVisible(false); details = new QLabel(); QHBoxLayout *layout = new QHBoxLayout; QVBoxLayout *dataLayout = new QVBoxLayout; dataLayout->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); layout->setAlignment(Qt::AlignLeft); QLabel *label = new QLabel(); label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); label->setPixmap(QIcon::fromTheme(QStringLiteral("dialog-information")).pixmap(style()->pixelMetric(QStyle::PM_MessageBoxIconSize))); label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); layout->addWidget(label); KUrlLabel *link = new KUrlLabel(); link->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); link->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); link->setGlowEnabled(false); link->setUnderline(false); link->setFloatEnabled(true); link->setUseCursor(true); link->setHighlightedColor(palette().color(QPalette::Link)); link->setSelectedColor(palette().color(QPalette::Link)); link->setText(i18n("Automatic changes have been performed due to plugin dependencies. Click here for further information")); dataLayout->addWidget(link); dataLayout->addWidget(details); layout->addLayout(dataLayout); setLayout(layout); QObject::connect(link, SIGNAL(leftClickedUrl()), this, SLOT(showDependencyDetails())); } KPluginSelector::Private::DependenciesWidget::~DependenciesWidget() { } void KPluginSelector::Private::DependenciesWidget::addDependency(const QString &dependency, const QString &pluginCausant, bool added) { if (!isVisible()) { setVisible(true); } struct FurtherInfo furtherInfo; furtherInfo.added = added; furtherInfo.pluginCausant = pluginCausant; if (dependencyMap.contains(dependency)) { // The dependency moved from added to removed or vice-versa if (added && removedByDependencies) { removedByDependencies--; } else if (addedByDependencies) { addedByDependencies--; } dependencyMap[dependency] = furtherInfo; } else { dependencyMap.insert(dependency, furtherInfo); } if (added) { addedByDependencies++; } else { removedByDependencies++; } updateDetails(); } void KPluginSelector::Private::DependenciesWidget::userOverrideDependency(const QString &dependency) { if (dependencyMap.contains(dependency)) { if (addedByDependencies && dependencyMap[dependency].added) { addedByDependencies--; } else if (removedByDependencies) { removedByDependencies--; } dependencyMap.remove(dependency); } updateDetails(); } void KPluginSelector::Private::DependenciesWidget::clearDependencies() { addedByDependencies = 0; removedByDependencies = 0; dependencyMap.clear(); updateDetails(); } void KPluginSelector::Private::DependenciesWidget::showDependencyDetails() { QString message = i18n("Automatic changes have been performed in order to satisfy plugin dependencies:\n"); foreach (const QString &dependency, dependencyMap.keys()) { if (dependencyMap[dependency].added) { message += i18n("\n %1 plugin has been automatically checked because of the dependency of %2 plugin", dependency, dependencyMap[dependency].pluginCausant); } else { message += i18n("\n %1 plugin has been automatically unchecked because of its dependency on %2 plugin", dependency, dependencyMap[dependency].pluginCausant); } } KMessageBox::information(this, message, i18n("Dependency Check")); addedByDependencies = 0; removedByDependencies = 0; updateDetails(); } void KPluginSelector::Private::DependenciesWidget::updateDetails() { if (!dependencyMap.count()) { setVisible(false); return; } QString message; if (addedByDependencies) { message += i18np("%1 plugin automatically added due to plugin dependencies", "%1 plugins automatically added due to plugin dependencies", addedByDependencies); } if (removedByDependencies && !message.isEmpty()) { message += i18n(", "); } if (removedByDependencies) { message += i18np("%1 plugin automatically removed due to plugin dependencies", "%1 plugins automatically removed due to plugin dependencies", removedByDependencies); } if (message.isEmpty()) { details->setVisible(false); } else { details->setVisible(true); details->setText(message); } } KPluginSelector::KPluginSelector(QWidget *parent) : QWidget(parent) , d(new Private(this)) { QVBoxLayout *layout = new QVBoxLayout; layout->setMargin(0); setLayout(layout); d->lineEdit = new QLineEdit(this); d->lineEdit->setClearButtonEnabled(true); d->lineEdit->setPlaceholderText(i18n("Search Plugins")); d->listView = new KCategorizedView(this); d->categoryDrawer = new KCategoryDrawer(d->listView); d->listView->setVerticalScrollMode(QListView::ScrollPerPixel); d->listView->setAlternatingRowColors(true); d->listView->setCategoryDrawer(d->categoryDrawer); d->dependenciesWidget = new Private::DependenciesWidget(this); d->pluginModel = new Private::PluginModel(d, this); d->proxyModel = new Private::ProxyModel(d, this); d->proxyModel->setCategorizedModel(true); d->proxyModel->setSourceModel(d->pluginModel); d->listView->setModel(d->proxyModel); d->listView->setAlternatingRowColors(true); Private::PluginDelegate *pluginDelegate = new Private::PluginDelegate(d, this); d->listView->setItemDelegate(pluginDelegate); d->listView->setMouseTracking(true); d->listView->viewport()->setAttribute(Qt::WA_Hover); connect(d->lineEdit, &QLineEdit::textChanged, d->proxyModel, &QSortFilterProxyModel::invalidate); connect(pluginDelegate, &Private::PluginDelegate::changed, this, &KPluginSelector::changed); connect(pluginDelegate, &Private::PluginDelegate::configCommitted, this, &KPluginSelector::configCommitted); layout->addWidget(d->lineEdit); layout->addWidget(d->listView); layout->addWidget(d->dependenciesWidget); } KPluginSelector::~KPluginSelector() { delete d->listView->itemDelegate(); delete d->listView; // depends on some other things in d, make sure this dies first. delete d; } void KPluginSelector::addPlugins(const QString &componentName, const QString &categoryName, const QString &categoryKey, KSharedConfig::Ptr config) { QStringList desktopFileNames; const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, componentName + QStringLiteral("/kpartplugins"), QStandardPaths::LocateDirectory); Q_FOREACH (const QString &dir, dirs) { QDirIterator it(dir, QStringList() << QStringLiteral("*.desktop"), QDir::NoFilter, QDirIterator::Subdirectories); while (it.hasNext()) { desktopFileNames.append(it.next()); } } QList pluginInfoList = KPluginInfo::fromFiles(desktopFileNames); if (pluginInfoList.isEmpty()) { return; } if (!config) { config = KSharedConfig::openConfig(componentName + QStringLiteral("rc")); } Q_ASSERT(config); KConfigGroup cfgGroup(config, "KParts Plugins"); // qDebug() << "cfgGroup = " << &cfgGroup; d->pluginModel->addPlugins(pluginInfoList, categoryName, categoryKey, cfgGroup); d->proxyModel->sort(0); } void KPluginSelector::addPlugins(const QList &pluginInfoList, PluginLoadMethod pluginLoadMethod, const QString &categoryName, const QString &categoryKey, const KSharedConfig::Ptr &config) { if (pluginInfoList.isEmpty()) { return; } KConfigGroup cfgGroup(config ? config : KSharedConfig::openConfig(), "Plugins"); // qDebug() << "cfgGroup = " << &cfgGroup; d->pluginModel->addPlugins(pluginInfoList, categoryName, categoryKey, cfgGroup, pluginLoadMethod, true /* manually added */); d->proxyModel->sort(0); } void KPluginSelector::load() { for (int i = 0; i < d->pluginModel->rowCount(); i++) { const QModelIndex index = d->pluginModel->index(i, 0); PluginEntry *pluginEntry = static_cast(index.internalPointer()); pluginEntry->pluginInfo.load(pluginEntry->cfgGroup); d->pluginModel->setData(index, pluginEntry->pluginInfo.isPluginEnabled(), Qt::CheckStateRole); } emit changed(false); } void KPluginSelector::save() { for (int i = 0; i < d->pluginModel->rowCount(); i++) { const QModelIndex index = d->pluginModel->index(i, 0); PluginEntry *pluginEntry = static_cast(index.internalPointer()); pluginEntry->pluginInfo.setPluginEnabled(pluginEntry->checked); pluginEntry->pluginInfo.save(pluginEntry->cfgGroup); pluginEntry->cfgGroup.sync(); } emit changed(false); } void KPluginSelector::defaults() { for (int i = 0; i < d->pluginModel->rowCount(); i++) { const QModelIndex index = d->pluginModel->index(i, 0); PluginEntry *pluginEntry = static_cast(index.internalPointer()); d->pluginModel->setData(index, pluginEntry->pluginInfo.isPluginEnabledByDefault(), Qt::CheckStateRole); } emit changed(true); } bool KPluginSelector::isDefault() const { for (int i = 0; i < d->pluginModel->rowCount(); i++) { const QModelIndex index = d->pluginModel->index(i, 0); PluginEntry *pluginEntry = static_cast(index.internalPointer()); if (d->pluginModel->data(index, Qt::CheckStateRole).toBool() != pluginEntry->pluginInfo.isPluginEnabledByDefault()) { return false; } } return true; } void KPluginSelector::updatePluginsState() { for (int i = 0; i < d->pluginModel->rowCount(); i++) { const QModelIndex index = d->pluginModel->index(i, 0); PluginEntry *pluginEntry = static_cast(index.internalPointer()); if (pluginEntry->manuallyAdded) { pluginEntry->pluginInfo.setPluginEnabled(pluginEntry->checked); } } } void KPluginSelector::setConfigurationArguments(const QStringList& arguments) { d->kcmArguments = arguments; } QStringList KPluginSelector::configurationArguments() const { return d->kcmArguments; } KPluginSelector::Private::PluginModel::PluginModel(KPluginSelector::Private *pluginSelector_d, QObject *parent) : QAbstractListModel(parent) , pluginSelector_d(pluginSelector_d) { } KPluginSelector::Private::PluginModel::~PluginModel() { } void KPluginSelector::Private::PluginModel::addPlugins(const QList &pluginList, const QString &categoryName, const QString &categoryKey, const KConfigGroup &cfgGroup, PluginLoadMethod pluginLoadMethod, bool manuallyAdded) { QList listToAdd; foreach (const KPluginInfo &pluginInfo, pluginList) { PluginEntry pluginEntry; pluginEntry.category = categoryName; pluginEntry.pluginInfo = pluginInfo; if (pluginLoadMethod == ReadConfigFile) { pluginEntry.pluginInfo.load(cfgGroup); } pluginEntry.checked = pluginInfo.isPluginEnabled(); pluginEntry.manuallyAdded = manuallyAdded; if (cfgGroup.isValid()) { pluginEntry.cfgGroup = cfgGroup; } else { pluginEntry.cfgGroup = pluginInfo.config(); } // this is where kiosk will set if a plugin is checkable or not (pluginName + "Enabled") pluginEntry.isCheckable = !pluginInfo.isValid() || !pluginEntry.cfgGroup.isEntryImmutable(pluginInfo.pluginName() + QLatin1String("Enabled")); if (!pluginEntryList.contains(pluginEntry) && !listToAdd.contains(pluginEntry) && (categoryKey.isEmpty() || !pluginInfo.category().compare(categoryKey, Qt::CaseInsensitive)) && (!pluginInfo.service() || !pluginInfo.service()->noDisplay())) { listToAdd << pluginEntry; if (!pluginSelector_d->showIcons && !pluginInfo.icon().isEmpty()) { pluginSelector_d->showIcons = true; } } } if (listToAdd.count()) { beginInsertRows(QModelIndex(), pluginEntryList.count(), pluginEntryList.count() + listToAdd.count() - 1); pluginEntryList << listToAdd; endInsertRows(); } } QList KPluginSelector::Private::PluginModel::pluginServices(const QModelIndex &index) const { return static_cast(index.internalPointer())->pluginInfo.kcmServices(); } QModelIndex KPluginSelector::Private::PluginModel::index(int row, int column, const QModelIndex &parent) const { Q_UNUSED(parent) return createIndex(row, column, (row < pluginEntryList.count()) ? (void *) &pluginEntryList.at(row) - : 0); + : nullptr); } QVariant KPluginSelector::Private::PluginModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || !index.internalPointer()) { return QVariant(); } PluginEntry *pluginEntry = static_cast(index.internalPointer()); switch (role) { case Qt::DisplayRole: return pluginEntry->pluginInfo.name(); case PluginEntryRole: return QVariant::fromValue(pluginEntry); case ServicesCountRole: return pluginEntry->pluginInfo.kcmServices().count(); case NameRole: return pluginEntry->pluginInfo.name(); case CommentRole: return pluginEntry->pluginInfo.comment(); case AuthorRole: return pluginEntry->pluginInfo.author(); case EmailRole: return pluginEntry->pluginInfo.email(); case WebsiteRole: return pluginEntry->pluginInfo.website(); case VersionRole: return pluginEntry->pluginInfo.version(); case LicenseRole: return pluginEntry->pluginInfo.license(); case DependenciesRole: return pluginEntry->pluginInfo.dependencies(); case IsCheckableRole: return pluginEntry->isCheckable; case Qt::DecorationRole: return pluginEntry->pluginInfo.icon(); case Qt::CheckStateRole: return pluginEntry->checked; case KCategorizedSortFilterProxyModel::CategoryDisplayRole: // fall through case KCategorizedSortFilterProxyModel::CategorySortRole: return pluginEntry->category; default: return QVariant(); } } bool KPluginSelector::Private::PluginModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!index.isValid()) { return false; } bool ret = false; if (role == Qt::CheckStateRole) { static_cast(index.internalPointer())->checked = value.toBool(); ret = true; } if (ret) { emit dataChanged(index, index); } return ret; } int KPluginSelector::Private::PluginModel::rowCount(const QModelIndex &parent) const { if (parent.isValid()) { return 0; } return pluginEntryList.count(); } KPluginSelector::Private::ProxyModel::ProxyModel(KPluginSelector::Private *pluginSelector_d, QObject *parent) : KCategorizedSortFilterProxyModel(parent) , pluginSelector_d(pluginSelector_d) { sort(0); } KPluginSelector::Private::ProxyModel::~ProxyModel() { } bool KPluginSelector::Private::ProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { Q_UNUSED(sourceParent) if (!pluginSelector_d->lineEdit->text().isEmpty()) { const QModelIndex index = sourceModel()->index(sourceRow, 0); const KPluginInfo pluginInfo = static_cast(index.internalPointer())->pluginInfo; return pluginInfo.name().contains(pluginSelector_d->lineEdit->text(), Qt::CaseInsensitive) || pluginInfo.comment().contains(pluginSelector_d->lineEdit->text(), Qt::CaseInsensitive); } return true; } bool KPluginSelector::Private::ProxyModel::subSortLessThan(const QModelIndex &left, const QModelIndex &right) const { return static_cast(left.internalPointer())->pluginInfo.name().compare(static_cast(right.internalPointer())->pluginInfo.name(), Qt::CaseInsensitive) < 0; } KPluginSelector::Private::PluginDelegate::PluginDelegate(KPluginSelector::Private *pluginSelector_d, QObject *parent) : KWidgetItemDelegate(pluginSelector_d->listView, parent) , checkBox(new QCheckBox) , pushButton(new QPushButton) , pluginSelector_d(pluginSelector_d) { pushButton->setIcon(QIcon::fromTheme(QStringLiteral("configure"))); // only for getting size matters } KPluginSelector::Private::PluginDelegate::~PluginDelegate() { delete checkBox; delete pushButton; } void KPluginSelector::Private::PluginDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { if (!index.isValid()) { return; } int xOffset = checkBox->sizeHint().width(); bool disabled = !index.model()->data(index, IsCheckableRole).toBool(); painter->save(); - QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, 0); + QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, nullptr); int iconSize = option.rect.height() - MARGIN * 2; if (pluginSelector_d->showIcons) { QIcon icon = QIcon::fromTheme(index.model()->data(index, Qt::DecorationRole).toString()); icon.paint(painter, QRect(pluginSelector_d->dependantLayoutValue(MARGIN + option.rect.left() + xOffset, iconSize, option.rect.width()), MARGIN + option.rect.top(), iconSize, iconSize)); } else { iconSize = -MARGIN; } QRect contentsRect(pluginSelector_d->dependantLayoutValue(MARGIN * 2 + iconSize + option.rect.left() + xOffset, option.rect.width() - MARGIN * 3 - iconSize - xOffset, option.rect.width()), MARGIN + option.rect.top(), option.rect.width() - MARGIN * 3 - iconSize - xOffset, option.rect.height() - MARGIN * 2); int lessHorizontalSpace = MARGIN * 2 + pushButton->sizeHint().width(); if (index.model()->data(index, ServicesCountRole).toBool()) { lessHorizontalSpace += MARGIN + pushButton->sizeHint().width(); } contentsRect.setWidth(contentsRect.width() - lessHorizontalSpace); if (option.state & QStyle::State_Selected) { painter->setPen(option.palette.highlightedText().color()); } if (pluginSelector_d->listView->layoutDirection() == Qt::RightToLeft) { contentsRect.translate(lessHorizontalSpace, 0); } painter->save(); if (disabled) { QPalette pal(option.palette); pal.setCurrentColorGroup(QPalette::Disabled); painter->setPen(pal.text().color()); } painter->save(); QFont font = titleFont(option.font); QFontMetrics fmTitle(font); painter->setFont(font); painter->drawText(contentsRect, Qt::AlignLeft | Qt::AlignTop, fmTitle.elidedText(index.model()->data(index, Qt::DisplayRole).toString(), Qt::ElideRight, contentsRect.width())); painter->restore(); painter->drawText(contentsRect, Qt::AlignLeft | Qt::AlignBottom, option.fontMetrics.elidedText(index.model()->data(index, CommentRole).toString(), Qt::ElideRight, contentsRect.width())); painter->restore(); painter->restore(); } QSize KPluginSelector::Private::PluginDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { int i = 5; int j = 1; if (index.model()->data(index, ServicesCountRole).toBool()) { i = 6; j = 2; } if (!pluginSelector_d->showIcons) { i--; } QFont font = titleFont(option.font); QFontMetrics fmTitle(font); return QSize(qMax(fmTitle.width(index.model()->data(index, Qt::DisplayRole).toString()), option.fontMetrics.width(index.model()->data(index, CommentRole).toString())) + (pluginSelector_d->showIcons ? KIconLoader::SizeMedium : 0) + MARGIN * i + pushButton->sizeHint().width() * j, qMax(KIconLoader::SizeMedium + MARGIN * 2, fmTitle.height() + option.fontMetrics.height() + MARGIN * 2)); } QList KPluginSelector::Private::PluginDelegate::createItemWidgets(const QModelIndex &index) const { Q_UNUSED(index); QList widgetList; QCheckBox *enabledCheckBox = new QCheckBox; connect(enabledCheckBox, &QAbstractButton::clicked, this, &PluginDelegate::slotStateChanged); connect(enabledCheckBox, &QAbstractButton::clicked, this, &PluginDelegate::emitChanged); QPushButton *aboutPushButton = new QPushButton; aboutPushButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-information"))); connect(aboutPushButton, &QAbstractButton::clicked, this, &PluginDelegate::slotAboutClicked); QPushButton *configurePushButton = new QPushButton; configurePushButton->setIcon(QIcon::fromTheme(QStringLiteral("configure"))); connect(configurePushButton, &QAbstractButton::clicked, this, &PluginDelegate::slotConfigureClicked); setBlockedEventTypes(enabledCheckBox, QList() << QEvent::MouseButtonPress << QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick << QEvent::KeyPress << QEvent::KeyRelease); setBlockedEventTypes(aboutPushButton, QList() << QEvent::MouseButtonPress << QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick << QEvent::KeyPress << QEvent::KeyRelease); setBlockedEventTypes(configurePushButton, QList() << QEvent::MouseButtonPress << QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick << QEvent::KeyPress << QEvent::KeyRelease); widgetList << enabledCheckBox << configurePushButton << aboutPushButton; return widgetList; } void KPluginSelector::Private::PluginDelegate::updateItemWidgets(const QList widgets, const QStyleOptionViewItem &option, const QPersistentModelIndex &index) const { QCheckBox *checkBox = static_cast(widgets[0]); checkBox->resize(checkBox->sizeHint()); checkBox->move(pluginSelector_d->dependantLayoutValue(MARGIN, checkBox->sizeHint().width(), option.rect.width()), option.rect.height() / 2 - checkBox->sizeHint().height() / 2); QPushButton *aboutPushButton = static_cast(widgets[2]); QSize aboutPushButtonSizeHint = aboutPushButton->sizeHint(); aboutPushButton->resize(aboutPushButtonSizeHint); aboutPushButton->move(pluginSelector_d->dependantLayoutValue(option.rect.width() - MARGIN - aboutPushButtonSizeHint.width(), aboutPushButtonSizeHint.width(), option.rect.width()), option.rect.height() / 2 - aboutPushButtonSizeHint.height() / 2); QPushButton *configurePushButton = static_cast(widgets[1]); QSize configurePushButtonSizeHint = configurePushButton->sizeHint(); configurePushButton->resize(configurePushButtonSizeHint); configurePushButton->move(pluginSelector_d->dependantLayoutValue(option.rect.width() - MARGIN * 2 - configurePushButtonSizeHint.width() - aboutPushButtonSizeHint.width(), configurePushButtonSizeHint.width(), option.rect.width()), option.rect.height() / 2 - configurePushButtonSizeHint.height() / 2); if (!index.isValid() || !index.internalPointer()) { checkBox->setVisible(false); aboutPushButton->setVisible(false); configurePushButton->setVisible(false); } else { checkBox->setChecked(index.model()->data(index, Qt::CheckStateRole).toBool()); checkBox->setEnabled(index.model()->data(index, IsCheckableRole).toBool()); configurePushButton->setVisible(index.model()->data(index, ServicesCountRole).toBool()); configurePushButton->setEnabled(index.model()->data(index, Qt::CheckStateRole).toBool()); } } void KPluginSelector::Private::PluginDelegate::slotStateChanged(bool state) { if (!focusedIndex().isValid()) { return; } const QModelIndex index = focusedIndex(); pluginSelector_d->dependenciesWidget->clearDependencies(); PluginEntry *pluginEntry = index.model()->data(index, PluginEntryRole).value(); pluginSelector_d->updateDependencies(pluginEntry, state); const_cast(index.model())->setData(index, state, Qt::CheckStateRole); } void KPluginSelector::Private::PluginDelegate::emitChanged() { emit changed(true); } void KPluginSelector::Private::PluginDelegate::slotAboutClicked() { const QModelIndex index = focusedIndex(); const QAbstractItemModel *model = index.model(); const QString name = model->data(index, NameRole).toString(); const QString comment = model->data(index, CommentRole).toString(); const QString author = model->data(index, AuthorRole).toString(); const QString email = model->data(index, EmailRole).toString(); const QString website = model->data(index, WebsiteRole).toString(); const QString version = model->data(index, VersionRole).toString(); const QString license = model->data(index, LicenseRole).toString(); KAboutData aboutData(name, name, version, comment, KAboutLicense::byKeyword(license).key(), QString(), QString(), website); aboutData.setProgramIconName(index.model()->data(index, Qt::DecorationRole).toString()); const QStringList authors = author.split(QLatin1Char(',')); const QStringList emails = email.split(QLatin1Char(',')); if (authors.count() == emails.count()) { int i = 0; foreach (const QString &author, authors) { if (!author.isEmpty()) { aboutData.addAuthor(author, QString(), emails[i]); } i++; } } KAboutApplicationDialog aboutPlugin(aboutData, itemView()); aboutPlugin.setWindowTitle(i18nc("Used only for plugins", "About %1", aboutData.displayName())); aboutPlugin.exec(); } void KPluginSelector::Private::PluginDelegate::slotConfigureClicked() { const QModelIndex index = focusedIndex(); const QAbstractItemModel *model = index.model(); PluginEntry *pluginEntry = model->data(index, PluginEntryRole).value(); KPluginInfo pluginInfo = pluginEntry->pluginInfo; QDialog configDialog(itemView()); configDialog.setWindowTitle(model->data(index, NameRole).toString()); // The number of KCModuleProxies in use determines whether to use a tabwidget - QTabWidget *newTabWidget = 0; + QTabWidget *newTabWidget = nullptr; // Widget to use for the setting dialog's main widget, // either a QTabWidget or a KCModuleProxy - QWidget *mainWidget = 0; + QWidget *mainWidget = nullptr; // Widget to use as the KCModuleProxy's parent. // The first proxy is owned by the dialog itself QWidget *moduleProxyParentWidget = &configDialog; foreach (const KService::Ptr &servicePtr, pluginInfo.kcmServices()) { if (!servicePtr->noDisplay()) { KCModuleInfo moduleInfo(servicePtr); KCModuleProxy *currentModuleProxy = new KCModuleProxy(moduleInfo, moduleProxyParentWidget, pluginSelector_d->kcmArguments); if (currentModuleProxy->realModule()) { moduleProxyList << currentModuleProxy; if (mainWidget && !newTabWidget) { // we already created one KCModuleProxy, so we need a tab widget. // Move the first proxy into the tab widget and ensure this and subsequent // proxies are in the tab widget newTabWidget = new QTabWidget(&configDialog); moduleProxyParentWidget = newTabWidget; mainWidget->setParent(newTabWidget); KCModuleProxy *moduleProxy = qobject_cast(mainWidget); if (moduleProxy) { newTabWidget->addTab(mainWidget, moduleProxy->moduleInfo().moduleName()); mainWidget = newTabWidget; } else { delete newTabWidget; - newTabWidget = 0; + newTabWidget = nullptr; moduleProxyParentWidget = &configDialog; - mainWidget->setParent(0); + mainWidget->setParent(nullptr); } } if (newTabWidget) { newTabWidget->addTab(currentModuleProxy, servicePtr->name()); } else { mainWidget = currentModuleProxy; } } else { delete currentModuleProxy; } } } // it could happen that we had services to show, but none of them were real modules. if (moduleProxyList.count()) { QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(mainWidget); const int marginHint = configDialog.style()->pixelMetric(QStyle::PM_DefaultChildMargin); layout->insertSpacing(-1, marginHint); QDialogButtonBox *buttonBox = new QDialogButtonBox(&configDialog); buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::RestoreDefaults); KGuiItem::assign(buttonBox->button(QDialogButtonBox::Ok), KStandardGuiItem::ok()); KGuiItem::assign(buttonBox->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel()); KGuiItem::assign(buttonBox->button(QDialogButtonBox::RestoreDefaults), KStandardGuiItem::defaults()); connect(buttonBox, &QDialogButtonBox::accepted, &configDialog, &QDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, &configDialog, &QDialog::reject); connect(buttonBox->button(QDialogButtonBox::RestoreDefaults), &QAbstractButton::clicked, this, &PluginDelegate::slotDefaultClicked); layout->addWidget(buttonBox); configDialog.setLayout(layout); if (configDialog.exec() == QDialog::Accepted) { foreach (KCModuleProxy *moduleProxy, moduleProxyList) { QStringList parentComponents = moduleProxy->moduleInfo().service()->property(QStringLiteral("X-KDE-ParentComponents")).toStringList(); moduleProxy->save(); foreach (const QString &parentComponent, parentComponents) { emit configCommitted(parentComponent.toLatin1()); } } } else { foreach (KCModuleProxy *moduleProxy, moduleProxyList) { moduleProxy->load(); } } qDeleteAll(moduleProxyList); moduleProxyList.clear(); } } void KPluginSelector::Private::PluginDelegate::slotDefaultClicked() { foreach (KCModuleProxy *moduleProxy, moduleProxyList) { moduleProxy->defaults(); } } QFont KPluginSelector::Private::PluginDelegate::titleFont(const QFont &baseFont) const { QFont retFont(baseFont); retFont.setBold(true); return retFont; } #include "moc_kpluginselector_p.cpp" #include "moc_kpluginselector.cpp" diff --git a/src/kpluginselector.h b/src/kpluginselector.h index 1f5267f..c7abbbf 100644 --- a/src/kpluginselector.h +++ b/src/kpluginselector.h @@ -1,230 +1,230 @@ /** * This file is part of the KDE project * Copyright (C) 2007, 2006 Rafael Fernández López * Copyright (C) 2002-2003 Matthias Kretz * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License version 2 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPLUGINSELECTOR_H #define KPLUGINSELECTOR_H #include #include #include #include class KPluginInfo; /** * @short A widget to select what plugins to load and configure the plugins. * * It shows the list of available plugins * * Since the user needs a way to know what a specific plugin does every plugin * sould install a desktop file containing a name, comment and category field. * The category is useful for applications that can use different kinds of * plugins like a playlist, skin or visualization * * The location of these desktop files is the * share/apps/<instancename>/<plugindir> directory. But if you need * you may use a different directory * * You can add plugins from different KConfig[group], by just calling all times * you want addPlugins method with the correct parameters * * Additionally, calls to constructor with same @p categoryName, will add new * items to the same category, even if plugins are from different categories * * @author Matthias Kretz * @author Rafael Fernández López */ class KCMUTILS_EXPORT KPluginSelector : public QWidget { Q_OBJECT Q_PROPERTY(QStringList configurationArguments READ configurationArguments WRITE setConfigurationArguments) public: enum PluginLoadMethod { ReadConfigFile = 0, IgnoreConfigFile }; /** * Create a new KPluginSelector */ - KPluginSelector(QWidget *parent = 0); + KPluginSelector(QWidget *parent = nullptr); /** * Destructor */ ~KPluginSelector(); /** * Add a list of KParts plugins * * The information about the plugins will be loaded from the * share/apps/<instancename>/kpartplugins directory * * @param componentName The name of the component of the plugin's parent. * @param categoryName The translated name of the category. This is the * name that is shown in the title. If the category * did exist before because of another call to * addPlugins, then they will be shown in that * category. If @p categoryName is a new one, then * a new category will be shown on the plugin window, * and the list of plugins added to it * @param categoryKey When you have different categories of KParts * plugins you distinguish between the plugins using * the Category key in the .desktop file. Use this * parameter to select only those KParts plugins * with the Category key == @p categoryKey. If * @p categoryKey is not set the Category key is * ignored and all plugins are shown. Not match case * @param config The KConfig object that holds the state of the * plugins being enabled or not. By default it will be * set to KSharedConfig::openConfig(componentName + "rc"). */ void addPlugins(const QString &componentName, const QString &categoryName = QString(), const QString &categoryKey = QString(), KSharedConfig::Ptr config = KSharedConfig::Ptr()); /** * Add a list of non-KParts plugins * * @param pluginInfoList A list of KPluginInfo objects containing the * necessary information for the plugins you want to * add to the list * @param pluginLoadMethod If KPluginSelector will try to load the * state of the plugin when loading the * dialog from the configuration file or not. * This is useful if for some reason you * called the setPluginEnabled() for each plugin * individually before loading the dialog, and * don't want KPluginSelector to override them * when loading * @param categoryName The translated name of the category. This is the * name that is shown in the title. If the category * did exist before because of another call to * addPlugins, then they will be shown in that * category. If @p categoryName is a new one, then * a new category will be shown on the plugin window, * and the list of plugins added to it * @param categoryKey When you have different categories of KParts * plugins you distinguish between the plugins using * the Category key in the .desktop file. Use this * parameter to select only those KParts plugins * with the Category key == @p categoryKey. If * @p categoryKey is not set the Category key is * ignored and all plugins are shown. Not match case * @param config The KConfig object that holds the state of the * plugins being enabled or not. By default it will * use KSharedConfig::openConfig(). It is recommended to * always pass a KConfig object if you use * KSettings::PluginPage since you never know from * where the page will be called (think global * config app). For example KViewCanvas passes * KConfig("kviewcanvas") * * @note All plugins that were set a config group using setConfig() method * will load and save their information from there. For those that * weren't any config object, @p config will be used */ void addPlugins(const QList &pluginInfoList, PluginLoadMethod pluginLoadMethod = ReadConfigFile, const QString &categoryName = QString(), const QString &categoryKey = QString(), const KSharedConfig::Ptr &config = KSharedConfig::Ptr()); /** * Load the state of the plugins (selected or not) from the KPluginInfo * objects */ void load(); /** * Save the configuration */ void save(); /** * Change to applications defaults * @see isDefault() */ void defaults(); /** * Returns true if the plugin selector does not have any changes to application defaults * @see defaults() * @since 4.3 */ bool isDefault() const; /** * Updates plugins state (enabled or not) * * This method won't save anything on any configuration file. It will just * be useful if you added plugins with the method: * * \code * void addPlugins(const QList &pluginInfoList, * const QString &categoryName = QString(), * const QString &categoryKey = QString(), * const KSharedConfig::Ptr &config = KSharedConfig::Ptr()); * \endcode * * To sum up, this method will update your plugins state depending if plugins * are ticked or not on the KPluginSelector dialog, without saving anything * anywhere */ void updatePluginsState(); /** * Sets the @p arguments with which the configuration modules will be initialized * * @since 5.9 */ void setConfigurationArguments(const QStringList &arguments); /** * Returns the configuration arguments that will be used * * @since 5.9 */ QStringList configurationArguments() const; Q_SIGNALS: /** * Tells you whether the configuration is changed or not. */ void changed(bool hasChanged); /** * Emitted after the config of an embedded KCM has been saved. The * argument is the name of the parent component that needs to reload * its config */ void configCommitted(const QByteArray &componentName); private: class Private; Private *const d; }; #endif diff --git a/src/kpluginselector_p.h b/src/kpluginselector_p.h index 650f605..7a991f8 100644 --- a/src/kpluginselector_p.h +++ b/src/kpluginselector_p.h @@ -1,220 +1,220 @@ /** * This file is part of the KDE project * Copyright (C) 2007, 2006 Rafael Fernández López * Copyright (C) 2002-2003 Matthias Kretz * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License version 2 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPLUGINSELECTOR_P_H #define KPLUGINSELECTOR_P_H #include #include #include #include #include #include class QLabel; class QCheckBox; class QLineEdit; class QPushButton; class QAbstractItemView; class KCategorizedView; class KCModuleProxy; class KCategoryDrawer; class PluginEntry; class KPluginSelector::Private : public QObject { Q_OBJECT public: enum ExtraRoles { PluginEntryRole = 0x09386561, ServicesCountRole = 0x1422E2AA, NameRole = 0x0CBBBB00, CommentRole = 0x19FC6DE2, AuthorRole = 0x30861E10, EmailRole = 0x02BE3775, WebsiteRole = 0x13095A34, VersionRole = 0x0A0CB450, LicenseRole = 0x001F308A, DependenciesRole = 0x04CAB650, IsCheckableRole = 0x0AC2AFF8 }; Private(KPluginSelector *parent); ~Private(); void updateDependencies(PluginEntry *pluginEntry, bool added); int dependantLayoutValue(int value, int width, int totalWidth) const; public: class PluginModel; class ProxyModel; class PluginDelegate; class DependenciesWidget; KPluginSelector *parent; QLineEdit *lineEdit; KCategorizedView *listView; KCategoryDrawer *categoryDrawer; PluginModel *pluginModel; ProxyModel *proxyModel; PluginDelegate *pluginDelegate; DependenciesWidget *dependenciesWidget; bool showIcons; QStringList kcmArguments; }; class PluginEntry { public: QString category; KPluginInfo pluginInfo; bool checked; bool manuallyAdded; KConfigGroup cfgGroup; KPluginSelector::PluginLoadMethod pluginLoadMethod; bool isCheckable; bool operator==(const PluginEntry &pe) const { // just comparing the entry path is not enough, since it is now also possible // to load the plugin information directly from a library (without .desktop files) return pluginInfo.entryPath() == pe.pluginInfo.entryPath() && pluginInfo.libraryPath() == pe.pluginInfo.libraryPath(); } }; Q_DECLARE_METATYPE(PluginEntry *) /** * This widget will inform the user about changes that happened automatically * due to plugin dependencies. */ class KPluginSelector::Private::DependenciesWidget : public QWidget { Q_OBJECT public: - DependenciesWidget(QWidget *parent = 0); + DependenciesWidget(QWidget *parent = nullptr); ~DependenciesWidget(); void addDependency(const QString &dependency, const QString &pluginCausant, bool added); void userOverrideDependency(const QString &dependency); void clearDependencies(); private Q_SLOTS: void showDependencyDetails(); private: struct FurtherInfo { bool added; QString pluginCausant; }; void updateDetails(); QLabel *details; QMap dependencyMap; int addedByDependencies; int removedByDependencies; }; class KPluginSelector::Private::PluginModel : public QAbstractListModel { public: - PluginModel(KPluginSelector::Private *pluginSelector_d, QObject *parent = 0); + PluginModel(KPluginSelector::Private *pluginSelector_d, QObject *parent = nullptr); ~PluginModel(); void addPlugins(const QList &pluginList, const QString &categoryName, const QString &categoryKey, const KConfigGroup &cfgGroup, PluginLoadMethod pluginLoadMethod = ReadConfigFile, bool manuallyAdded = false); QList pluginServices(const QModelIndex &index) const; QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) Q_DECL_OVERRIDE; int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; public: QList pluginEntryList; private: KPluginSelector::Private *pluginSelector_d; }; class KPluginSelector::Private::ProxyModel : public KCategorizedSortFilterProxyModel { public: - ProxyModel(KPluginSelector::Private *pluginSelector_d, QObject *parent = 0); + ProxyModel(KPluginSelector::Private *pluginSelector_d, QObject *parent = nullptr); ~ProxyModel(); protected: bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const Q_DECL_OVERRIDE; bool subSortLessThan(const QModelIndex &left, const QModelIndex &right) const Q_DECL_OVERRIDE; private: KPluginSelector::Private *pluginSelector_d; }; class KPluginSelector::Private::PluginDelegate : public KWidgetItemDelegate { Q_OBJECT public: - PluginDelegate(KPluginSelector::Private *pluginSelector_d, QObject *parent = 0); + PluginDelegate(KPluginSelector::Private *pluginSelector_d, QObject *parent = nullptr); ~PluginDelegate(); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const Q_DECL_OVERRIDE; Q_SIGNALS: void changed(bool hasChanged); void configCommitted(const QByteArray &componentName); protected: QList createItemWidgets(const QModelIndex &index) const Q_DECL_OVERRIDE; void updateItemWidgets(const QList widgets, const QStyleOptionViewItem &option, const QPersistentModelIndex &index) const Q_DECL_OVERRIDE; private Q_SLOTS: void slotStateChanged(bool state); void emitChanged(); void slotAboutClicked(); void slotConfigureClicked(); void slotDefaultClicked(); private: QFont titleFont(const QFont &baseFont) const; QCheckBox *checkBox; QPushButton *pushButton; QList moduleProxyList; KPluginSelector::Private *pluginSelector_d; }; #endif // KPLUGINSELECTOR_P_H diff --git a/src/ksettings/componentsdialog.cpp b/src/ksettings/componentsdialog.cpp index e24cd18..d13e784 100644 --- a/src/ksettings/componentsdialog.cpp +++ b/src/ksettings/componentsdialog.cpp @@ -1,180 +1,180 @@ /* This file is part of the KDE project Copyright (C) 2003 Matthias Kretz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "componentsdialog_p.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace KSettings { class ComponentsDialog::ComponentsDialogPrivate { public: QTreeWidget *listview; QFrame *infowidget; QLabel *iconwidget; QLabel *commentwidget; QLabel *descriptionwidget; QMap plugininfomap; QList plugininfolist; }; ComponentsDialog::ComponentsDialog(QWidget *parent, const char *name) : QDialog(parent), d(new ComponentsDialogPrivate) { setObjectName(QString::fromLatin1(name)); setModal(false); setWindowTitle(i18n("Select Components")); QVBoxLayout *layout = new QVBoxLayout; setLayout(layout); QWidget *page = new QWidget(this); layout->addWidget(page); QDialogButtonBox *buttonBox = new QDialogButtonBox(this); buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Cancel); connect(buttonBox->button(QDialogButtonBox::Apply), &QAbstractButton::clicked, this, &ComponentsDialog::savePluginInfos); connect(buttonBox, &QDialogButtonBox::accepted, this, &ComponentsDialog::savePluginInfos); connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); layout->addWidget(buttonBox); QHBoxLayout *hbox = new QHBoxLayout(page); hbox->setMargin(0); d->listview = new QTreeWidget(page); d->listview->setMinimumSize(200, 200); d->infowidget = new QFrame(page); d->infowidget->setMinimumSize(200, 200); QVBoxLayout *vbox = new QVBoxLayout(d->infowidget); vbox->setMargin(0); d->iconwidget = new QLabel(d->infowidget); vbox->addWidget(d->iconwidget); vbox->addWidget(new KSeparator(d->infowidget)); d->commentwidget = new QLabel(d->infowidget); d->commentwidget->setWordWrap(true); vbox->addWidget(d->commentwidget); d->descriptionwidget = new QLabel(d->infowidget); d->descriptionwidget->setWordWrap(true); vbox->addWidget(d->descriptionwidget); d->listview->setAcceptDrops(false); connect(d->listview, &QTreeWidget::itemPressed, this, &ComponentsDialog::executed); connect(d->listview, &QTreeWidget::itemActivated, this, &ComponentsDialog::executed); connect(d->listview, SIGNAL(itemSelectionChanged(QTreeWidgetItem*,int)), this, SLOT(executed(QTreeWidgetItem*,int))); } ComponentsDialog::~ComponentsDialog() { delete d; } void ComponentsDialog::addPluginInfo(KPluginInfo *info) { d->plugininfolist.append(info); } void ComponentsDialog::setPluginInfos(const QMap & plugininfos) { for (QMap::ConstIterator it = plugininfos.begin(); it != plugininfos.end(); ++it) { d->plugininfolist.append(it.value()); } } void ComponentsDialog::setPluginInfos(const QList &plugins) { d->plugininfolist = plugins; } void ComponentsDialog::show() { // clear the treelist d->listview->clear(); d->plugininfomap.clear(); // construct the treelist for (QList::ConstIterator it = d->plugininfolist.constBegin(); it != d->plugininfolist.constEnd(); ++it) { (*it)->load(); QTreeWidgetItem *item = new QTreeWidgetItem(d->listview, QStringList((*it)->name())); if (!(*it)->icon().isEmpty()) { item->setIcon(0, SmallIcon((*it)->icon(), IconSize(KIconLoader::Small))); } item->setCheckState(0, (*it)->isPluginEnabled() ? Qt::Checked : Qt::Unchecked); d->plugininfomap[ item ] = (*it); } QDialog::show(); } void ComponentsDialog::executed(QTreeWidgetItem *item, int) { // qDebug() ; - if (item == 0) { + if (item == nullptr) { return; } bool checked = (item->checkState(0) == Qt::Checked); // qDebug() << "it's a " << ( checked ? "checked" : "unchecked" ) // << " QCheckListItem" << endl; KPluginInfo *info = d->plugininfomap[ item ]; info->setPluginEnabled(checked); //checkDependencies( info ); // show info about the component on the right d->iconwidget->setPixmap(SmallIcon(info->icon(), KIconLoader::SizeLarge)); d->commentwidget->setText(info->comment()); //d->descriptionwidget->setText( info->description() ); } void ComponentsDialog::savePluginInfos() { for (QList::ConstIterator it = d->plugininfolist.constBegin(); it != d->plugininfolist.constEnd(); ++it) { if ((*it)->config().isValid()) { (*it)->save(); (*it)->config().sync(); } } } } //namespace #include "moc_componentsdialog_p.cpp" diff --git a/src/ksettings/componentsdialog_p.h b/src/ksettings/componentsdialog_p.h index ef4430e..8d9ad0d 100644 --- a/src/ksettings/componentsdialog_p.h +++ b/src/ksettings/componentsdialog_p.h @@ -1,84 +1,84 @@ /* This file is part of the KDE project Copyright (C) 2003 Matthias Kretz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef COMPONENTSDIALOG_P_H #define COMPONENTSDIALOG_P_H #include #include #include class QString; class KPluginInfo; class QTreeWidgetItem; namespace KSettings { /** Dialog for selecting which plugins should be active for an application. Set the list of available plugins with \ref setPluginInfos. The dialog will save the configuration on clicking ok or apply to the applications config file. Connect to the okClicked() and applyClicked() signals to be notified about configuration changes. */ class KCMUTILS_EXPORT ComponentsDialog : public QDialog { Q_OBJECT public: /** Create Dialog. @param parent parent widget @param name name */ - explicit ComponentsDialog(QWidget *parent = 0, const char *name = 0); + explicit ComponentsDialog(QWidget *parent = nullptr, const char *name = nullptr); ~ComponentsDialog(); /** Add a plugin that the dialog offers for selection. */ void addPluginInfo(KPluginInfo *); /** Set list of plugins the dialog offers for selection. (Overwrites a previous list) */ void setPluginInfos(const QMap &plugininfos); /** Set list of plugins the dialog offers for selection. (Overwrites a previous list) */ void setPluginInfos(const QList &plugins); /** * reimplemented */ void show(); private Q_SLOTS: void executed(QTreeWidgetItem *, int); void savePluginInfos(); private: class ComponentsDialogPrivate; ComponentsDialogPrivate *const d; }; } #endif // COMPONENTSDIALOG_P_H diff --git a/src/ksettings/dialog.cpp b/src/ksettings/dialog.cpp index eeff4f5..2eda90e 100644 --- a/src/ksettings/dialog.cpp +++ b/src/ksettings/dialog.cpp @@ -1,562 +1,562 @@ /* This file is part of the KDE project Copyright (C) 2003 Matthias Kretz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "dialog.h" #include "dialog_p.h" #include "dispatcher.h" //#include "componentsdialog_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include uint qHash(const KCModuleInfo &info) { return qHash(info.fileName()); } namespace KSettings { Dialog::Dialog(QWidget *parent) : KCMultiDialog(*new DialogPrivate(this), new KPageWidget, parent) { } Dialog::Dialog(const QStringList &components, QWidget *parent) : KCMultiDialog(*new DialogPrivate(this), new KPageWidget, parent) { Q_D(Dialog); d->components = components; } Dialog::~Dialog() { } void Dialog::setAllowComponentSelection(bool selection) { d_func()->staticlistview = !selection; } bool Dialog::allowComponentSelection() const { return !d_func()->staticlistview; } void Dialog::setKCMArguments(const QStringList &arguments) { Q_D(Dialog); d->arguments = arguments; } void Dialog::setComponentBlacklist(const QStringList &blacklist) { Q_D(Dialog); d->componentBlacklist = blacklist; } void Dialog::addPluginInfos(const KPluginInfo::List &plugininfos) { Q_D(Dialog); for (KPluginInfo::List::ConstIterator it = plugininfos.begin(); it != plugininfos.end(); ++it) { d->registeredComponents.append(it->pluginName()); if (it->kcmServices().isEmpty()) { // this plugin has no kcm services, still we want to show the disable/enable stuff // so add a dummy kcm KService::Ptr service = it->service(); d->kcmInfos << KCModuleInfo(service); continue; } foreach (const KService::Ptr &service, it->kcmServices()) { d->kcmInfos << KCModuleInfo(service); } } // The plugin, when disabled, disables all the KCMs described by kcmServices(). // - Normally they are grouped using a .setdlg file so that the group parent can get a // checkbox to enable/disable the plugin. // - If the plugin does not belong to a group and has only one KCM the checkbox can be // used with this KCM. // - If the plugin belongs to a group but there are other modules in the group that do not // belong to this plugin we give a kError and show no checkbox // - If the plugin belongs to multiple groups we give a kError and show no checkbox d->plugininfos = plugininfos; } KPluginInfo::List Dialog::pluginInfos() const { return d_func()->plugininfos; } void Dialog::showEvent(QShowEvent *) { Q_D(Dialog); if (d->firstshow) { setUpdatesEnabled(false); d->kcmInfos += d->instanceServices(); if (!d->components.isEmpty()) { d->kcmInfos += d->parentComponentsServices(d->components); } d->createDialogFromServices(); d->firstshow = false; setUpdatesEnabled(true); } Dispatcher::syncConfiguration(); } DialogPrivate::DialogPrivate(Dialog *parent) : KCMultiDialogPrivate(parent), staticlistview(true), firstshow(true), pluginStateDirty(0) { } QSet DialogPrivate::instanceServices() { //qDebug() ; QString componentName = QCoreApplication::instance()->applicationName(); registeredComponents.append(componentName); //qDebug() << "calling KServiceGroup::childGroup( " << componentName << " )"; KServiceGroup::Ptr service = KServiceGroup::childGroup(componentName); QSet ret; if (service && service->isValid()) { //qDebug() << "call was successful"; const KServiceGroup::List list = service->entries(); for (KServiceGroup::List::ConstIterator it = list.begin(); it != list.end(); ++it) { KSycocaEntry::Ptr p = (*it); if (p->isType(KST_KService)) { //qDebug() << "found service"; const KService::Ptr service(static_cast(p.data())); ret << KCModuleInfo(service); } else qWarning() << "KServiceGroup::childGroup returned" " something else than a KService" << endl; } } return ret; } QSet DialogPrivate::parentComponentsServices(const QStringList &kcdparents) { registeredComponents += kcdparents; QString constraint = kcdparents.join(QStringLiteral("' in [X-KDE-ParentComponents]) or ('")); constraint = QStringLiteral("('") + constraint + QStringLiteral("' in [X-KDE-ParentComponents])"); //qDebug() << "constraint = " << constraint; const QList services = KServiceTypeTrader::self()->query(QStringLiteral("KCModule"), constraint); QSet ret; foreach (const KService::Ptr &service, services) { ret << KCModuleInfo(service); } return ret; } bool DialogPrivate::isPluginForKCMEnabled(const KCModuleInfo *moduleinfo, KPluginInfo &pinfo) const { // if the user of this class requested to hide disabled modules // we check whether it should be enabled or not bool enabled = true; //qDebug() << "check whether the '" << moduleinfo->moduleName() << "' KCM should be shown"; // for all parent components const QStringList parentComponents = moduleinfo->service()->property( QStringLiteral("X-KDE-ParentComponents")).toStringList(); for (QStringList::ConstIterator pcit = parentComponents.begin(); pcit != parentComponents.end(); ++pcit) { // if the parentComponent is not registered ignore it if (!registeredComponents.contains(*pcit)) { continue; } // we check if the parent component is a plugin // if not the KCModule must be enabled enabled = true; if (pinfo.pluginName() == *pcit) { // it is a plugin: we check whether the plugin is enabled pinfo.load(); enabled = pinfo.isPluginEnabled(); //qDebug() << "parent " << *pcit << " is " << (enabled ? "enabled" : "disabled"); } // if it is enabled we're done for this KCModuleInfo if (enabled) { return true; } } return enabled; } bool DialogPrivate::isPluginImmutable(const KPluginInfo &pinfo) const { return pinfo.property(QStringLiteral("X-KDE-PluginInfo-Immutable")).toBool(); } KPageWidgetItem *DialogPrivate::createPageItem(KPageWidgetItem *parentItem, const QString &name, const QString &comment, const QString &iconName, int weight) { Q_Q(Dialog); QWidget *page = new QWidget(q); QCheckBox *checkBox = new QCheckBox(i18n("Enable component"), page); QLabel *iconLabel = new QLabel(page); QLabel *commentLabel = new QLabel(comment, page); commentLabel->setTextFormat(Qt::RichText); QVBoxLayout *layout = new QVBoxLayout(page); layout->addWidget(checkBox); layout->addWidget(iconLabel); layout->addWidget(commentLabel); layout->addStretch(); page->setLayout(layout); KPageWidgetItem *item = new KPageWidgetItem(page, name); item->setIcon(QIcon::fromTheme(iconName)); iconLabel->setPixmap(item->icon().pixmap(128, 128)); item->setProperty("_k_weight", weight); checkBoxForItem.insert(item, checkBox); const KPageWidgetModel *model = qobject_cast(q->pageWidget()->model()); Q_ASSERT(model); if (parentItem) { const QModelIndex parentIndex = model->index(parentItem); const int siblingCount = model->rowCount(parentIndex); int row = 0; for (; row < siblingCount; ++row) { KPageWidgetItem *siblingItem = model->item(parentIndex.child(row, 0)); if (siblingItem->property("_k_weight").toInt() > weight) { // the item we found is heavier than the new module q->insertPage(siblingItem, item); break; } } if (row == siblingCount) { // the new module is either the first or the heaviest item q->addSubPage(parentItem, item); } } else { const int siblingCount = model->rowCount(); int row = 0; for (; row < siblingCount; ++row) { KPageWidgetItem *siblingItem = model->item(model->index(row, 0)); if (siblingItem->property("_k_weight").toInt() > weight) { // the item we found is heavier than the new module q->insertPage(siblingItem, item); break; } } if (row == siblingCount) { // the new module is either the first or the heaviest item q->addPage(item); } } return (item); } void DialogPrivate::parseGroupFile(const QString &filename) { KConfig file(filename, KConfig::SimpleConfig); const QStringList groups = file.groupList(); foreach (const QString &group, groups) { if (group.isEmpty()) { continue; } KConfigGroup conf(&file, group); const QString parentId = conf.readEntry("Parent"); KPageWidgetItem *parentItem = pageItemForGroupId.value(parentId); KPageWidgetItem *item = createPageItem(parentItem, conf.readEntry("Name"), conf.readEntry("Comment"), conf.readEntry("Icon"), conf.readEntry("Weight", 100)); pageItemForGroupId.insert(group, item); } } void DialogPrivate::createDialogFromServices() { Q_Q(Dialog); // read .setdlg files (eg: share/kapp/kapp.setdlg) QString setdlgpath = QStandardPaths::locate(QStandardPaths::DataLocation /*includes appname, too*/, QCoreApplication::instance()->applicationName() + QStringLiteral(".setdlg")); if (!setdlgpath.isEmpty()) { parseGroupFile(setdlgpath); } const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::DataLocation, QStringLiteral("ksettingsdialog"), QStandardPaths::LocateDirectory); Q_FOREACH (const QString &dir, dirs) { const QStringList fileNames = QDir(dir).entryList(QStringList() << QStringLiteral("*.setdlg")); Q_FOREACH (const QString &file, fileNames) { parseGroupFile(dir + QLatin1Char('/') + file); } } //qDebug() << kcmInfos.count(); foreach (const KCModuleInfo &info, kcmInfos) { const QStringList parentComponents = info.service()->property(QStringLiteral("X-KDE-ParentComponents")).toStringList(); bool blacklisted = false; foreach (const QString &parentComponent, parentComponents) { if (componentBlacklist.contains(parentComponent)) { blacklisted = true; break; } } if (blacklisted) { continue; } const QString parentId = info.service()->property(QStringLiteral("X-KDE-CfgDlgHierarchy"), QVariant::String).toString(); KPageWidgetItem *parent = pageItemForGroupId.value(parentId); if (!parent) { // dummy kcm bool foundPlugin = false; foreach (const KPluginInfo &pinfo, plugininfos) { if (pinfo.service() == info.service()) { if (!pinfo.kcmServices().count()) { const KService::Ptr service = info.service(); // FIXME get weight from service or plugin info const int weight = 1000; - KPageWidgetItem *item = createPageItem(0, service->name(), service->comment(), service->icon(), weight); + KPageWidgetItem *item = createPageItem(nullptr, service->name(), service->comment(), service->icon(), weight); connectItemCheckBox(item, pinfo, pinfo.isPluginEnabled()); foundPlugin = true; break; } } } if (foundPlugin) { continue; } } KPageWidgetItem *item = q->addModule(info, parent, arguments); // qDebug() << "added KCM '" << info.moduleName() << "'"; foreach (KPluginInfo pinfo, plugininfos) { // qDebug() << pinfo.pluginName(); if (pinfo.kcmServices().contains(info.service())) { const bool isEnabled = isPluginForKCMEnabled(&info, pinfo); // qDebug() << "correct KPluginInfo for this KCM"; // this KCM belongs to a plugin if (parent && pinfo.kcmServices().count() >= 1) { item->setEnabled(isEnabled); const KPluginInfo &plugin = pluginForItem.value(parent); if (plugin.isValid()) { if (plugin != pinfo) { qCritical() << "A group contains more than one plugin: '" << plugin.pluginName() << "' and '" << pinfo.pluginName() << "'. Now it won't be possible to enable/disable the plugin." << endl; parent->setCheckable(false); q->disconnect(parent, SIGNAL(toggled(bool)), q, SLOT(_k_updateEnabledState(bool))); } // else everything is fine } else { connectItemCheckBox(parent, pinfo, isEnabled); } } else { pluginForItem.insert(item, pinfo); item->setCheckable(!isPluginImmutable(pinfo)); item->setChecked(isEnabled); q->connect(item, SIGNAL(toggled(bool)), q, SLOT(_k_updateEnabledState(bool))); } break; } } } // now that the KCMs are in, check for empty groups and remove them again { const KPageWidgetModel *model = qobject_cast(q->pageWidget()->model()); const QHash::ConstIterator end = pageItemForGroupId.constEnd(); QHash::ConstIterator it = pageItemForGroupId.constBegin(); for (; it != end; ++it) { const QModelIndex index = model->index(it.value()); KPluginInfo pinfo; foreach (const KPluginInfo &p, plugininfos) { if (p.name() == it.key()) { pinfo = p; break; } } bool allowEmpty = false; if (pinfo.isValid()) { allowEmpty = pinfo.property(QStringLiteral("X-KDE-PluginInfo-AllowEmptySettings")).toBool(); } if (!index.child(0, 0).isValid()) { // no children, and it's not allowed => remove this item if (!allowEmpty) { q->removePage(it.value()); } else { connectItemCheckBox(it.value(), pinfo, pinfo.isPluginEnabled()); } } } } // TODO: Don't show the reset button until the issue with the // KPluginSelector::load() method is solved. // Problem: // KCMultiDialog::show() call KCModule::load() to reset all KCMs // (KPluginSelector::load() resets all plugin selections and all plugin // KCMs). // The reset button calls KCModule::load(), too but in this case we want the // KPluginSelector to only reset the current visible plugin KCM and not // touch the plugin selections. // I have no idea how to check that in KPluginSelector::load()... //q->showButton(KDialog::User1, true); QObject::connect(q->button(QDialogButtonBox::Ok), SIGNAL(clicked()), q, SLOT(_k_syncConfiguration())); QObject::connect(q->button(QDialogButtonBox::Apply), SIGNAL(clicked()), q, SLOT(_k_syncConfiguration())); QObject::connect(q, SIGNAL(configCommitted(QByteArray)), q, SLOT(_k_reparseConfiguration(QByteArray))); } void DialogPrivate::connectItemCheckBox(KPageWidgetItem *item, const KPluginInfo &pinfo, bool isEnabled) { Q_Q(Dialog); QCheckBox *checkBox = checkBoxForItem.value(item); Q_ASSERT(checkBox); pluginForItem.insert(item, pinfo); item->setCheckable(!isPluginImmutable(pinfo)); item->setChecked(isEnabled); checkBox->setVisible(!isPluginImmutable(pinfo)); checkBox->setChecked(isEnabled); q->connect(item, SIGNAL(toggled(bool)), q, SLOT(_k_updateEnabledState(bool))); q->connect(item, &KPageWidgetItem::toggled, checkBox, &QAbstractButton::setChecked); q->connect(checkBox, &QAbstractButton::clicked, item, &KPageWidgetItem::setChecked); } void DialogPrivate::_k_syncConfiguration() { Q_Q(Dialog); const QHash::Iterator endIt = pluginForItem.end(); QHash::Iterator it = pluginForItem.begin(); for (; it != endIt; ++it) { KPageWidgetItem *item = it.key(); KPluginInfo pinfo = it.value(); pinfo.setPluginEnabled(item->isChecked()); pinfo.save(); } if (pluginStateDirty > 0) { emit q->pluginSelectionChanged(); pluginStateDirty = 0; } Dispatcher::syncConfiguration(); } void DialogPrivate::_k_reparseConfiguration(const QByteArray &a) { Dispatcher::reparseConfiguration(QString::fromLatin1(a)); } /* void DialogPrivate::_k_configureTree() { // qDebug() ; QObject::connect(subdlg, SIGNAL(okClicked()), q, SLOT(_k_updateTreeList())); QObject::connect(subdlg, SIGNAL(applyClicked()), q, SLOT(_k_updateTreeList())); QObject::connect(subdlg, SIGNAL(okClicked()), q, SIGNAL(pluginSelectionChanged())); QObject::connect(subdlg, SIGNAL(applyClicked()), q, SIGNAL(pluginSelectionChanged())); } */ void DialogPrivate::_k_clientChanged() { if (pluginStateDirty > 0) { Q_Q(Dialog); q->buttonBox()->button(QDialogButtonBox::Apply)->setEnabled(true); } else { KCMultiDialogPrivate::_k_clientChanged(); } } void DialogPrivate::_k_updateEnabledState(bool enabled) { Q_Q(Dialog); KPageWidgetItem *item = qobject_cast(q->sender()); if (!item) { qWarning() << "invalid sender"; return; } // iterate over all child KPageWidgetItem objects and check whether they need to be enabled/disabled const KPageWidgetModel *model = qobject_cast(q->pageWidget()->model()); Q_ASSERT(model); QModelIndex index = model->index(item); if (!index.isValid()) { qWarning() << "could not find item in model"; return; } const KPluginInfo &pinfo = pluginForItem.value(item); if (!pinfo.isValid()) { qWarning() << "could not find KPluginInfo in item"; return; } if (pinfo.isPluginEnabled() != enabled) { ++pluginStateDirty; } else { --pluginStateDirty; } if (pluginStateDirty < 2) { _k_clientChanged(); } //qDebug() ; QModelIndex firstborn = index.child(0, 0); if (firstborn.isValid()) { //qDebug() << "iterating over children"; // change all children index = firstborn; QStack stack; while (index.isValid()) { //qDebug() << index; KPageWidgetItem *item = model->item(index); //qDebug() << "item->setEnabled(" << enabled << ')'; item->setEnabled(enabled); firstborn = index.child(0, 0); if (firstborn.isValid()) { stack.push(index); index = firstborn; } else { index = index.sibling(index.row() + 1, 0); while (!index.isValid() && !stack.isEmpty()) { index = stack.pop(); index = index.sibling(index.row() + 1, 0); } } } } } } //namespace #include "moc_dialog.cpp" diff --git a/src/ksettings/dialog.h b/src/ksettings/dialog.h index fd8c0af..2844f3f 100644 --- a/src/ksettings/dialog.h +++ b/src/ksettings/dialog.h @@ -1,184 +1,184 @@ /* This file is part of the KDE project Copyright (C) 2003 Matthias Kretz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KSETTINGS_DIALOG_H #define KSETTINGS_DIALOG_H #include #include #include #include template class QList; class KPluginInfo; class KCModuleInfo; namespace KSettings { class DialogPrivate; /** * @short Generic configuration dialog that works over component boundaries * * For more information see \ref KSettings. * * This class aims to standardize the use of configuration dialogs in KDE * applications. Especially when using KParts and/or Plugins you face problems * creating a consistent config dialog. * * To show a configuration dialog you only have to call the show method and be * done with it. A code example: * * You initialize \p m_cfgdlg with * \code * m_cfgdlg = new Dialog( this ); * \endcode * If you use a KPart that was not especially designed for your app you can use * the second constructor: * \code * QStringList kpartslist; * for( all my kparts ) * kpartslist += m_mypart->componentData().componentName(); * m_cfgdlg = new Dialog( kpartslist, this ); * \endcode * and the action for the config dialog is connected to the show slot: * \code * KStandardAction::preferences( m_cfgdlg, SLOT( show() ), actionCollection() ); * \endcode * * If you need to be informed when the config was changed and applied in the * dialog you might want to take a look at Dispatcher. * * For more information see \ref KSettings. * * @author Matthias Kretz */ class KCMUTILS_EXPORT Dialog : public KCMultiDialog { friend class PageNode; Q_DECLARE_PRIVATE(Dialog) Q_OBJECT public: /** * Construct a new Preferences Dialog for the application. It uses all * KCMs with X-KDE-ParentApp set to QCoreApplication::instance()->applicationName(). * * @param content Select whether you want a static or configurable * config dialog. * @param parent The parent is only used as the parent for the * dialog - centering the dialog over the parent * widget. */ - explicit Dialog(QWidget *parent = 0); + explicit Dialog(QWidget *parent = nullptr); /** * Construct a new Preferences Dialog with the pages for the selected * instance names. For example if you want to have the configuration * pages for the kviewviewer KPart you would pass a * QStringList consisting of only the name of the part "kviewviewer". * * @param components A list of the names of the components that your * config dialog should merge the config pages in. * @param parent The parent is only used as the parent for the * dialog - centering the dialog over the parent * widget. */ - explicit Dialog(const QStringList &components, QWidget *parent = 0); + explicit Dialog(const QStringList &components, QWidget *parent = nullptr); ~Dialog(); /** * If you use a Configurable dialog you need to pass KPluginInfo * objects that the dialog should configure. */ void addPluginInfos(const QList &plugininfos); /** * Sets the argument list that is given to all the KControlModule's when * they are created. * Use this if you have KControlModule's that need special arguments to * work * * Note that this function only works before showing the * KSettings::Dialog for the first time. * @param arguments The list of arguments passed to each KCM */ void setKCMArguments(const QStringList &arguments); /** * Set the blacklisted component list. Any KCM that lists one * of the components in the given blacklist is not loaded even if it * would fit otherwise. This is a way to explicitly prevent loading of * certain KControlModules. * * Note that this function only works before showing the * KSettings::Dialog for the first time. * @param blacklist the list of components that prevent a KCM from being * loaded */ void setComponentBlacklist(const QStringList &blacklist); /** * Tells the dialog whether the entries in the listview are all static * or whether it should add checkboxes to select which parts * of the optional functionality should be active or not. * * Note that this function only works before showing the dialog for the first time. * * Defaults to \p false. * * @param allowSelection \p true The user can select what functionality he wants. * @param allowSelection \p false While running no entries are added or deleted */ void setAllowComponentSelection(bool allowSelection); bool allowComponentSelection() const; /** * Returns a list of all KPluginInfo objects the dialog uses. */ QList pluginInfos() const; protected: /** * Reimplemented to lazy create the dialog on first show. */ void showEvent(QShowEvent *) Q_DECL_OVERRIDE; Q_SIGNALS: /** * If you use the dialog in Configurable mode and want to be notified * when the user changes the plugin selections use this signal. It's * emitted if the selection has changed and the user pressed Apply or * Ok. In the slot you would then load and unload the plugins as * requested. */ void pluginSelectionChanged(); private: //Q_PRIVATE_SLOT(d_func(), void _k_configureTree()) Q_PRIVATE_SLOT(d_func(), void _k_updateEnabledState(bool)) Q_PRIVATE_SLOT(d_func(), void _k_syncConfiguration()) Q_PRIVATE_SLOT(d_func(), void _k_reparseConfiguration(const QByteArray &)) }; } #endif // KSETTINGS_DIALOG_H diff --git a/src/ksettings/pluginpage.cpp b/src/ksettings/pluginpage.cpp index 8e86e04..4afc0a0 100644 --- a/src/ksettings/pluginpage.cpp +++ b/src/ksettings/pluginpage.cpp @@ -1,84 +1,84 @@ /* This file is part of the KDE project Copyright (C) 2003 Matthias Kretz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "ksettings/pluginpage.h" #include "kpluginselector.h" #include #include "ksettings/dispatcher.h" #include namespace KSettings { class PluginPagePrivate { public: PluginPagePrivate() - : selwid(0) + : selwid(nullptr) { } KPluginSelector *selwid; void _k_reparseConfiguration(const QByteArray &a); }; PluginPage::PluginPage(const KAboutData *aboutData, QWidget *parent, const QVariantList &args) : KCModule(aboutData, parent, args), d_ptr(new PluginPagePrivate) { Q_D(PluginPage); d->selwid = new KPluginSelector(this); connect(d->selwid, SIGNAL(changed(bool)), this, SIGNAL(changed(bool))); connect(d->selwid, SIGNAL(configCommitted(QByteArray)), this, SLOT(_k_reparseConfiguration(QByteArray))); } void PluginPagePrivate::_k_reparseConfiguration(const QByteArray &a) { Dispatcher::reparseConfiguration(QString::fromLatin1(a)); } PluginPage::~PluginPage() { delete d_ptr; } KPluginSelector *PluginPage::pluginSelector() { return d_ptr->selwid; } void PluginPage::load() { d_ptr->selwid->load(); } void PluginPage::save() { d_ptr->selwid->save(); } void PluginPage::defaults() { d_ptr->selwid->defaults(); } } //namespace #include "moc_pluginpage.cpp" diff --git a/src/ksettings/pluginpage.h b/src/ksettings/pluginpage.h index 486b46b..caed49f 100644 --- a/src/ksettings/pluginpage.h +++ b/src/ksettings/pluginpage.h @@ -1,115 +1,115 @@ /* This file is part of the KDE project Copyright (C) 2003 Matthias Kretz This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KSETTINGS_PLUGINPAGE_H #define KSETTINGS_PLUGINPAGE_H #include #include class KPluginSelector; namespace KSettings { class PluginPagePrivate; /** * @short Convenience KCModule for creating a plugins config page. * * This class makes it very easy to create a plugins configuration page to your * program. All you need to do is create a class that is derived from * PluginPage and add the appropriate plugin information to the KPluginSelector. * This is done using the pluginSelector() method: * \code * K_PLUGIN_FACTORY(MyAppPluginConfigFactory, * registerPlugin(); * ) * * MyAppPluginConfig(QWidget * parent, const QVariantList & args) * : PluginPage(MyAppPluginConfigFactory::componentData(), parent, args) * { * pluginSelector()->addPlugins( QCoreApplication::instance()->applicationName(), i18n( "General Plugins" ), "General" ); * pluginSelector()->addPlugins( QCoreApplication::instance()->applicationName(), i18n( "Effects" ), "Effects" ); * } * \endcode * * All that remains to be done is to create the appropriate .desktop file * \verbatim [Desktop Entry] Encoding=UTF-8 Icon=plugin Type=Service ServiceTypes=KCModule X-KDE-Library=myapppluginconfig X-KDE-FactoryName=MyAppPluginConfigFactory X-KDE-ParentApp=myapp X-KDE-ParentComponents=myapp Name=Plugins Comment=Select and configure your plugins: \endverbatim * * @author Matthias Kretz */ class KCMUTILS_EXPORT PluginPage : public KCModule { Q_OBJECT Q_DECLARE_PRIVATE(PluginPage) public: /** * Standard KCModule constructor. * Automatically creates the KPluginSelector widget. */ explicit PluginPage(const KAboutData *aboutData, - QWidget *parent = 0, + QWidget *parent = nullptr, const QVariantList &args = QVariantList()); ~PluginPage(); /** * @return a reference to the KPluginSelector. */ KPluginSelector *pluginSelector(); /** * Load the state of the plugins (selected or not) from the KPluginInfo * objects. For KParts plugins everything should work automatically. For * your own type of plugins you might need to reimplement the * KPluginInfo::pluginLoaded() method. If that doesn't fit your needs * you can also reimplement this method. */ void load() Q_DECL_OVERRIDE; /** * Save the state of the plugins to KConfig objects */ void save() Q_DECL_OVERRIDE; void defaults() Q_DECL_OVERRIDE; protected: PluginPagePrivate *const d_ptr; private: Q_PRIVATE_SLOT(d_func(), void _k_reparseConfiguration(const QByteArray &a)) }; } #endif // KSETTINGS_PLUGINPAGE_H