feat: add missing KF6 framework recipes
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
set(HAVE_CANBERRA ${Canberra_FOUND})
|
||||
set(HAVE_QTMULTIMEDIA ${Qt6Multimedia_FOUND})
|
||||
configure_file(knotify-config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/knotify-config.h )
|
||||
|
||||
add_library(KF6NotifyConfig)
|
||||
add_library(KF6::NotifyConfig ALIAS KF6NotifyConfig)
|
||||
|
||||
set_target_properties(KF6NotifyConfig PROPERTIES
|
||||
VERSION ${KNOTIFYCONFIG_VERSION}
|
||||
SOVERSION ${KNOTIFYCONFIG_SOVERSION}
|
||||
EXPORT_NAME NotifyConfig
|
||||
)
|
||||
|
||||
target_sources(KF6NotifyConfig PRIVATE
|
||||
knotifyconfigactionswidget.cpp
|
||||
knotifyconfigelement.cpp
|
||||
knotifyeventlist.cpp
|
||||
knotifyconfigwidget.cpp
|
||||
)
|
||||
|
||||
ki18n_wrap_ui(KF6NotifyConfig knotifyconfigactionswidgetbase.ui)
|
||||
|
||||
ecm_qt_declare_logging_category(KF6NotifyConfig
|
||||
HEADER knotifyconfig_debug.h
|
||||
IDENTIFIER KNOTIFYCONFIG_LOG
|
||||
CATEGORY_NAME kf.notifyconfig
|
||||
DESCRIPTION "KNotifyConfig"
|
||||
EXPORT KNOTIFYCONFIG
|
||||
)
|
||||
|
||||
ecm_generate_export_header(KF6NotifyConfig
|
||||
BASE_NAME KNotifyConfig
|
||||
GROUP_BASE_NAME KF
|
||||
VERSION ${KF_VERSION}
|
||||
USE_VERSION_HEADER
|
||||
DEPRECATED_BASE_VERSION 0
|
||||
)
|
||||
|
||||
target_include_directories(KF6NotifyConfig INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR_KF}/KNotifyConfig>")
|
||||
|
||||
target_link_libraries(KF6NotifyConfig
|
||||
PUBLIC
|
||||
Qt6::Widgets
|
||||
PRIVATE
|
||||
KF6::I18n
|
||||
KF6::KIOWidgets # KUrlRequester
|
||||
)
|
||||
|
||||
if (HAVE_DBUS)
|
||||
target_link_libraries(KF6NotifyConfig PRIVATE Qt6::DBus)
|
||||
endif()
|
||||
|
||||
if(Canberra_FOUND)
|
||||
target_link_libraries(KF6NotifyConfig PRIVATE Canberra::Canberra)
|
||||
elseif (Qt6Multimedia_FOUND)
|
||||
target_link_libraries(KF6NotifyConfig PRIVATE Qt6::Multimedia)
|
||||
endif()
|
||||
|
||||
ecm_generate_headers(KNotifyConfig_HEADERS
|
||||
HEADER_NAMES
|
||||
KNotifyConfigWidget
|
||||
|
||||
REQUIRED_HEADERS KNotifyConfig_HEADERS
|
||||
)
|
||||
|
||||
install(TARGETS KF6NotifyConfig EXPORT KF6NotifyConfigTargets ${KF_INSTALL_TARGETS_DEFAULT_ARGS})
|
||||
|
||||
########### install files ###############
|
||||
install(FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/knotifyconfig_export.h
|
||||
${KNotifyConfig_HEADERS}
|
||||
DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF}/KNotifyConfig COMPONENT Devel)
|
||||
|
||||
if(BUILD_QCH)
|
||||
ecm_add_qch(
|
||||
KF6NotifyConfig_QCH
|
||||
NAME KNotifyConfig
|
||||
BASE_NAME KF6NotifyConfig
|
||||
VERSION ${KF_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
|
||||
Qt6Widgets_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()
|
||||
|
||||
ecm_qt_install_logging_categories(
|
||||
EXPORT KNOTIFYCONFIG
|
||||
FILE knotifyconfig.categories
|
||||
DESTINATION "${KDE_INSTALL_LOGGINGCATEGORIESDIR}"
|
||||
)
|
||||
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Invoke the extractrc script on all .ui, .rc, and .kcfg files in the sources.
|
||||
# The results are stored in a pseudo .cpp file to be picked up by xgettext.
|
||||
lst=`find . -name \*.rc -o -name \*.ui -o -name \*.kcfg`
|
||||
if [ -n "$lst" ] ; then
|
||||
$EXTRACTRC $lst >> rc.cpp
|
||||
fi
|
||||
|
||||
# Extract strings from all source files.
|
||||
# If your framework depends on KI18n, use $XGETTEXT. If it uses Qt translation
|
||||
# system, use $EXTRACT_TR_STRINGS.
|
||||
$XGETTEXT `find . -name \*.cpp -o -name \*.h -o -name \*.qml` -o $podir/knotifyconfig6.pot
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef KNOTIFY_CONFIG_H
|
||||
#define KNOTIFY_CONFIG_H
|
||||
|
||||
#cmakedefine01 HAVE_CANBERRA
|
||||
#cmakedefine01 HAVE_QTMULTIMEDIA
|
||||
|
||||
#endif /* KNOTIFY_CONFIG_H */
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
This file is part of the KDE libraries
|
||||
SPDX-FileCopyrightText: 2005-2007 Olivier Goffart <ogoffart at kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-only
|
||||
*/
|
||||
|
||||
#include "knotifyconfigactionswidget.h"
|
||||
|
||||
#include "knotifyconfigelement.h"
|
||||
#include <knotifyconfig_debug.h>
|
||||
|
||||
#include <QFile>
|
||||
#include <QStandardPaths>
|
||||
#include <QUrl>
|
||||
|
||||
#if HAVE_CANBERRA
|
||||
#include <canberra.h>
|
||||
#elif HAVE_QTMULTIMEDIA
|
||||
#include <QAudioOutput>
|
||||
#include <QMediaPlayer>
|
||||
#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")));
|
||||
|
||||
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.Sound_select, SIGNAL(textChanged(QString)), this, SIGNAL(changed()));
|
||||
connect(m_ui.Sound_play, SIGNAL(clicked()), this, SLOT(slotPlay()));
|
||||
}
|
||||
|
||||
KNotifyConfigActionsWidget::~KNotifyConfigActionsWidget()
|
||||
{
|
||||
#if 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.Sound_select->setUrl(QUrl(config->readEntry(QStringLiteral("Sound"), true)));
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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 HAVE_CANBERRA
|
||||
if (!m_context) {
|
||||
int ret = ca_context_create(&m_context);
|
||||
if (ret != CA_SUCCESS) {
|
||||
qCWarning(KNOTIFYCONFIG_LOG) << "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) {
|
||||
qCWarning(KNOTIFYCONFIG_LOG) << "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) {
|
||||
qCWarning(KNOTIFYCONFIG_LOG) << "Failed to play sound with canberra:" << ca_strerror(ret);
|
||||
return;
|
||||
}
|
||||
#elif HAVE_QTMULTIMEDIA
|
||||
auto player = new QMediaPlayer(this);
|
||||
auto audioOutput = new QAudioOutput(player);
|
||||
connect(player, &QMediaPlayer::playingChanged, player, [player](bool playing) {
|
||||
if (!playing) {
|
||||
player->deleteLater();
|
||||
}
|
||||
});
|
||||
connect(player, &QMediaPlayer::errorOccurred, player, [player]() {
|
||||
player->deleteLater();
|
||||
});
|
||||
player->setAudioOutput(audioOutput);
|
||||
player->setSource(soundURL);
|
||||
player->play();
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "moc_knotifyconfigactionswidget.cpp"
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 2005-2007 Olivier Goffart <ogoffart at kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-only
|
||||
*/
|
||||
|
||||
#ifndef KNOTIFYCONFIGACTIONSWIDGET_H
|
||||
#define KNOTIFYCONFIGACTIONSWIDGET_H
|
||||
|
||||
#include "knotify-config.h"
|
||||
#include "ui_knotifyconfigactionswidgetbase.h"
|
||||
#include <QWidget>
|
||||
|
||||
#if HAVE_CANBERRA
|
||||
struct ca_context;
|
||||
#endif
|
||||
|
||||
class KNotifyConfigElement;
|
||||
|
||||
/**
|
||||
* Represent the config for an event
|
||||
* @internal
|
||||
* @author Olivier Goffart <ogoffart @ kde.org>
|
||||
*/
|
||||
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();
|
||||
|
||||
private:
|
||||
Ui::KNotifyConfigActionsWidgetBase m_ui;
|
||||
#if HAVE_CANBERRA
|
||||
ca_context *m_context = nullptr;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // KNOTIFYCONFIGACTIONSWIDGET_H
|
||||
@@ -0,0 +1,111 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>KNotifyConfigActionsWidgetBase</class>
|
||||
<widget class="QWidget" name="KNotifyConfigActionsWidgetBase">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>433</width>
|
||||
<height>202</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<widget class="QToolButton" name="Sound_play">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="2">
|
||||
<widget class="KUrlRequester" name="Sound_select">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Select the sound to play</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="Sound_check">
|
||||
<property name="text">
|
||||
<string>Play a &sound</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="4">
|
||||
<widget class="QCheckBox" name="Popup_check">
|
||||
<property name="text">
|
||||
<string>Show a message in a &popup</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>KUrlRequester</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>kurlrequester.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>Sound_check</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>Sound_play</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>59</x>
|
||||
<y>23</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>118</x>
|
||||
<y>20</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>Sound_check</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>Sound_select</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>18</x>
|
||||
<y>16</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>254</x>
|
||||
<y>8</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 2005-2006 Olivier Goffart <ogoffart at kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-only
|
||||
*/
|
||||
|
||||
#include "knotifyconfigelement.h"
|
||||
|
||||
#include <KConfig>
|
||||
#include <KConfigGroup>
|
||||
|
||||
KNotifyConfigElement::KNotifyConfigElement(const QString &eventid, KConfig *config)
|
||||
: m_config(new KConfigGroup(config, QStringLiteral("Event/") + eventid))
|
||||
, m_eventId(eventid)
|
||||
{
|
||||
}
|
||||
|
||||
KNotifyConfigElement::~KNotifyConfigElement()
|
||||
{
|
||||
delete m_config;
|
||||
}
|
||||
|
||||
QString KNotifyConfigElement::readEntry(const QString &entry, bool path)
|
||||
{
|
||||
if (m_cache.contains(entry)) {
|
||||
return m_cache[entry];
|
||||
}
|
||||
return path ? m_config->readPathEntry(entry, QString()) : m_config->readEntry(entry, QString());
|
||||
}
|
||||
|
||||
void KNotifyConfigElement::writeEntry(const QString &entry, const QString &data)
|
||||
{
|
||||
m_cache[entry] = data;
|
||||
}
|
||||
|
||||
QString KNotifyConfigElement::eventId() const
|
||||
{
|
||||
return m_eventId;
|
||||
}
|
||||
|
||||
void KNotifyConfigElement::save()
|
||||
{
|
||||
QMap<QString, QString>::const_iterator it = m_cache.constBegin();
|
||||
for (; it != m_cache.constEnd(); ++it) {
|
||||
m_config->writeEntry(it.key(), it.value());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
This file is part of the KDE project
|
||||
SPDX-FileCopyrightText: 2005-2006 Olivier Goffart <ogoffart at kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-only
|
||||
*/
|
||||
|
||||
#ifndef KNOTIFYCONFIGELEMENT_H
|
||||
#define KNOTIFYCONFIGELEMENT_H
|
||||
|
||||
#include <QMap>
|
||||
#include <QString>
|
||||
|
||||
class KConfig;
|
||||
class KConfigGroup;
|
||||
|
||||
/**
|
||||
* Represent the config for an event
|
||||
@author Olivier Goffart <ogoffart@kde.org>
|
||||
*/
|
||||
class KNotifyConfigElement
|
||||
{
|
||||
public:
|
||||
KNotifyConfigElement(const QString &eventid, KConfig *config);
|
||||
~KNotifyConfigElement();
|
||||
|
||||
KNotifyConfigElement(const KNotifyConfigElement &) = delete;
|
||||
KNotifyConfigElement &operator=(const KNotifyConfigElement &) = delete;
|
||||
|
||||
QString readEntry(const QString &entry, bool path = false);
|
||||
void writeEntry(const QString &entry, const QString &data);
|
||||
|
||||
QString eventId() const;
|
||||
|
||||
void save();
|
||||
|
||||
private:
|
||||
QMap<QString, QString> m_cache;
|
||||
KConfigGroup *m_config;
|
||||
QString m_eventId;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
This file is part of the KDE libraries
|
||||
SPDX-FileCopyrightText: 2005 Olivier Goffart <ogoffart at kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-only
|
||||
*/
|
||||
|
||||
#include "knotifyconfigwidget.h"
|
||||
#include "knotifyconfigactionswidget.h"
|
||||
#include "knotifyconfigelement.h"
|
||||
#include "knotifyeventlist.h"
|
||||
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
#include <QDBusConnectionInterface>
|
||||
#endif
|
||||
|
||||
#include <KLocalizedString>
|
||||
|
||||
class KNotifyConfigWidgetPrivate
|
||||
{
|
||||
public:
|
||||
KNotifyEventList *eventList;
|
||||
KNotifyConfigActionsWidget *actionsconfig;
|
||||
KNotifyConfigElement *currentElement;
|
||||
QString application;
|
||||
};
|
||||
|
||||
KNotifyConfigWidget::KNotifyConfigWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, d(new KNotifyConfigWidgetPrivate)
|
||||
{
|
||||
d->currentElement = nullptr;
|
||||
d->eventList = new KNotifyEventList(this);
|
||||
d->eventList->setFocus();
|
||||
d->actionsconfig = new KNotifyConfigActionsWidget(this);
|
||||
d->actionsconfig->setEnabled(false);
|
||||
connect(d->eventList, SIGNAL(eventSelected(KNotifyConfigElement *)), this, SLOT(slotEventSelected(KNotifyConfigElement *)));
|
||||
connect(d->actionsconfig, SIGNAL(changed()), this, SLOT(slotActionChanged()));
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addWidget(d->eventList, 1);
|
||||
layout->addWidget(d->actionsconfig);
|
||||
}
|
||||
|
||||
KNotifyConfigWidget::~KNotifyConfigWidget() = default;
|
||||
|
||||
void KNotifyConfigWidget::setApplication(const QString &app)
|
||||
{
|
||||
d->currentElement = nullptr;
|
||||
d->application = app.isEmpty() ? QCoreApplication::instance()->applicationName() : app;
|
||||
d->eventList->fill(d->application);
|
||||
}
|
||||
|
||||
void KNotifyConfigWidget::selectEvent(const QString &eventId)
|
||||
{
|
||||
d->eventList->selectEvent(eventId);
|
||||
}
|
||||
|
||||
void KNotifyConfigWidget::slotEventSelected(KNotifyConfigElement *e)
|
||||
{
|
||||
if (d->currentElement) {
|
||||
d->actionsconfig->save(d->currentElement);
|
||||
}
|
||||
d->currentElement = e;
|
||||
if (e) {
|
||||
d->actionsconfig->setConfigElement(e);
|
||||
d->actionsconfig->setEnabled(true);
|
||||
} else {
|
||||
d->actionsconfig->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void KNotifyConfigWidget::save()
|
||||
{
|
||||
if (d->currentElement) {
|
||||
d->actionsconfig->save(d->currentElement);
|
||||
}
|
||||
|
||||
d->eventList->save();
|
||||
Q_EMIT changed(false);
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
// ask KNotification objects to reload their config
|
||||
QDBusMessage message =
|
||||
QDBusMessage::createSignal(QStringLiteral("/Config"), QStringLiteral("org.kde.knotification"), QStringLiteral("reparseConfiguration"));
|
||||
message.setArguments(QVariantList() << d->application);
|
||||
QDBusConnection::sessionBus().send(message);
|
||||
#endif
|
||||
}
|
||||
|
||||
void KNotifyConfigWidget::revertToDefaults()
|
||||
{
|
||||
d->eventList->fill(d->application, true);
|
||||
Q_EMIT changed(true);
|
||||
}
|
||||
|
||||
void KNotifyConfigWidget::disableAllSounds()
|
||||
{
|
||||
if (d->eventList->disableAllSounds()) {
|
||||
if (d->currentElement) {
|
||||
d->actionsconfig->setConfigElement(d->currentElement);
|
||||
}
|
||||
d->eventList->updateAllItems();
|
||||
Q_EMIT changed(true);
|
||||
}
|
||||
}
|
||||
|
||||
KNotifyConfigWidget *KNotifyConfigWidget::configure(QWidget *parent, const QString &appname)
|
||||
{
|
||||
QDialog *dialog = new QDialog(parent);
|
||||
dialog->setWindowTitle(i18n("Configure Notifications"));
|
||||
|
||||
KNotifyConfigWidget *w = new KNotifyConfigWidget(dialog);
|
||||
|
||||
QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog);
|
||||
buttonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Apply | QDialogButtonBox::Cancel);
|
||||
buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(dialog);
|
||||
layout->addWidget(w);
|
||||
layout->addWidget(buttonBox);
|
||||
|
||||
connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), w, SLOT(save()));
|
||||
connect(buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), w, SLOT(save()));
|
||||
connect(w, SIGNAL(changed(bool)), buttonBox->button(QDialogButtonBox::Apply), SLOT(setEnabled(bool)));
|
||||
|
||||
connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept()));
|
||||
connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject()));
|
||||
|
||||
w->setApplication(appname);
|
||||
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
dialog->show();
|
||||
return w;
|
||||
}
|
||||
|
||||
void KNotifyConfigWidget::slotActionChanged()
|
||||
{
|
||||
Q_EMIT changed(true); // TODO
|
||||
if (d->currentElement) {
|
||||
d->actionsconfig->save(d->currentElement);
|
||||
d->eventList->updateCurrentItem();
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_knotifyconfigwidget.cpp"
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
This file is part of the KDE libraries
|
||||
SPDX-FileCopyrightText: 2005 Olivier Goffart <ogoffart at kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-only
|
||||
*/
|
||||
|
||||
#ifndef KNOTIFYCONFIGWIDGET_H
|
||||
#define KNOTIFYCONFIGWIDGET_H
|
||||
|
||||
#include <QString>
|
||||
#include <QWidget>
|
||||
#include <knotifyconfig_export.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class KNotifyConfigElement;
|
||||
class KNotifyConfigWidgetPrivate;
|
||||
/**
|
||||
* @class KNotifyConfigWidget knotifyconfigwidget.h <KNotifyConfigWidget>
|
||||
*
|
||||
* Configure the notification for a given application
|
||||
*
|
||||
* You probably will want to use the static function configure
|
||||
*
|
||||
* If you create the widget yourself, you must call setApplication before showing it
|
||||
*
|
||||
* @author Olivier Goffart <ogoffart @ kde.org>
|
||||
*/
|
||||
class KNOTIFYCONFIG_EXPORT KNotifyConfigWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit KNotifyConfigWidget(QWidget *parent);
|
||||
~KNotifyConfigWidget() override;
|
||||
|
||||
/**
|
||||
* Show a dialog with the widget.
|
||||
* @param parent the parent widget of the dialog
|
||||
* @param appname the application name, if null, it is autodetected
|
||||
* @return the widget itself the topLevelWidget of it is probably a KDialog
|
||||
*/
|
||||
static KNotifyConfigWidget *configure(QWidget *parent = nullptr, const QString &appname = QString());
|
||||
|
||||
/**
|
||||
* Change the application
|
||||
*
|
||||
* @param appname name of the application. if null QCoreApplication::instance()->applicationName() is used
|
||||
*/
|
||||
void setApplication(const QString &appname = QString());
|
||||
|
||||
/**
|
||||
* Select a given notification in the current list
|
||||
*
|
||||
* @param id The id of the notification
|
||||
* @since 5.18
|
||||
*/
|
||||
void selectEvent(const QString &eventId);
|
||||
|
||||
public Q_SLOTS:
|
||||
/**
|
||||
* save to the config file
|
||||
*/
|
||||
void save();
|
||||
|
||||
/*
|
||||
* Reset the UI to display the default values
|
||||
* @see KCModule::defaults
|
||||
* @since 5.15
|
||||
*/
|
||||
void revertToDefaults();
|
||||
|
||||
/*
|
||||
* Disable all sounds for the current application
|
||||
* @since 5.23
|
||||
*/
|
||||
void disableAllSounds();
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* Indicate that the state of the modules contents has changed.
|
||||
* This signal is emitted whenever the state of the configuration changes.
|
||||
* @see KCModule::changed
|
||||
*/
|
||||
void changed(bool state);
|
||||
|
||||
private Q_SLOTS:
|
||||
KNOTIFYCONFIG_NO_EXPORT void slotEventSelected(KNotifyConfigElement *e);
|
||||
KNOTIFYCONFIG_NO_EXPORT void slotActionChanged();
|
||||
|
||||
private:
|
||||
std::unique_ptr<KNotifyConfigWidgetPrivate> const d;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
This file is part of the KDE libraries
|
||||
SPDX-FileCopyrightText: 2005 Olivier Goffart <ogoffart at kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-only
|
||||
*/
|
||||
|
||||
#include "knotifyeventlist.h"
|
||||
|
||||
#include <knotifyconfig_debug.h>
|
||||
|
||||
#include <KConfig>
|
||||
#include <KConfigGroup>
|
||||
#include <KLocalizedString>
|
||||
|
||||
#include <QHeaderView>
|
||||
#include <QPainter>
|
||||
#include <QRegularExpression>
|
||||
#include <QStandardPaths>
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
// BEGIN KNotifyEventListDelegate
|
||||
|
||||
class KNotifyEventList::KNotifyEventListDelegate : public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
explicit KNotifyEventListDelegate(QObject *parent = nullptr);
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
KNotifyEventList::KNotifyEventListDelegate::KNotifyEventListDelegate(QObject *parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void KNotifyEventList::KNotifyEventListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
if (index.column() != 0) {
|
||||
return QStyledItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
|
||||
QVariant displayData = index.data(Qt::UserRole);
|
||||
QString prstring = displayData.toString();
|
||||
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
|
||||
// qDebug() << prstring;
|
||||
|
||||
QRect rect = option.rect;
|
||||
|
||||
QStringList optionsList = prstring.split(QLatin1Char('|'));
|
||||
QList<QIcon> iconList;
|
||||
iconList << (optionsList.contains(QStringLiteral("Sound")) ? QIcon::fromTheme(QStringLiteral("media-playback-start")) : QIcon());
|
||||
iconList << (optionsList.contains(QStringLiteral("Popup")) ? QIcon::fromTheme(QStringLiteral("dialog-information")) : QIcon());
|
||||
|
||||
int mc_x = 0;
|
||||
|
||||
int iconWidth = option.decorationSize.width();
|
||||
int iconHeight = option.decorationSize.height();
|
||||
for (const QIcon &icon : std::as_const(iconList)) {
|
||||
icon.paint(painter, rect.left() + mc_x + 4, rect.top() + (rect.height() - iconHeight) / 2, iconWidth, iconHeight);
|
||||
mc_x += iconWidth + 4;
|
||||
}
|
||||
}
|
||||
|
||||
// END KNotifyEventListDelegate
|
||||
|
||||
KNotifyEventList::KNotifyEventList(QWidget *parent)
|
||||
: QTreeWidget(parent)
|
||||
, config(nullptr)
|
||||
{
|
||||
QStringList headerLabels;
|
||||
headerLabels << i18nc("State of the notified event", "State") << i18nc("Title of the notified event", "Title")
|
||||
<< i18nc("Description of the notified event", "Description");
|
||||
setHeaderLabels(headerLabels);
|
||||
|
||||
setItemDelegate(new KNotifyEventListDelegate(this));
|
||||
setRootIsDecorated(false);
|
||||
setAlternatingRowColors(true);
|
||||
|
||||
// Extract icon size as the font height (as h=w on icons)
|
||||
QStyleOptionViewItem iconOption;
|
||||
iconOption.initFrom(this);
|
||||
int iconWidth = iconOption.fontMetrics.height() - 2; // 1px margin top & bottom
|
||||
setIconSize(QSize(iconWidth, iconWidth));
|
||||
|
||||
header()->setSectionResizeMode(0, QHeaderView::Fixed);
|
||||
header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
|
||||
|
||||
connect(this, SIGNAL(currentItemChanged(QTreeWidgetItem *, QTreeWidgetItem *)), this, SLOT(slotSelectionChanged(QTreeWidgetItem *, QTreeWidgetItem *)));
|
||||
}
|
||||
|
||||
KNotifyEventList::~KNotifyEventList()
|
||||
{
|
||||
delete config;
|
||||
}
|
||||
|
||||
void KNotifyEventList::fill(const QString &appname, bool loadDefaults)
|
||||
{
|
||||
m_elements.clear();
|
||||
clear();
|
||||
delete config;
|
||||
config = new KConfig(appname + QStringLiteral(".notifyrc"), KConfig::NoGlobals);
|
||||
auto configSources =
|
||||
QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("knotifications6/") + appname + QStringLiteral(".notifyrc"));
|
||||
// `QStandardPaths` follows the order of precedence given by `$XDG_DATA_DIRS
|
||||
// (more priority goest first), but for `addConfigSources() it is the opposite
|
||||
std::reverse(configSources.begin(), configSources.end());
|
||||
config->addConfigSources(configSources);
|
||||
|
||||
QStringList conflist = config->groupList();
|
||||
QRegularExpression rx(QStringLiteral("^Event/([^/]*)$"));
|
||||
conflist = conflist.filter(rx);
|
||||
|
||||
for (const QString &group : std::as_const(conflist)) {
|
||||
KConfigGroup cg(config, group);
|
||||
QString id = rx.match(group).captured(1);
|
||||
QString name = cg.readEntry("Name");
|
||||
QString description = cg.readEntry("Comment");
|
||||
|
||||
if (loadDefaults) {
|
||||
KConfigGroup g(config, QStringLiteral("Event/") + id);
|
||||
const auto keyList = g.keyList();
|
||||
for (const QString &entry : keyList) {
|
||||
g.revertToDefault(entry);
|
||||
}
|
||||
}
|
||||
|
||||
m_elements << new KNotifyEventListItem(this, id, name, description, config);
|
||||
}
|
||||
|
||||
resizeColumnToContents(2);
|
||||
}
|
||||
|
||||
void KNotifyEventList::save()
|
||||
{
|
||||
for (KNotifyEventListItem *it : std::as_const(m_elements)) {
|
||||
it->save();
|
||||
}
|
||||
config->sync();
|
||||
}
|
||||
|
||||
bool KNotifyEventList::disableAllSounds()
|
||||
{
|
||||
bool changed = false;
|
||||
for (KNotifyEventListItem *it : std::as_const(m_elements)) {
|
||||
QStringList actions = it->configElement()->readEntry(QStringLiteral("Action")).split(QLatin1Char('|'));
|
||||
if (actions.removeAll(QStringLiteral("Sound"))) {
|
||||
it->configElement()->writeEntry(QStringLiteral("Action"), actions.join(QLatin1Char('|')));
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
void KNotifyEventList::slotSelectionChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
|
||||
{
|
||||
Q_UNUSED(current);
|
||||
|
||||
KNotifyEventListItem *it = dynamic_cast<KNotifyEventListItem *>(currentItem());
|
||||
if (it) {
|
||||
Q_EMIT eventSelected(it->configElement());
|
||||
} else {
|
||||
Q_EMIT eventSelected(nullptr);
|
||||
}
|
||||
|
||||
it = dynamic_cast<KNotifyEventListItem *>(previous);
|
||||
if (it) {
|
||||
it->update();
|
||||
}
|
||||
}
|
||||
|
||||
void KNotifyEventList::updateCurrentItem()
|
||||
{
|
||||
KNotifyEventListItem *it = dynamic_cast<KNotifyEventListItem *>(currentItem());
|
||||
if (it) {
|
||||
it->update();
|
||||
}
|
||||
}
|
||||
|
||||
void KNotifyEventList::updateAllItems()
|
||||
{
|
||||
for (KNotifyEventListItem *it : std::as_const(m_elements)) {
|
||||
it->update();
|
||||
}
|
||||
}
|
||||
|
||||
void KNotifyEventList::selectEvent(const QString &eventId)
|
||||
{
|
||||
auto it = std::find_if(m_elements.constBegin(), m_elements.constEnd(), [&eventId](KNotifyEventListItem *item) {
|
||||
return item->configElement()->eventId() == eventId;
|
||||
});
|
||||
|
||||
if (it != m_elements.constEnd()) {
|
||||
setCurrentItem(*it);
|
||||
}
|
||||
}
|
||||
|
||||
QSize KNotifyEventList::sizeHint() const
|
||||
{
|
||||
int fontSize = fontMetrics().height();
|
||||
return QSize(48 * fontSize, 12 * fontSize);
|
||||
}
|
||||
|
||||
KNotifyEventListItem::KNotifyEventListItem(QTreeWidget *parent, const QString &eventName, const QString &name, const QString &description, KConfig *config)
|
||||
: QTreeWidgetItem(parent)
|
||||
, m_config(eventName, config)
|
||||
{
|
||||
setText(1, name);
|
||||
setToolTip(1, description);
|
||||
setText(2, description);
|
||||
setToolTip(2, description);
|
||||
update();
|
||||
}
|
||||
|
||||
KNotifyEventListItem::~KNotifyEventListItem()
|
||||
{
|
||||
}
|
||||
|
||||
void KNotifyEventListItem::save()
|
||||
{
|
||||
m_config.save();
|
||||
}
|
||||
|
||||
void KNotifyEventListItem::update()
|
||||
{
|
||||
setData(0, Qt::UserRole, m_config.readEntry(QStringLiteral("Action")));
|
||||
}
|
||||
|
||||
#include "moc_knotifyeventlist.cpp"
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
This file is part of the KDE libraries
|
||||
SPDX-FileCopyrightText: 2005 Olivier Goffart <ogoffart at kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-only
|
||||
*/
|
||||
|
||||
#ifndef KNOTIFYEVENTLIST_H
|
||||
#define KNOTIFYEVENTLIST_H
|
||||
|
||||
#include "knotifyconfigelement.h"
|
||||
|
||||
#include <QTreeWidget>
|
||||
|
||||
class KNotifyConfigElement;
|
||||
class KNotifyEventListItem;
|
||||
class KConfig;
|
||||
|
||||
/**
|
||||
@author Olivier Goffart <ogoffart at kde.org>
|
||||
*/
|
||||
class KNotifyEventList : public QTreeWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit KNotifyEventList(QWidget *parent);
|
||||
~KNotifyEventList() override;
|
||||
void fill(const QString &appname, bool loadDefaults = false);
|
||||
void save();
|
||||
void updateCurrentItem();
|
||||
void updateAllItems();
|
||||
QSize sizeHint() const override;
|
||||
|
||||
void selectEvent(const QString &eventId);
|
||||
bool disableAllSounds();
|
||||
|
||||
private:
|
||||
KConfig *config;
|
||||
QList<KNotifyEventListItem *> m_elements;
|
||||
|
||||
class KNotifyEventListDelegate;
|
||||
|
||||
private Q_SLOTS:
|
||||
void slotSelectionChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
|
||||
|
||||
Q_SIGNALS:
|
||||
void eventSelected(KNotifyConfigElement *);
|
||||
};
|
||||
|
||||
class KNotifyEventListItem : public QTreeWidgetItem
|
||||
{
|
||||
public:
|
||||
KNotifyEventListItem(QTreeWidget *parent, const QString &eventName, const QString &name, const QString &description, KConfig *confir);
|
||||
~KNotifyEventListItem() override;
|
||||
void save();
|
||||
|
||||
KNotifyConfigElement *configElement()
|
||||
{
|
||||
return &m_config;
|
||||
}
|
||||
|
||||
void update();
|
||||
|
||||
private:
|
||||
KNotifyConfigElement m_config;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user