feat: add missing KF6 framework recipes

This commit is contained in:
2026-05-07 07:53:26 +01:00
parent d8d498f831
commit a69f479b52
2374 changed files with 2610246 additions and 0 deletions
@@ -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}"
)
+13
View File
@@ -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 &amp;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 &amp;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