diff --git a/CMakeLists.txt b/CMakeLists.txt index 155422d..4349c9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,120 +1,117 @@ cmake_minimum_required(VERSION 3.5) set(KF5_VERSION "5.70.0") # handled by release scripts set(KF5_DEP_VERSION "5.69.0") # handled by release scripts project(KNotifyConfig VERSION ${KF5_VERSION}) # Dependencies include(FeatureSummary) find_package(ECM 5.69.0 NO_MODULE) set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://commits.kde.org/extra-cmake-modules") feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) set(REQUIRED_QT_VERSION 5.12.0) # Required Qt5 components to build this framework find_package(Qt5 ${REQUIRED_QT_VERSION} NO_MODULE REQUIRED Widgets DBus) find_package(Qt5 ${REQUIRED_QT_VERSION} QUIET OPTIONAL_COMPONENTS TextToSpeech) if (NOT Qt5TextToSpeech_FOUND) message(STATUS "Qt5TextToSpeech not found, speech features will be disabled") else() add_definitions(-DHAVE_SPEECH) endif() include(KDEInstallDirs) include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(KDECMakeSettings) find_package(KF5Completion ${KF5_DEP_VERSION} REQUIRED) find_package(KF5Config ${KF5_DEP_VERSION} REQUIRED) find_package(KF5I18n ${KF5_DEP_VERSION} REQUIRED) find_package(KF5KIO ${KF5_DEP_VERSION} REQUIRED) find_package(Canberra) set_package_properties(Canberra PROPERTIES PURPOSE "Needed to preview notification sounds" TYPE OPTIONAL) -if (Canberra_FOUND) - add_definitions(-DHAVE_CANBERRA) -else() +if (NOT Canberra_FOUND) # This is REQUIRED since you cannot tell CMake "either one of those two optional ones are required" find_package(Phonon4Qt5 4.6.60 NO_MODULE REQUIRED) set_package_properties(Phonon4Qt5 PROPERTIES DESCRIPTION "Qt-based audio library" PURPOSE "Needed to preview notification sounds when Canberra isn't available") - add_definitions(-DHAVE_PHONON4QT5) endif() # Includes include(GenerateExportHeader) include(ECMSetupVersion) include(ECMGenerateHeaders) include(ECMAddQch) include(CMakePackageConfigHelpers) # ECM setup ecm_setup_version( PROJECT VARIABLE_PREFIX KNOTIFYCONFIG VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/knotifyconfig_version.h" PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5NotifyConfigConfigVersion.cmake" SOVERSION 5) option(BUILD_QCH "Build API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)" OFF) add_feature_info(QCH ${BUILD_QCH} "API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)") add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050d00) add_definitions(-DKF_DISABLE_DEPRECATED_BEFORE_AND_AT=0x054400) # Subdirectories add_definitions(-DTRANSLATION_DOMAIN=\"knotifyconfig5\") if (IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/po") ki18n_install(po) endif() #We can't activate it as it depend against phonon but it builds fine without it #add_definitions(-DQT_NO_FOREACH) add_subdirectory(src) if(BUILD_TESTING) add_subdirectory(tests) endif() # Create a Config.cmake and a ConfigVersion.cmake file and install them set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5NotifyConfig") if (BUILD_QCH) ecm_install_qch_export( TARGETS KF5NotifyConfig_QCH FILE KF5NotifyConfigQchTargets.cmake DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) set(PACKAGE_INCLUDE_QCHTARGETS "include(\"\${CMAKE_CURRENT_LIST_DIR}/KF5NotifyConfigQchTargets.cmake\")") endif() configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/KF5NotifyConfigConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/KF5NotifyConfigConfig.cmake" INSTALL_DESTINATION "${CMAKECONFIG_INSTALL_DIR}" ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KF5NotifyConfigConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/KF5NotifyConfigConfigVersion.cmake" DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) install(EXPORT KF5NotifyConfigTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KF5NotifyConfigTargets.cmake NAMESPACE KF5:: ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/knotifyconfig_version.h" DESTINATION "${KDE_INSTALL_INCLUDEDIR_KF5}" COMPONENT Devel ) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1282446..90b5748 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,85 +1,86 @@ +set(HAVE_CANBERRA ${Canberra_FOUND}) set(HAVE_PHONON ${Phonon4Qt5_FOUND}) configure_file(knotify-config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/knotify-config.h ) ########### next target ############### set(knotifyconfig_LIB_SRCS knotifyconfigactionswidget.cpp knotifyconfigelement.cpp knotifyeventlist.cpp knotifyconfigwidget.cpp ) set( knotifyconfig_UI knotifyconfigactionswidgetbase.ui ) ki18n_wrap_ui(knotifyconfig_LIB_SRCS ${knotifyconfig_UI} ) add_library(KF5NotifyConfig ${knotifyconfig_LIB_SRCS}) generate_export_header(KF5NotifyConfig BASE_NAME KNotifyConfig) add_library(KF5::NotifyConfig ALIAS KF5NotifyConfig) target_include_directories(KF5NotifyConfig INTERFACE "$") target_link_libraries(KF5NotifyConfig PUBLIC Qt5::Widgets PRIVATE KF5::I18n KF5::KIOWidgets # KUrlRequester Qt5::DBus) if(Canberra_FOUND) target_link_libraries(KF5NotifyConfig PRIVATE Canberra::Canberra) elseif (Phonon4Qt5_FOUND) target_link_libraries(KF5NotifyConfig PRIVATE Phonon::phonon4qt5) endif() set_target_properties(KF5NotifyConfig PROPERTIES VERSION ${KNOTIFYCONFIG_VERSION_STRING} SOVERSION ${KNOTIFYCONFIG_SOVERSION} EXPORT_NAME NotifyConfig ) ecm_generate_headers(KNotifyConfig_HEADERS HEADER_NAMES KNotifyConfigWidget REQUIRED_HEADERS KNotifyConfig_HEADERS ) install(TARGETS KF5NotifyConfig EXPORT KF5NotifyConfigTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) ########### install files ############### install(FILES ${CMAKE_CURRENT_BINARY_DIR}/knotifyconfig_export.h ${KNotifyConfig_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/KNotifyConfig COMPONENT Devel) if(BUILD_QCH) ecm_add_qch( KF5NotifyConfig_QCH NAME KNotifyConfig BASE_NAME KF5NotifyConfig VERSION ${KF5_VERSION} ORG_DOMAIN org.kde SOURCES # using only public headers, to cover only public API ${KNotifyConfig_HEADERS} MD_MAINPAGE "${CMAKE_SOURCE_DIR}/README.md" LINK_QCHS Qt5Widgets_QCH INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR} BLANK_MACROS KNOTIFYCONFIG_EXPORT KNOTIFYCONFIG_DEPRECATED KNOTIFYCONFIG_DEPRECATED_EXPORT TAGFILE_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} QCH_INSTALL_DESTINATION ${KDE_INSTALL_QTQCHDIR} COMPONENT Devel ) endif() include(ECMGeneratePriFile) ecm_generate_pri_file(BASE_NAME KNotifyConfig LIB_NAME KF5NotifyConfig DEPS "widgets" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF5}/KNotifyConfig) install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) diff --git a/src/knotify-config.h.cmake b/src/knotify-config.h.cmake index 7917612..e42fc49 100644 --- a/src/knotify-config.h.cmake +++ b/src/knotify-config.h.cmake @@ -1,7 +1,8 @@ #ifndef KNOTIFY_CONFIG_H #define KNOTIFY_CONFIG_H +#cmakedefine HAVE_CANBERRA #cmakedefine HAVE_PHONON #endif /* KNOTIFY_CONFIG_H */ diff --git a/src/knotifyconfigactionswidget.cpp b/src/knotifyconfigactionswidget.cpp index f6237c6..f6eaa05 100644 --- a/src/knotifyconfigactionswidget.cpp +++ b/src/knotifyconfigactionswidget.cpp @@ -1,218 +1,216 @@ /* This file is part of the KDE libraries Copyright (C) 2005-2007 Olivier Goffart 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 "knotifyconfigactionswidget.h" #include "knotifyconfigelement.h" #include #include -#include "knotify-config.h" - #if defined(HAVE_CANBERRA) #include #elif defined(HAVE_PHONON) #include #endif KNotifyConfigActionsWidget::KNotifyConfigActionsWidget(QWidget *parent) : QWidget(parent) { m_ui.setupUi(this); //Show sounds directory by default QStringList soundDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("sounds"), QStandardPaths::LocateDirectory); if (!soundDirs.isEmpty()) { m_ui.Sound_select->setStartDir(QUrl::fromLocalFile(soundDirs.last())); } m_ui.Sound_select->setMimeTypeFilters({QStringLiteral("audio/x-vorbis+ogg"), QStringLiteral("audio/x-wav")}); m_ui.Sound_play->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start"))); m_ui.Sound_check->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start"))); m_ui.Popup_check->setIcon(QIcon::fromTheme(QStringLiteral("dialog-information"))); m_ui.Logfile_check->setIcon(QIcon::fromTheme(QStringLiteral("text-x-generic"))); m_ui.Execute_check->setIcon(QIcon::fromTheme(QStringLiteral("system-run"))); m_ui.Taskbar_check->setIcon(QIcon::fromTheme(QStringLiteral("services"))); m_ui.TTS_check->setIcon(QIcon::fromTheme(QStringLiteral("text-speak"))); connect(m_ui.Execute_check, SIGNAL(toggled(bool)), this, SIGNAL(changed())); connect(m_ui.Sound_check, SIGNAL(toggled(bool)), this, SIGNAL(changed())); connect(m_ui.Popup_check, SIGNAL(toggled(bool)), this, SIGNAL(changed())); connect(m_ui.Logfile_check, SIGNAL(toggled(bool)), this, SIGNAL(changed())); connect(m_ui.Taskbar_check, SIGNAL(toggled(bool)), this, SIGNAL(changed())); connect(m_ui.TTS_check, SIGNAL(toggled(bool)), this, SLOT(slotTTSComboChanged())); connect(m_ui.Execute_select, SIGNAL(textChanged(QString)), this, SIGNAL(changed())); connect(m_ui.Sound_select, SIGNAL(textChanged(QString)), this, SIGNAL(changed())); connect(m_ui.Logfile_select, SIGNAL(textChanged(QString)), this, SIGNAL(changed())); connect(m_ui.Sound_play, SIGNAL(clicked()), this, SLOT(slotPlay())); connect(m_ui.TTS_combo, SIGNAL(currentIndexChanged(int)), this, SLOT(slotTTSComboChanged())); m_ui.TTS_combo->setEnabled(false); if (!KNotifyConfigElement::have_tts()) { m_ui.TTS_check->setVisible(false); m_ui.TTS_select->setVisible(false); m_ui.TTS_combo->setVisible(false); } } KNotifyConfigActionsWidget::~KNotifyConfigActionsWidget() { -#ifdef HAVE_CANBERRA +#if defined(HAVE_CANBERRA) if (m_context) { ca_context_destroy(m_context); } m_context = nullptr; #endif } void KNotifyConfigActionsWidget::setConfigElement(KNotifyConfigElement *config) { bool blocked = blockSignals(true); //to block the changed() signal QString prstring = config->readEntry(QStringLiteral("Action")); QStringList actions = prstring.split(QLatin1Char('|')); m_ui.Sound_check->setChecked(actions.contains(QStringLiteral("Sound"))); m_ui.Popup_check->setChecked(actions.contains(QStringLiteral("Popup"))); m_ui.Logfile_check->setChecked(actions.contains(QStringLiteral("Logfile"))); m_ui.Execute_check->setChecked(actions.contains(QStringLiteral("Execute"))); m_ui.Taskbar_check->setChecked(actions.contains(QStringLiteral("Taskbar"))); m_ui.TTS_check->setChecked(actions.contains(QStringLiteral("TTS"))); m_ui.Sound_select->setUrl(QUrl(config->readEntry(QStringLiteral("Sound"), true))); m_ui.Logfile_select->setUrl(QUrl(config->readEntry(QStringLiteral("Logfile"), true))); m_ui.Execute_select->setUrl(QUrl::fromLocalFile(config->readEntry(QStringLiteral("Execute")))); m_ui.TTS_select->setText(config->readEntry(QStringLiteral("TTS"))); if (m_ui.TTS_select->text() == QLatin1String("%e")) { m_ui.TTS_combo->setCurrentIndex(1); } else if (m_ui.TTS_select->text() == QLatin1String("%m") || m_ui.TTS_select->text() == QLatin1String("%s")) { m_ui.TTS_combo->setCurrentIndex(0); } else { m_ui.TTS_combo->setCurrentIndex(2); } blockSignals(blocked); } void KNotifyConfigActionsWidget::save(KNotifyConfigElement *config) { QStringList actions; if (m_ui.Sound_check->isChecked()) { actions << QStringLiteral("Sound"); } if (m_ui.Popup_check->isChecked()) { actions << QStringLiteral("Popup"); } if (m_ui.Logfile_check->isChecked()) { actions << QStringLiteral("Logfile"); } if (m_ui.Execute_check->isChecked()) { actions << QStringLiteral("Execute"); } if (m_ui.Taskbar_check->isChecked()) { actions << QStringLiteral("Taskbar"); } if (m_ui.TTS_check->isChecked()) { actions << QStringLiteral("TTS"); } config->writeEntry(QStringLiteral("Action"), actions.join(QLatin1Char('|'))); config->writeEntry(QStringLiteral("Sound"), m_ui.Sound_select->text()); // don't use .url() here, .notifyrc files have predefined "static" entries with no path config->writeEntry(QStringLiteral("Logfile"), m_ui.Logfile_select->url().toString()); config->writeEntry(QStringLiteral("Execute"), m_ui.Execute_select->url().toLocalFile()); switch (m_ui.TTS_combo->currentIndex()) { case 0: config->writeEntry(QStringLiteral("TTS"), QStringLiteral("%s")); break; case 1: config->writeEntry(QStringLiteral("TTS"), QStringLiteral("%e")); break; case 2: default: config->writeEntry(QStringLiteral("TTS"), m_ui.TTS_select->text()); } } void KNotifyConfigActionsWidget::slotPlay() { const QString soundFilename = m_ui.Sound_select->text(); QUrl soundURL; const auto dataLocations = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); for (const QString &dataLocation : dataLocations) { soundURL = QUrl::fromUserInput(soundFilename, dataLocation + QStringLiteral("/sounds"), QUrl::AssumeLocalFile); if (soundURL.isLocalFile() && QFile::exists(soundURL.toLocalFile())) { break; } else if (!soundURL.isLocalFile() && soundURL.isValid()) { break; } soundURL.clear(); } #if defined(HAVE_CANBERRA) if (!m_context) { int ret = ca_context_create(&m_context); if (ret != CA_SUCCESS) { qWarning() << "Failed to initialize canberra context for audio notification:" << ca_strerror(ret); m_context = nullptr; return; } QString desktopFileName = QGuiApplication::desktopFileName(); // handle apps which set the desktopFileName property with filename suffix, // due to unclear API dox (https://bugreports.qt.io/browse/QTBUG-75521) if (desktopFileName.endsWith(QLatin1String(".desktop"))) { desktopFileName.chop(8); } ret = ca_context_change_props(m_context, CA_PROP_APPLICATION_NAME, qUtf8Printable(qApp->applicationDisplayName()), CA_PROP_APPLICATION_ID, qUtf8Printable(desktopFileName), CA_PROP_APPLICATION_ICON_NAME, qUtf8Printable(qApp->windowIcon().name()), nullptr); if (ret != CA_SUCCESS) { qWarning() << "Failed to set application properties on canberra context for audio notification:" << ca_strerror(ret); } } ca_proplist *props = nullptr; ca_proplist_create(&props); // We'll also want this cached for a time. volatile makes sure the cache is // dropped after some time or when the cache is under pressure. ca_proplist_sets(props, CA_PROP_MEDIA_FILENAME, QFile::encodeName(soundURL.toLocalFile()).constData()); ca_proplist_sets(props, CA_PROP_CANBERRA_CACHE_CONTROL, "volatile"); int ret = ca_context_play_full(m_context, 0, props, nullptr, nullptr); ca_proplist_destroy(props); if (ret != CA_SUCCESS) { qWarning() << "Failed to play sound with canberra:" << ca_strerror(ret); return; } #elif defined(HAVE_PHONON) Phonon::MediaObject *media = Phonon::createPlayer(Phonon::NotificationCategory, soundURL); media->play(); connect(media, SIGNAL(finished()), media, SLOT(deleteLater())); #endif } void KNotifyConfigActionsWidget::slotTTSComboChanged() { m_ui.TTS_select->setEnabled(m_ui.TTS_check->isChecked() && m_ui.TTS_combo->currentIndex() == 2); emit changed(); } diff --git a/src/knotifyconfigactionswidget.h b/src/knotifyconfigactionswidget.h index 91ef7f2..0cacfdf 100644 --- a/src/knotifyconfigactionswidget.h +++ b/src/knotifyconfigactionswidget.h @@ -1,58 +1,59 @@ /* This file is part of the KDE project Copyright (C) 2005-2007 by Olivier Goffart 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 KNOTIFYCONFIGACTIONSWIDGET_H #define KNOTIFYCONFIGACTIONSWIDGET_H #include #include "ui_knotifyconfigactionswidgetbase.h" +#include "knotify-config.h" #ifdef HAVE_CANBERRA struct ca_context; #endif class KNotifyConfigElement; /** * Represent the config for an event * @internal * @author Olivier Goffart */ class KNotifyConfigActionsWidget : public QWidget { Q_OBJECT public: explicit KNotifyConfigActionsWidget(QWidget *parent); ~KNotifyConfigActionsWidget() override; void setConfigElement(KNotifyConfigElement *config); void save(KNotifyConfigElement *config); Q_SIGNALS: void changed(); private Q_SLOTS: void slotPlay(); void slotTTSComboChanged(); private: Ui::KNotifyConfigActionsWidgetBase m_ui; #ifdef HAVE_CANBERRA ca_context *m_context = nullptr; #endif }; #endif // KNOTIFYCONFIGACTIONSWIDGET_H