Warning, file /frameworks/knotifyconfig/src/knotifyconfigactionswidget.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2005-2007 Olivier Goffart <ogoffart at kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only 0006 */ 0007 0008 #include "knotifyconfigactionswidget.h" 0009 0010 #include "knotifyconfigelement.h" 0011 #include <knotifyconfig_debug.h> 0012 0013 #include <QFile> 0014 #include <QStandardPaths> 0015 #include <QUrl> 0016 0017 #if HAVE_CANBERRA 0018 #include <canberra.h> 0019 #elif HAVE_PHONON 0020 #include <phonon/mediaobject.h> 0021 #endif 0022 0023 KNotifyConfigActionsWidget::KNotifyConfigActionsWidget(QWidget *parent) 0024 : QWidget(parent) 0025 { 0026 m_ui.setupUi(this); 0027 0028 // Show sounds directory by default 0029 QStringList soundDirs = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("sounds"), QStandardPaths::LocateDirectory); 0030 if (!soundDirs.isEmpty()) { 0031 m_ui.Sound_select->setStartDir(QUrl::fromLocalFile(soundDirs.last())); 0032 } 0033 m_ui.Sound_select->setMimeTypeFilters({QStringLiteral("audio/x-vorbis+ogg"), QStringLiteral("audio/x-wav")}); 0034 0035 m_ui.Sound_play->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start"))); 0036 m_ui.Sound_check->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start"))); 0037 m_ui.Popup_check->setIcon(QIcon::fromTheme(QStringLiteral("dialog-information"))); 0038 m_ui.Logfile_check->setIcon(QIcon::fromTheme(QStringLiteral("text-x-generic"))); 0039 m_ui.Execute_check->setIcon(QIcon::fromTheme(QStringLiteral("system-run"))); 0040 m_ui.Taskbar_check->setIcon(QIcon::fromTheme(QStringLiteral("services"))); 0041 m_ui.TTS_check->setIcon(QIcon::fromTheme(QStringLiteral("text-speak"))); 0042 0043 connect(m_ui.Execute_check, SIGNAL(toggled(bool)), this, SIGNAL(changed())); 0044 connect(m_ui.Sound_check, SIGNAL(toggled(bool)), this, SIGNAL(changed())); 0045 connect(m_ui.Popup_check, SIGNAL(toggled(bool)), this, SIGNAL(changed())); 0046 connect(m_ui.Logfile_check, SIGNAL(toggled(bool)), this, SIGNAL(changed())); 0047 connect(m_ui.Taskbar_check, SIGNAL(toggled(bool)), this, SIGNAL(changed())); 0048 connect(m_ui.TTS_check, SIGNAL(toggled(bool)), this, SLOT(slotTTSComboChanged())); 0049 connect(m_ui.Execute_select, SIGNAL(textChanged(QString)), this, SIGNAL(changed())); 0050 connect(m_ui.Sound_select, SIGNAL(textChanged(QString)), this, SIGNAL(changed())); 0051 connect(m_ui.Logfile_select, SIGNAL(textChanged(QString)), this, SIGNAL(changed())); 0052 connect(m_ui.Sound_play, SIGNAL(clicked()), this, SLOT(slotPlay())); 0053 connect(m_ui.TTS_select, SIGNAL(textChanged(QString)), this, SIGNAL(changed())); 0054 connect(m_ui.TTS_combo, SIGNAL(currentIndexChanged(int)), this, SLOT(slotTTSComboChanged())); 0055 m_ui.TTS_combo->setEnabled(false); 0056 if (!KNotifyConfigElement::have_tts()) { 0057 m_ui.TTS_check->setVisible(false); 0058 m_ui.TTS_select->setVisible(false); 0059 m_ui.TTS_combo->setVisible(false); 0060 } 0061 } 0062 0063 KNotifyConfigActionsWidget::~KNotifyConfigActionsWidget() 0064 { 0065 #if HAVE_CANBERRA 0066 if (m_context) { 0067 ca_context_destroy(m_context); 0068 } 0069 m_context = nullptr; 0070 #endif 0071 } 0072 0073 void KNotifyConfigActionsWidget::setConfigElement(KNotifyConfigElement *config) 0074 { 0075 bool blocked = blockSignals(true); // to block the changed() signal 0076 QString prstring = config->readEntry(QStringLiteral("Action")); 0077 QStringList actions = prstring.split(QLatin1Char('|')); 0078 0079 m_ui.Sound_check->setChecked(actions.contains(QStringLiteral("Sound"))); 0080 m_ui.Popup_check->setChecked(actions.contains(QStringLiteral("Popup"))); 0081 m_ui.Logfile_check->setChecked(actions.contains(QStringLiteral("Logfile"))); 0082 m_ui.Execute_check->setChecked(actions.contains(QStringLiteral("Execute"))); 0083 m_ui.Taskbar_check->setChecked(actions.contains(QStringLiteral("Taskbar"))); 0084 m_ui.TTS_check->setChecked(actions.contains(QStringLiteral("TTS"))); 0085 0086 m_ui.Sound_select->setUrl(QUrl(config->readEntry(QStringLiteral("Sound"), true))); 0087 m_ui.Logfile_select->setUrl(QUrl(config->readEntry(QStringLiteral("Logfile"), true))); 0088 m_ui.Execute_select->setUrl(QUrl::fromLocalFile(config->readEntry(QStringLiteral("Execute")))); 0089 m_ui.TTS_select->setText(config->readEntry(QStringLiteral("TTS"))); 0090 if (m_ui.TTS_select->text() == QLatin1String("%e")) { 0091 m_ui.TTS_combo->setCurrentIndex(1); 0092 } else if (m_ui.TTS_select->text() == QLatin1String("%m") || m_ui.TTS_select->text() == QLatin1String("%s")) { 0093 m_ui.TTS_combo->setCurrentIndex(0); 0094 } else { 0095 m_ui.TTS_combo->setCurrentIndex(2); 0096 } 0097 blockSignals(blocked); 0098 } 0099 0100 void KNotifyConfigActionsWidget::save(KNotifyConfigElement *config) 0101 { 0102 QStringList actions; 0103 if (m_ui.Sound_check->isChecked()) { 0104 actions << QStringLiteral("Sound"); 0105 } 0106 if (m_ui.Popup_check->isChecked()) { 0107 actions << QStringLiteral("Popup"); 0108 } 0109 if (m_ui.Logfile_check->isChecked()) { 0110 actions << QStringLiteral("Logfile"); 0111 } 0112 if (m_ui.Execute_check->isChecked()) { 0113 actions << QStringLiteral("Execute"); 0114 } 0115 if (m_ui.Taskbar_check->isChecked()) { 0116 actions << QStringLiteral("Taskbar"); 0117 } 0118 if (m_ui.TTS_check->isChecked()) { 0119 actions << QStringLiteral("TTS"); 0120 } 0121 0122 config->writeEntry(QStringLiteral("Action"), actions.join(QLatin1Char('|'))); 0123 0124 config->writeEntry(QStringLiteral("Sound"), 0125 m_ui.Sound_select->text()); // don't use .url() here, .notifyrc files have predefined "static" entries with no path 0126 config->writeEntry(QStringLiteral("Logfile"), m_ui.Logfile_select->url().toString()); 0127 config->writeEntry(QStringLiteral("Execute"), m_ui.Execute_select->url().toLocalFile()); 0128 switch (m_ui.TTS_combo->currentIndex()) { 0129 case 0: 0130 config->writeEntry(QStringLiteral("TTS"), QStringLiteral("%s")); 0131 break; 0132 case 1: 0133 config->writeEntry(QStringLiteral("TTS"), QStringLiteral("%e")); 0134 break; 0135 case 2: 0136 default: 0137 config->writeEntry(QStringLiteral("TTS"), m_ui.TTS_select->text()); 0138 } 0139 } 0140 0141 void KNotifyConfigActionsWidget::slotPlay() 0142 { 0143 const QString soundFilename = m_ui.Sound_select->text(); 0144 QUrl soundURL; 0145 const auto dataLocations = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); 0146 for (const QString &dataLocation : dataLocations) { 0147 soundURL = QUrl::fromUserInput(soundFilename, dataLocation + QStringLiteral("/sounds"), QUrl::AssumeLocalFile); 0148 if (soundURL.isLocalFile() && QFile::exists(soundURL.toLocalFile())) { 0149 break; 0150 } else if (!soundURL.isLocalFile() && soundURL.isValid()) { 0151 break; 0152 } 0153 soundURL.clear(); 0154 } 0155 0156 #if HAVE_CANBERRA 0157 if (!m_context) { 0158 int ret = ca_context_create(&m_context); 0159 if (ret != CA_SUCCESS) { 0160 qCWarning(KNOTIFYCONFIG_LOG) << "Failed to initialize canberra context for audio notification:" << ca_strerror(ret); 0161 m_context = nullptr; 0162 return; 0163 } 0164 0165 QString desktopFileName = QGuiApplication::desktopFileName(); 0166 // handle apps which set the desktopFileName property with filename suffix, 0167 // due to unclear API dox (https://bugreports.qt.io/browse/QTBUG-75521) 0168 if (desktopFileName.endsWith(QLatin1String(".desktop"))) { 0169 desktopFileName.chop(8); 0170 } 0171 ret = ca_context_change_props(m_context, 0172 CA_PROP_APPLICATION_NAME, 0173 qUtf8Printable(qApp->applicationDisplayName()), 0174 CA_PROP_APPLICATION_ID, 0175 qUtf8Printable(desktopFileName), 0176 CA_PROP_APPLICATION_ICON_NAME, 0177 qUtf8Printable(qApp->windowIcon().name()), 0178 nullptr); 0179 if (ret != CA_SUCCESS) { 0180 qCWarning(KNOTIFYCONFIG_LOG) << "Failed to set application properties on canberra context for audio notification:" << ca_strerror(ret); 0181 } 0182 } 0183 0184 ca_proplist *props = nullptr; 0185 ca_proplist_create(&props); 0186 0187 // We'll also want this cached for a time. volatile makes sure the cache is 0188 // dropped after some time or when the cache is under pressure. 0189 ca_proplist_sets(props, CA_PROP_MEDIA_FILENAME, QFile::encodeName(soundURL.toLocalFile()).constData()); 0190 ca_proplist_sets(props, CA_PROP_CANBERRA_CACHE_CONTROL, "volatile"); 0191 0192 int ret = ca_context_play_full(m_context, 0, props, nullptr, nullptr); 0193 0194 ca_proplist_destroy(props); 0195 0196 if (ret != CA_SUCCESS) { 0197 qCWarning(KNOTIFYCONFIG_LOG) << "Failed to play sound with canberra:" << ca_strerror(ret); 0198 return; 0199 } 0200 #elif HAVE_PHONON 0201 Phonon::MediaObject *media = Phonon::createPlayer(Phonon::NotificationCategory, soundURL); 0202 media->play(); 0203 connect(media, SIGNAL(finished()), media, SLOT(deleteLater())); 0204 #endif 0205 } 0206 0207 void KNotifyConfigActionsWidget::slotTTSComboChanged() 0208 { 0209 m_ui.TTS_select->setEnabled(m_ui.TTS_check->isChecked() && m_ui.TTS_combo->currentIndex() == 2); 0210 Q_EMIT changed(); 0211 }