diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt index 882f2cd..ceec389 100644 --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -1,83 +1,85 @@ include(ECMMarkAsTest) include(ECMMarkNonGuiExecutable) find_package(Qt5Test ${QT_MIN_VERSION} CONFIG QUIET) find_package(Qt5Qml ${QT_MIN_VERSION} CONFIG QUIET) if(NOT Qt5Test_FOUND) message(STATUS "Qt5Test not found, autotests will not be built.") return() endif() if(NOT Qt5Qml_FOUND) message(STATUS "Qt5Qml not found, QML autotests will not be built.") endif() set(CONFIGFILE "${CMAKE_CURRENT_SOURCE_DIR}/kdeplatformtheme_kdeglobals") set(CHANGED_CONFIGFILE "${CMAKE_CURRENT_SOURCE_DIR}/kdeplatformtheme_changed_kdeglobals") configure_file(kdeplatformtheme_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/kdeplatformtheme_config.h) remove_definitions(-DQT_NO_CAST_FROM_ASCII) # qdbusmenubar uses them remove_definitions(-DQT_NO_SIGNALS_SLOTS_KEYWORDS) macro(FRAMEWORKINTEGRATION_TESTS _testname) add_executable(${_testname} ${_testname}.cpp ${ARGN}) set_target_properties(${_testname} PROPERTIES COMPILE_FLAGS "-DUNIT_TEST") add_test(NAME frameworkintegration-${_testname} COMMAND ${_testname}) ecm_mark_as_test(${_testname}) ecm_mark_nongui_executable(${_testname}) target_include_directories(${_testname} PRIVATE ${CMAKE_BINARY_DIR}/src/platformtheme) target_link_libraries(${_testname} Qt5::GuiPrivate Qt5::Test Qt5::DBus Qt5::X11Extras Qt5::QuickControls2 ${QT5PLATFORMSUPPORT_LIBS} KF5::ConfigWidgets KF5::ConfigCore KF5::IconThemes KF5::KIOFileWidgets KF5::I18n KF5::Notifications KF5::WindowSystem KF5::WaylandClient XCB::XCB) endmacro() set(platformThemeSRCS ../src/platformtheme/qdbusmenubar.cpp # fork of Qt's qdbusmenubar with some added setters for our convenience ../src/platformtheme/kdeplatformtheme.cpp ../src/platformtheme/kfontsettingsdata.cpp ../src/platformtheme/khintssettings.cpp ../src/platformtheme/kdeplatformfiledialoghelper.cpp ../src/platformtheme/kdeplatformfiledialogbase.cpp ../src/platformtheme/kdeplatformsystemtrayicon.cpp ../src/platformtheme/kdirselectdialog.cpp ../src/platformtheme/kfiletreeview.cpp ../src/platformtheme/kwaylandintegration.cpp ../src/platformtheme/x11integration.cpp ) +qt5_add_dbus_interface(platformThemeSRCS ../src/platformtheme/org.kde.StatusNotifierWatcher.xml statusnotifierwatcher_interface) + frameworkintegration_tests( kdeplatformtheme_unittest ${platformThemeSRCS} ) frameworkintegration_tests( kfontsettingsdata_unittest ../src/platformtheme/kfontsettingsdata.cpp ) frameworkintegration_tests( kfiledialog_unittest ) frameworkintegration_tests( ksni_unittest ) frameworkintegration_tests( kdirselectdialog_unittest ../src/platformtheme/kdeplatformfiledialogbase.cpp ../src/platformtheme/kdirselectdialog.cpp ../src/platformtheme/kfiletreeview.cpp ) frameworkintegration_tests( khintssettings_unittest ../src/platformtheme/khintssettings.cpp ) if(Qt5Qml_FOUND) add_test(NAME qmltests COMMAND qmltestrunner WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) frameworkintegration_tests(kfiledialogqml_unittest) target_link_libraries(kfiledialogqml_unittest Qt5::Qml) endif() diff --git a/src/platformtheme/CMakeLists.txt b/src/platformtheme/CMakeLists.txt index 0293b0a..12854c0 100644 --- a/src/platformtheme/CMakeLists.txt +++ b/src/platformtheme/CMakeLists.txt @@ -1,66 +1,68 @@ find_package(X11) set_package_properties(X11 PROPERTIES DESCRIPTION "Required for updating the Cursor theme on X11" URL "http://www.x.org" TYPE REQUIRED ) set(HAVE_X11 ${X11_FOUND}) if(HAVE_X11) find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED X11Extras) find_package(XCB COMPONENTS XCB) set_package_properties(XCB PROPERTIES TYPE REQUIRED) endif() configure_file(config-platformtheme.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-platformtheme.h ) # qdbusmenubar uses them remove_definitions(-DQT_NO_SIGNALS_SLOTS_KEYWORDS) set(platformtheme_SRCS qdbusmenubar.cpp # fork of Qt's qdbusmenubar with some added setters for our convenience kdeplatformtheme.cpp kfontsettingsdata.cpp khintssettings.cpp kdeplatformfiledialoghelper.cpp kdeplatformfiledialogbase.cpp kdeplatformsystemtrayicon.cpp kfiletreeview.cpp kdirselectdialog.cpp kwaylandintegration.cpp x11integration.cpp main.cpp ) +qt5_add_dbus_interface(platformtheme_SRCS org.kde.StatusNotifierWatcher.xml statusnotifierwatcher_interface) + add_library(KDEPlasmaPlatformTheme MODULE ${platformtheme_SRCS}) target_link_libraries(KDEPlasmaPlatformTheme PRIVATE Qt5::GuiPrivate Qt5::DBus Qt5::X11Extras Qt5::QuickControls2 KF5::ConfigWidgets KF5::ConfigCore KF5::IconThemes KF5::KIOFileWidgets # KFileFilterCombo, KDirSortFilterProxyModel, KRecentDirs KF5::KIOWidgets KF5::XmlGui KF5::I18n KF5::Notifications KF5::WindowSystem KF5::WaylandClient XCB::XCB ${QT5PLATFORMSUPPORT_LIBS} ) if(HAVE_X11) target_link_libraries(KDEPlasmaPlatformTheme PRIVATE Qt5::X11Extras ${X11_Xcursor_LIB} ${XCB_XCB_LIBRARY}) endif() set_target_properties(KDEPlasmaPlatformTheme PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/platformthemes/") install(TARGETS KDEPlasmaPlatformTheme DESTINATION ${KDE_INSTALL_QTPLUGINDIR}/platformthemes) install(FILES fonts_global_toolbar.upd fonts_global.upd fonts_akregator.upd fonts_kate.upd DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR}) install(PROGRAMS fonts_global.pl fonts_akregator.pl fonts_kate.pl DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR}) diff --git a/src/platformtheme/kdeplatformsystemtrayicon.cpp b/src/platformtheme/kdeplatformsystemtrayicon.cpp index ea2efe9..b5ee54a 100644 --- a/src/platformtheme/kdeplatformsystemtrayicon.cpp +++ b/src/platformtheme/kdeplatformsystemtrayicon.cpp @@ -1,375 +1,379 @@ /* This file is part of the KDE libraries * Copyright 2014 Martin Gräßlin * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2 of the License or ( at * your option ) version 3 or, at the discretion of KDE e.V. ( which shall * act as a proxy as in section 14 of the GPLv3 ), 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 Lesser 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 "kdeplatformsystemtrayicon.h" #include #include #include #include #include #include #include +#include "statusnotifierwatcher_interface.h" + SystemTrayMenu::SystemTrayMenu() : QPlatformMenu() , m_tag(0) , m_menu(new QMenu()) { connect(m_menu.data(), &QMenu::aboutToShow, this, &QPlatformMenu::aboutToShow); connect(m_menu.data(), &QMenu::aboutToHide, this, &QPlatformMenu::aboutToHide); } SystemTrayMenu::~SystemTrayMenu() { if (m_menu) { m_menu->deleteLater(); } } QPlatformMenuItem *SystemTrayMenu::createMenuItem() const { return new SystemTrayMenuItem(); } QPlatformMenu *SystemTrayMenu::createSubMenu() const { return new SystemTrayMenu(); } void SystemTrayMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) { if (SystemTrayMenuItem *ours = qobject_cast(menuItem)) { bool inserted = false; if (SystemTrayMenuItem *oursBefore = qobject_cast(before)) { for (auto it = m_items.begin(); it != m_items.end(); ++it) { if (*it == oursBefore) { m_items.insert(it, ours); if (m_menu) { m_menu->insertAction(oursBefore->action(), ours->action()); } inserted = true; break; } } } if (!inserted) { m_items.append(ours); if (m_menu) { m_menu->addAction(ours->action()); } } } } QPlatformMenuItem *SystemTrayMenu::menuItemAt(int position) const { if (position < m_items.size()) { return m_items.at(position); } return nullptr; } QPlatformMenuItem *SystemTrayMenu::menuItemForTag(quintptr tag) const { auto it = std::find_if(m_items.constBegin(), m_items.constEnd(), [tag](SystemTrayMenuItem *item) { return item->tag() == tag; }); if (it != m_items.constEnd()) { return *it; } return nullptr; } void SystemTrayMenu::removeMenuItem(QPlatformMenuItem *menuItem) { if (SystemTrayMenuItem *ours = qobject_cast(menuItem)) { m_items.removeOne(ours); if (ours->action() && m_menu) { m_menu->removeAction(ours->action()); } } } void SystemTrayMenu::setEnabled(bool enabled) { if (!m_menu) { return; } m_menu->setEnabled(enabled); } void SystemTrayMenu::setIcon(const QIcon &icon) { if (!m_menu) { return; } m_menu->setIcon(icon); } void SystemTrayMenu::setTag(quintptr tag) { m_tag = tag; } void SystemTrayMenu::setText(const QString &text) { if (!m_menu) { return; } m_menu->setTitle(text); } void SystemTrayMenu::setVisible(bool visible) { if (!m_menu) { return; } m_menu->setVisible(visible); } void SystemTrayMenu::syncMenuItem(QPlatformMenuItem *menuItem) { Q_UNUSED(menuItem) // nothing to do } void SystemTrayMenu::syncSeparatorsCollapsible(bool enable) { if (!m_menu) { return; } m_menu->setSeparatorsCollapsible(enable); } quintptr SystemTrayMenu::tag() const { return m_tag; } QMenu *SystemTrayMenu::menu() const { return m_menu.data(); } SystemTrayMenuItem::SystemTrayMenuItem() : QPlatformMenuItem() , m_tag(0) , m_action(new QAction(this)) { connect(m_action, &QAction::triggered, this, &QPlatformMenuItem::activated); connect(m_action, &QAction::hovered, this, &QPlatformMenuItem::hovered); } SystemTrayMenuItem::~SystemTrayMenuItem() { } void SystemTrayMenuItem::setCheckable(bool checkable) { m_action->setCheckable(checkable); } void SystemTrayMenuItem::setChecked(bool isChecked) { m_action->setChecked(isChecked); } void SystemTrayMenuItem::setEnabled(bool enabled) { m_action->setEnabled(enabled); } void SystemTrayMenuItem::setFont(const QFont &font) { m_action->setFont(font); } void SystemTrayMenuItem::setIcon(const QIcon &icon) { m_action->setIcon(icon); } void SystemTrayMenuItem::setIsSeparator(bool isSeparator) { m_action->setSeparator(isSeparator); } void SystemTrayMenuItem::setMenu(QPlatformMenu *menu) { if (SystemTrayMenu *ourMenu = qobject_cast(menu)) { m_action->setMenu(ourMenu->menu()); } } void SystemTrayMenuItem::setRole(QPlatformMenuItem::MenuRole role) { Q_UNUSED(role) } void SystemTrayMenuItem::setShortcut(const QKeySequence &shortcut) { m_action->setShortcut(shortcut); } void SystemTrayMenuItem::setTag(quintptr tag) { m_tag = tag; } void SystemTrayMenuItem::setText(const QString &text) { m_action->setText(text); } void SystemTrayMenuItem::setVisible(bool isVisible) { m_action->setVisible(isVisible); } void SystemTrayMenuItem::setIconSize(int size) { Q_UNUSED(size); } void SystemTrayMenuItem::setHasExclusiveGroup(bool hasExclusiveGroup) { if (hasExclusiveGroup) { if (!m_action->actionGroup()) { m_action->setActionGroup(new QActionGroup(m_action)); } } else { QActionGroup *actionGroup = m_action->actionGroup(); if (actionGroup) { m_action->setActionGroup(nullptr); delete actionGroup; } } } quintptr SystemTrayMenuItem::tag() const { return m_tag; } QAction *SystemTrayMenuItem::action() const { return m_action; } KDEPlatformSystemTrayIcon::KDEPlatformSystemTrayIcon() : QPlatformSystemTrayIcon() , m_sni(nullptr) { } KDEPlatformSystemTrayIcon::~KDEPlatformSystemTrayIcon() { } void KDEPlatformSystemTrayIcon::init() { if (!m_sni) { m_sni = new KStatusNotifierItem(); m_sni->setStandardActionsEnabled(false); m_sni->setTitle(QApplication::applicationDisplayName()); connect(m_sni, &KStatusNotifierItem::activateRequested, [this](bool active, const QPoint &pos) { Q_UNUSED(active) Q_UNUSED(pos) emit activated(QPlatformSystemTrayIcon::Trigger); }); connect(m_sni, &KStatusNotifierItem::secondaryActivateRequested, [this](const QPoint &pos) { Q_UNUSED(pos) emit activated(QPlatformSystemTrayIcon::MiddleClick); }); } } void KDEPlatformSystemTrayIcon::cleanup() { delete m_sni; m_sni = nullptr; } void KDEPlatformSystemTrayIcon::updateIcon(const QIcon &icon) { if (!m_sni) { return; } if (icon.name().isEmpty()) { m_sni->setIconByPixmap(icon); m_sni->setToolTipIconByPixmap(icon); } else { m_sni->setIconByName(icon.name()); m_sni->setToolTipIconByName(icon.name()); } } void KDEPlatformSystemTrayIcon::updateToolTip(const QString &tooltip) { if (!m_sni) { return; } m_sni->setToolTipTitle(tooltip); } void KDEPlatformSystemTrayIcon::updateMenu(QPlatformMenu *menu) { if (!m_sni) { return; } if (SystemTrayMenu *ourMenu = qobject_cast(menu)) { m_sni->setContextMenu(ourMenu->menu()); } } QPlatformMenu *KDEPlatformSystemTrayIcon::createMenu() const { return new SystemTrayMenu(); } QRect KDEPlatformSystemTrayIcon::geometry() const { // StatusNotifierItem doesn't provide the geometry return QRect(); } void KDEPlatformSystemTrayIcon::showMessage(const QString &title, const QString &msg, const QIcon &icon, MessageIcon iconType, int secs) { Q_UNUSED(iconType) if (!m_sni) { return; } m_sni->showMessage(title, msg, icon.name(), secs); } bool KDEPlatformSystemTrayIcon::isSystemTrayAvailable() const { - QDBusInterface systrayHost(QStringLiteral("org.kde.StatusNotifierWatcher"), QStringLiteral("/StatusNotifierWatcher"), QStringLiteral("org.kde.StatusNotifierWatcher")); + org::kde::StatusNotifierWatcher systrayHost(QStringLiteral("org.kde.StatusNotifierWatcher"), + QStringLiteral("/StatusNotifierWatcher"), + QDBusConnection::sessionBus()); if (systrayHost.isValid()) { - return systrayHost.property("IsStatusNotifierHostRegistered").toBool(); + return systrayHost.isStatusNotifierHostRegistered(); } return false; } bool KDEPlatformSystemTrayIcon::supportsMessages() const { return true; }