diff --git a/applets/appmenu/lib/appmenuapplet.h b/applets/appmenu/lib/appmenuapplet.h --- a/applets/appmenu/lib/appmenuapplet.h +++ b/applets/appmenu/lib/appmenuapplet.h @@ -33,8 +33,6 @@ { Q_OBJECT - Q_PROPERTY(bool appletEnabled READ appletEnabled NOTIFY appletEnabledChanged) - Q_PROPERTY(AppMenuModel* model READ model WRITE setModel NOTIFY modelChanged) Q_PROPERTY(int view READ view WRITE setView NOTIFY viewChanged) @@ -65,18 +63,14 @@ int view() const; void setView(int type); - bool appletEnabled() const; - signals: void modelChanged(); void viewChanged(); void currentIndexChanged(); void buttonGridChanged(); - void appletEnabledChanged(); void requestActivateIndex(int index); public slots: - void updateAppletEnabled(); void trigger(QQuickItem *ctx, int idx); protected: @@ -90,8 +84,8 @@ int m_currentIndex = -1; int m_viewType = FullView; - bool m_appletEnabled = true; QPointer m_currentMenu; QPointer m_buttonGrid; QPointer m_model; + static int s_refs; }; diff --git a/applets/appmenu/lib/appmenuapplet.cpp b/applets/appmenu/lib/appmenuapplet.cpp --- a/applets/appmenu/lib/appmenuapplet.cpp +++ b/applets/appmenu/lib/appmenuapplet.cpp @@ -30,24 +30,53 @@ #include #include #include +#include +#include +#include #include +int AppMenuApplet::s_refs = 0; + +static const QString s_viewService(QStringLiteral("org.kde.kappmenuview")); + AppMenuApplet::AppMenuApplet(QObject *parent, const QVariantList &data) : Plasma::Applet(parent, data) { + ++s_refs; + //if we're the first, regster the service + if (s_refs == 1) { + QDBusConnection::sessionBus().interface()->registerService(s_viewService, + QDBusConnectionInterface::QueueService, + QDBusConnectionInterface::DontAllowReplacement); + } + /*it registers or unregisters the service when the destroyed value of the applet change, + and not in the dtor, because: + when we "delete" an applet, it just hides it for about a minute setting its status + to destroyed, in order to be able to do a clean undo: if we undo, there will be + another destroyedchanged and destroyed will be false. + When this happens, if we are the only appmenu applet existing, the dbus interface + will have to be registered again*/ + connect(this, &Applet::destroyedChanged, this, [this](bool destroyed) { + if (destroyed) { + //if we were the last, unregister + if (--s_refs == 0) { + QDBusConnection::sessionBus().interface()->unregisterService(s_viewService); + } + } else { + //if we're the first, regster the service + if (++s_refs == 1) { + QDBusConnection::sessionBus().interface()->registerService(s_viewService, + QDBusConnectionInterface::QueueService, + QDBusConnectionInterface::DontAllowReplacement); + } + } + }); } AppMenuApplet::~AppMenuApplet() = default; void AppMenuApplet::init() { - // TODO Wayland PlasmaShellSurface stuff - QDBusConnection::sessionBus().connect(QStringLiteral("org.kde.kappmenu"), - QStringLiteral("/KAppMenu"), - QStringLiteral("org.kde.kappmenu"), - QStringLiteral("reconfigured"), - this, SLOT(updateAppletEnabled())); - updateAppletEnabled(); } AppMenuModel *AppMenuApplet::model() const @@ -102,24 +131,6 @@ } } -bool AppMenuApplet::appletEnabled() const -{ - return m_appletEnabled; -} - -void AppMenuApplet::updateAppletEnabled() -{ - KConfigGroup config(KSharedConfig::openConfig(QStringLiteral("kdeglobals")), QStringLiteral("Appmenu Style")); - const QString &menuStyle = config.readEntry(QStringLiteral("Style")); - - const bool enabled = (menuStyle == QLatin1String("Widget")); - - if (m_appletEnabled != enabled) { - m_appletEnabled = enabled; - emit appletEnabledChanged(); - } -} - QMenu *AppMenuApplet::createMenu(int idx) const { QMenu *menu = nullptr; diff --git a/applets/appmenu/package/contents/ui/main.qml b/applets/appmenu/package/contents/ui/main.qml --- a/applets/appmenu/package/contents/ui/main.qml +++ b/applets/appmenu/package/contents/ui/main.qml @@ -30,7 +30,6 @@ id: root readonly property bool vertical: plasmoid.formFactor === PlasmaCore.Types.Vertical - readonly property bool appletEnabled: plasmoid.nativeInterface.appletEnabled readonly property bool view: plasmoid.configuration.compactView readonly property bool menuAvailable: appMenuModel.menuAvailable @@ -40,31 +39,25 @@ plasmoid.nativeInterface.view = view } - Plasmoid.preferredRepresentation: (plasmoid.configuration.compactView || vertical || !appletEnabled) ? Plasmoid.compactRepresentation : Plasmoid.fullRepresentation + Plasmoid.preferredRepresentation: (plasmoid.configuration.compactView || vertical) ? Plasmoid.compactRepresentation : Plasmoid.fullRepresentation Plasmoid.compactRepresentation: PlasmaComponents.ToolButton { readonly property int fakeIndex: 0 Layout.fillWidth: false Layout.fillHeight: false Layout.minimumWidth: implicitWidth Layout.maximumWidth: implicitWidth - enabled: appletEnabled ? menuAvailable : kcmAuthorized - checkable: appletEnabled && menuAvailable && plasmoid.nativeInterface.currentIndex === fakeIndex + enabled: menuAvailable + checkable: menuAvailable && plasmoid.nativeInterface.currentIndex === fakeIndex checked: checkable - iconSource: appletEnabled ? "application-menu" : "emblem-warning" - onClicked: { - if (appletEnabled) { - plasmoid.nativeInterface.trigger(this, 0); - } else { - KCMShell.open("style") - } - } + iconSource: i18n("application-menu") + onClicked: plasmoid.nativeInterface.trigger(this, 0); } Plasmoid.fullRepresentation: GridLayout { id: buttonGrid //when we're not enabled set to active to show the configure button - Plasmoid.status: !appletEnabled || buttonRepeater.count > 0 ? + Plasmoid.status: buttonRepeater.count > 0 ? PlasmaCore.Types.ActiveStatus : PlasmaCore.Types.HiddenStatus Layout.minimumWidth: implicitWidth Layout.minimumHeight: implicitHeight @@ -107,10 +100,6 @@ } } - Plasmoid.toolTipMainText: appletEnabled ? "" : i18n("Application Menu Widget is disabled") - Plasmoid.toolTipSubText: appletEnabled || !root.kcmAuthorized ? "" - : i18nc("it being the 'Application Menu Widget'", "Go to System Settings > Application Style > Fine Tuning (tab) to enable it."); - AppMenuPrivate.AppMenuModel { id: appMenuModel onRequestActivateIndex: plasmoid.nativeInterface.requestActivateIndex(index) diff --git a/appmenu/appmenu.h b/appmenu/appmenu.h --- a/appmenu/appmenu.h +++ b/appmenu/appmenu.h @@ -33,6 +33,7 @@ #include "menuimporter.h" class QDBusPendingCallWatcher; +class QDBusServiceWatcher; class KDBusMenuImporter; class AppmenuDBus; class TopMenuBar; @@ -91,6 +92,7 @@ MenuImporter *m_menuImporter = nullptr; AppmenuDBus *m_appmenuDBus; + QDBusServiceWatcher *m_menuViewWatcher; QPointer m_menu; }; diff --git a/appmenu/appmenu.cpp b/appmenu/appmenu.cpp --- a/appmenu/appmenu.cpp +++ b/appmenu/appmenu.cpp @@ -71,6 +71,35 @@ connect(this, &AppMenuModule::showRequest, m_appmenuDBus, &AppmenuDBus::showRequest); connect(this, &AppMenuModule::menuHidden, m_appmenuDBus, &AppmenuDBus::menuHidden); connect(this, &AppMenuModule::menuShown, m_appmenuDBus, &AppmenuDBus::menuShown); + + m_menuViewWatcher = new QDBusServiceWatcher(QStringLiteral("org.kde.kappmenuview"), QDBusConnection::sessionBus(), + QDBusServiceWatcher::WatchForRegistration|QDBusServiceWatcher::WatchForUnregistration, this); + + auto setupMenuImporter = [this]() { + QDBusConnection::sessionBus().connect({}, {}, QStringLiteral("com.canonical.dbusmenu"), + QStringLiteral("ItemActivationRequested"), + this, SLOT(itemActivationRequested(int,uint))); + + // Setup a menu importer if needed + if (!m_menuImporter) { + m_menuImporter = new MenuImporter(this); + connect(m_menuImporter, &MenuImporter::WindowRegistered, this, &AppMenuModule::slotWindowRegistered); + m_menuImporter->connectToBus(); + } + }; + connect(m_menuViewWatcher, &QDBusServiceWatcher::serviceRegistered, this, setupMenuImporter); + connect(m_menuViewWatcher, &QDBusServiceWatcher::serviceUnregistered, this, [this](const QString &service) { + Q_UNUSED(service) + QDBusConnection::sessionBus().disconnect({}, {}, QStringLiteral("com.canonical.dbusmenu"), + QStringLiteral("ItemActivationRequested"), + this, SLOT(itemActivationRequested(int,uint))); + delete m_menuImporter; + m_menuImporter = nullptr; + }); + + if (QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.kappmenuview"))) { + setupMenuImporter(); + } } AppMenuModule::~AppMenuModule() = default; @@ -174,36 +203,9 @@ emit showRequest(message().service(), QDBusObjectPath(message().path()), actionId); } -// reload settings +// this method is not really used anymore but has to be kept for DBus compatibility void AppMenuModule::reconfigure() { - hideMenu(); // hide window decoration menu if exists - - KConfigGroup config(KSharedConfig::openConfig(QStringLiteral("kdeglobals")), QStringLiteral("Appmenu Style")); - const QString &menuStyle = config.readEntry("Style", "InApplication"); - // TODO enum or Kconfigxt or what not? - if (menuStyle == QLatin1String("Decoration")) { - QDBusConnection::sessionBus().connect({}, {}, QStringLiteral("com.canonical.dbusmenu"), - QStringLiteral("ItemActivationRequested"), - this, SLOT(itemActivationRequested(int,uint))); - } else { - QDBusConnection::sessionBus().disconnect({}, {}, QStringLiteral("com.canonical.dbusmenu"), - QStringLiteral("ItemActivationRequested"), - this, SLOT(itemActivationRequested(int,uint))); - } - - if (menuStyle == QLatin1String("InApplication")) { - delete m_menuImporter; - m_menuImporter = nullptr; - return; - } - - // Setup a menu importer if needed - if (!m_menuImporter) { - m_menuImporter = new MenuImporter(this); - connect(m_menuImporter, &MenuImporter::WindowRegistered, this, &AppMenuModule::slotWindowRegistered); - m_menuImporter->connectToBus(); - } } #include "appmenu.moc"