summaryrefslogtreecommitdiffstats
path: root/kttsd/kcmkttsmgr
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit00bb99ac80741fc50ef8a289719373032f2391eb (patch)
tree3a5a9bf72f942784b38bf77dd66c534662fab5f2 /kttsd/kcmkttsmgr
downloadtdeaccessibility-00bb99ac80741fc50ef8a289719373032f2391eb.tar.gz
tdeaccessibility-00bb99ac80741fc50ef8a289719373032f2391eb.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdeaccessibility@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kttsd/kcmkttsmgr')
-rw-r--r--kttsd/kcmkttsmgr/Makefile.am51
-rw-r--r--kttsd/kcmkttsmgr/addtalker.cpp225
-rw-r--r--kttsd/kcmkttsmgr/addtalker.h89
-rw-r--r--kttsd/kcmkttsmgr/addtalkerwidget.ui260
-rw-r--r--kttsd/kcmkttsmgr/kcmkttsd.desktop142
-rw-r--r--kttsd/kcmkttsmgr/kcmkttsd_testmessage.desktop46
-rw-r--r--kttsd/kcmkttsmgr/kcmkttsmgr.cpp2713
-rw-r--r--kttsd/kcmkttsmgr/kcmkttsmgr.h530
-rw-r--r--kttsd/kcmkttsmgr/kcmkttsmgrwidget.ui1928
-rw-r--r--kttsd/kcmkttsmgr/kcmkttsmgrwidget.ui.h16
-rw-r--r--kttsd/kcmkttsmgr/selectevent.cpp149
-rw-r--r--kttsd/kcmkttsmgr/selectevent.h69
-rw-r--r--kttsd/kcmkttsmgr/selecteventwidget.ui62
13 files changed, 6280 insertions, 0 deletions
diff --git a/kttsd/kcmkttsmgr/Makefile.am b/kttsd/kcmkttsmgr/Makefile.am
new file mode 100644
index 0000000..094f59c
--- /dev/null
+++ b/kttsd/kcmkttsmgr/Makefile.am
@@ -0,0 +1,51 @@
+# Include paths.
+INCLUDES = \
+ -I$(top_srcdir)/kttsd/libkttsd -I$(top_builddir)/kttsd/libkttsd \
+ $(CFLAGS_GST) \
+ $(KTTS_KSPEECH_INCLUDE) \
+ $(all_includes)
+
+# Let automoc handle all of the metsource files (moc).
+METASOURCES = AUTO
+
+#########################################################################
+# KCMODULE SECTION
+#########################################################################
+# This is the kcmodule that gets installed. It's name is used for all
+# of the other Makefile.am variables.
+
+kde_module_LTLIBRARIES = kcm_kttsd.la
+
+kspeech_DIR = $(KTTS_KSPEECH_DIR)
+kspeechsink_DIR = $(KTTS_KSPEECH_DIR)
+
+# The source, library search path, and link libraries.
+kcm_kttsd_la_SOURCES = \
+ kspeech.stub \
+ kspeechsink.skel \
+ kcmkttsmgr.cpp \
+ kcmkttsmgrwidget.ui \
+ addtalker.cpp \
+ addtalkerwidget.ui \
+ selectevent.cpp \
+ selecteventwidget.ui
+
+kcm_kttsd_la_LDFLAGS = -avoid-version -module -no-undefined $(all_libraries)
+kcm_kttsd_la_LIBADD = \
+ $(top_builddir)/kttsd/libkttsd/libkttsd.la \
+ $(LIB_KIO)
+
+# Header files that should not be installed.
+noinst_HEADERS = \
+ kcmkttsmgr.h \
+ kcmkttsmgrwidget.h \
+ kcmkttsmgrwidget.ui.h \
+ addtalker.h \
+ selectevent.h
+
+# K Menu entry.
+xdg_apps_DATA = kcmkttsd.desktop
+
+# Install data files.
+kcmkttsddatadir = $(kde_datadir)/kttsd/
+kcmkttsddata_DATA = kcmkttsd_testmessage.desktop
diff --git a/kttsd/kcmkttsmgr/addtalker.cpp b/kttsd/kcmkttsmgr/addtalker.cpp
new file mode 100644
index 0000000..2353ada
--- /dev/null
+++ b/kttsd/kcmkttsmgr/addtalker.cpp
@@ -0,0 +1,225 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Dialog to allow user to add a new Talker by selecting a language and synthesizer
+ (button). Uses addtalkerwidget.ui.
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// Qt includes.
+#include <qradiobutton.h>
+
+// KDE includes.
+#include <kcombobox.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+// KTTS includes.
+#include "addtalker.h"
+
+AddTalker::AddTalker(SynthToLangMap synthToLangMap, QWidget* parent, const char* name, WFlags fl)
+ : AddTalkerWidget(parent,name,fl)
+{
+ // Build maps.
+ setSynthToLangMap(synthToLangMap);
+
+ // Fill comboboxes.
+ applyFilter();
+
+ // Default to user's desktop language.
+ QString languageCode = KGlobal::locale()->defaultLanguage();
+ // If there is not a synth that supports the locale, try stripping country code.
+ if (!m_langToSynthMap.contains(languageCode))
+ {
+ QString countryCode;
+ QString charSet;
+ QString twoAlpha;
+ KGlobal::locale()->splitLocale(languageCode, twoAlpha, countryCode, charSet);
+ languageCode = twoAlpha;
+ }
+ // If there is still not a synth that supports the language code, default to "other".
+ if (!m_langToSynthMap.contains(languageCode)) languageCode = "other";
+
+ // Select the language in the language combobox.
+ QString language = languageCodeToLanguage(languageCode);
+ languageSelection->setCurrentItem(language, false);
+
+ // Filter comboboxes.
+ applyFilter();
+
+ // Connect widgets to slots.
+ connect(languageRadioButton, SIGNAL(clicked()), this, SLOT(applyFilter()));
+ connect(synthesizerRadioButton, SIGNAL(clicked()), this, SLOT(applyFilter()));
+ connect(languageSelection, SIGNAL(activated(int)), this, SLOT(applyFilter()));
+ connect(synthesizerSelection, SIGNAL(activated(int)), this, SLOT(applyFilter()));
+}
+
+AddTalker::~AddTalker()
+{
+}
+
+/**
+* Returns user's chosen language code.
+*/
+QString AddTalker::getLanguageCode()
+{
+ return m_languageToLanguageCodeMap[languageSelection->currentText()];
+}
+
+/**
+* Returns user's chosen synthesizer.
+*/
+QString AddTalker::getSynthesizer() { return synthesizerSelection->currentText(); }
+
+// Set the synthesizer-to-languages map.
+// @param synthToLang QMap of supported language codes indexed by synthesizer.
+void AddTalker::setSynthToLangMap(SynthToLangMap synthToLangMap)
+{
+ m_synthToLangMap = synthToLangMap;
+ // "Invert" the map, i.e., map language codes to synthesizers.
+ QStringList synthList = m_synthToLangMap.keys();
+ const int synthListCount = synthList.count();
+ for (int synthNdx=0; synthNdx < synthListCount; ++synthNdx)
+ {
+ QString synth = synthList[synthNdx];
+ QStringList languageCodeList = m_synthToLangMap[synth];
+ const int languageCodeListCount = languageCodeList.count();
+ for (int langNdx=0; langNdx < languageCodeListCount; ++langNdx)
+ {
+ QString languageCode = languageCodeList[langNdx];
+ QStringList synthesizerList = m_langToSynthMap[languageCode];
+ synthesizerList.append(synth);
+ m_langToSynthMap[languageCode] = synthesizerList;
+ }
+ }
+ // Fill language to language code map.
+ QStringList languageCodeList = m_langToSynthMap.keys();
+ const int languageCodeListCount = languageCodeList.count();
+ for (int ndx = 0; ndx < languageCodeListCount; ++ndx)
+ {
+ QString languageCode = languageCodeList[ndx];
+ QString language = languageCodeToLanguage(languageCode);
+ m_languageToLanguageCodeMap[language] = languageCode;
+ }
+}
+
+// Converts a language code plus optional country code to language description.
+QString AddTalker::languageCodeToLanguage(const QString &languageCode)
+{
+ QString twoAlpha;
+ QString countryCode;
+ QString charSet;
+ QString language;
+ if (languageCode == "other")
+ language = i18n("Other");
+ else
+ {
+ KGlobal::locale()->splitLocale(languageCode, twoAlpha, countryCode, charSet);
+ language = KGlobal::locale()->twoAlphaToLanguageName(twoAlpha);
+ }
+ if (!countryCode.isEmpty())
+ language += " (" + KGlobal::locale()->twoAlphaToCountryName(countryCode) + ")";
+ return language;
+}
+
+// Based on user's radio button selection, filters choices for language or synthesizer
+// comboboxes based on what is selected in the other combobox.
+void AddTalker::applyFilter()
+{
+ if (languageRadioButton->isChecked())
+ {
+ // Get current language.
+ QString language = languageSelection->currentText();
+ // Fill language combobox will all possible languages.
+ languageSelection->clear();
+ QStringList languageCodeList = m_langToSynthMap.keys();
+ const int languageCodeListCount = languageCodeList.count();
+ QStringList languageList;
+ for (int ndx=0; ndx < languageCodeListCount; ++ndx)
+ {
+ languageList.append(languageCodeToLanguage(languageCodeList[ndx]));
+ }
+ languageList.sort();
+ for (int ndx=0; ndx < languageCodeListCount; ++ndx)
+ {
+ languageSelection->insertItem(languageList[ndx]);
+ }
+ // Re-select user's selection.
+ languageSelection->setCurrentItem(language, false);
+ // Get current language selection.
+ language = languageSelection->currentText();
+ // Map current language to language code.
+ QString languageCode = m_languageToLanguageCodeMap[language];
+ // Get list of synths that support this language code.
+ QStringList synthList = m_langToSynthMap[languageCode];
+ // Get current user's synth selection.
+ QString synth = synthesizerSelection->currentText();
+ // Fill synthesizer combobox.
+ synthesizerSelection->clear();
+ synthList.sort();
+ const int synthListCount = synthList.count();
+ for (int ndx=0; ndx < synthListCount; ++ndx)
+ {
+ synthesizerSelection->insertItem(synthList[ndx]);
+ }
+ // Re-select user's selection.
+ synthesizerSelection->setCurrentItem(synth, false);
+ }
+ else
+ {
+ // Get current synth selection.
+ QString synth = synthesizerSelection->currentText();
+ // Fill synthesizer combobox with all possible synths.
+ synthesizerSelection->clear();
+ QStringList synthList = m_synthToLangMap.keys();
+ synthList.sort();
+ const int synthListCount = synthList.count();
+ for (int ndx=0; ndx < synthListCount; ++ndx)
+ {
+ synthesizerSelection->insertItem(synthList[ndx]);
+ }
+ // Re-select user's synthesizer.
+ synthesizerSelection->setCurrentItem(synth, false);
+ // Get current synth selection.
+ synth = synthesizerSelection->currentText();
+ // Get list of supported language codes.
+ QStringList languageCodeList = m_synthToLangMap[synth];
+ // Get current user's language selection.
+ QString language = languageSelection->currentText();
+ // Fill language combobox with language descriptions.
+ languageSelection->clear();
+ const int languageCodeListCount = languageCodeList.count();
+ QStringList languageList;
+ for (int ndx=0; ndx < languageCodeListCount; ++ndx)
+ {
+ languageList.append(languageCodeToLanguage(languageCodeList[ndx]));
+ }
+ languageList.sort();
+ for (int ndx=0; ndx < languageCodeListCount; ++ndx)
+ {
+ languageSelection->insertItem(languageList[ndx]);
+ }
+ // Re-select user's language selection.
+ languageSelection->setCurrentItem(language, false);
+ }
+}
+
+#include "addtalker.moc"
+
diff --git a/kttsd/kcmkttsmgr/addtalker.h b/kttsd/kcmkttsmgr/addtalker.h
new file mode 100644
index 0000000..29bbfb5
--- /dev/null
+++ b/kttsd/kcmkttsmgr/addtalker.h
@@ -0,0 +1,89 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Dialog to allow user to add a new Talker by selecting a language and synthesizer
+ (button). Uses addtalkerwidget.ui.
+ -------------------
+ Copyright:
+ (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef ADDTALKER_H
+#define ADDTALKER_H
+
+// Qt includes.
+#include <qmap.h>
+
+#include "addtalkerwidget.h"
+
+typedef QMap<QString,QStringList> SynthToLangMap;
+typedef QMap<QString,QStringList> LangToSynthMap;
+
+class AddTalker : public AddTalkerWidget
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructor.
+ * @param synthToLangMap QMap of supported language codes indexed by synthesizer.
+ * @param parent Inherited KDialog parameter.
+ * @param name Inherited KDialog parameter.
+ */
+ AddTalker(SynthToLangMap synthToLangMap, QWidget* parent = 0, const char* name = 0, WFlags fl = 0 );
+
+ /**
+ * Destructor.
+ */
+ ~AddTalker();
+
+ /**
+ * Returns user's chosen language code.
+ */
+ QString getLanguageCode();
+
+ /**
+ * Returns user's chosen synthesizer.
+ */
+ QString getSynthesizer();
+
+
+private:
+ /**
+ * Set the synthesizer-to-languages map.
+ * @param synthToLang QMap of supported language codes indexed by synthesizer.
+ */
+ void setSynthToLangMap(SynthToLangMap synthToLangMap);
+
+ // Converts a language code plus optional country code to language description.
+ QString languageCodeToLanguage(const QString &languageCode);
+
+ // QMap of language descriptions to language codes.
+ QMap<QString,QString> m_languageToLanguageCodeMap;
+ // QMap of supported languages indexed by synthesizer.
+ SynthToLangMap m_synthToLangMap;
+ // QMap of synthesizers indexed by language code they support.
+ LangToSynthMap m_langToSynthMap;
+
+private slots:
+ // Based on user's radio button selection, filters choices for language or synthesizer
+ // comboboxes based on what is selected in the other combobox.
+ void applyFilter();
+};
+
+#endif
+
diff --git a/kttsd/kcmkttsmgr/addtalkerwidget.ui b/kttsd/kcmkttsmgr/addtalkerwidget.ui
new file mode 100644
index 0000000..f493138
--- /dev/null
+++ b/kttsd/kcmkttsmgr/addtalkerwidget.ui
@@ -0,0 +1,260 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>AddTalkerWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>AddTalkerWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>469</width>
+ <height>153</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Add Talker</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup" row="0" column="0">
+ <property name="name">
+ <cstring>buttonGroup2</cstring>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KComboBox" row="2" column="1">
+ <property name="name">
+ <cstring>synthesizerSelection</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the speech synthesizer to do the speaking.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="KComboBox" row="1" column="1">
+ <property name="name">
+ <cstring>languageSelection</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the language to be spoken. Note that after you configure a Talker, your chosen Language may be overridden by the synthesizer, depending upon the options you choose.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <spacer row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>351</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>synthesizerLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Synthesizer:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>synthesizerSelection</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the speech synthesizer to do the speaking.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <spacer row="1" column="2">
+ <property name="name">
+ <cstring>spacer10</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>25</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="1" column="4">
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>30</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="2" column="4">
+ <property name="name">
+ <cstring>spacer7</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>30</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="2" column="2">
+ <property name="name">
+ <cstring>spacer10_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>25</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="0" column="2" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>showAllLabel</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <underline>1</underline>
+ </font>
+ </property>
+ <property name="text">
+ <string>Show All</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignLeft</set>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The radio buttons below determine which box shows all possibilities. The box to the left of the checked button shows all possibilities. The box to the left of the unchecked box only shows those possibilities that match the other box.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>languageLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Language:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>languageSelection</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the language to be spoken. Note that after you configure a Talker, your chosen Language may be overridden by the synthesizer, depending upon the options you choose.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="1" column="3">
+ <property name="name">
+ <cstring>languageRadioButton</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="buttonGroupId">
+ <number>0</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check to list all the possible languages in the Language box at the left. When a language has been chosen, the Synthesizer box will show only those synthesizers that can speak in the chosen language.</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="2" column="3">
+ <property name="name">
+ <cstring>synthesizerRadioButton</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="buttonGroupId">
+ <number>0</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check this box to display all the available synthesizers in the Synthesizer box to the left. When a synthesizer is chosen, only the languages that can be spoken by that synthesizer appear in the Language box.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>languageSelection</tabstop>
+ <tabstop>synthesizerSelection</tabstop>
+ <tabstop>languageRadioButton</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kcombobox.h</includehint>
+</includehints>
+</UI>
diff --git a/kttsd/kcmkttsmgr/kcmkttsd.desktop b/kttsd/kcmkttsmgr/kcmkttsd.desktop
new file mode 100644
index 0000000..b54e66e
--- /dev/null
+++ b/kttsd/kcmkttsmgr/kcmkttsd.desktop
@@ -0,0 +1,142 @@
+[Desktop Entry]
+Type=Application
+Name=Text-to-Speech
+Name[bg]=Синтез на глас
+Name[bs]=Izgovaranje teksta
+Name[ca]=Text a veu
+Name[cs]=Hlasová syntéza
+Name[cy]=Testun-i-Leferydd
+Name[da]=Tekst-til-tale
+Name[de]=Sprachausgabe
+Name[el]=Κείμενο-σε-ομιλία
+Name[es]=Texto a voz
+Name[et]=Tekst kõneks
+Name[eu]=Testutik hizketara
+Name[fa]=متن به گفتار
+Name[fi]=Teksti puheeksi
+Name[fr]=Synthèse vocale
+Name[ga]=Téacs-go-Caint
+Name[gl]=Texto-para-Fala
+Name[he]=טקסט לדיבור
+Name[hu]=Szövegfelolvasó
+Name[is]=Texti-í-tal
+Name[it]=Pronuncia
+Name[ja]=テキスト読み上げ
+Name[ka]=ტექსტი-გახმოვანება
+Name[km]=អត្ថបទ​ដែល​ត្រូវ​និយាយ
+Name[mk]=Текст-во-говор
+Name[ms]=Teks-ke-Tutur
+Name[nb]=Tekst-til-tale
+Name[nds]=Vörleser
+Name[ne]=पाठ वाचक
+Name[nl]=Tekst-tot-spraak
+Name[pa]=ਪਾਠ ਤੋਂ ਬੋਲੀ
+Name[pl]=Odczytywanie tekstu
+Name[pt]=Texto-para-Fala
+Name[pt_BR]=Conversão de texto para fala
+Name[ru]=Синтез речи
+Name[sk]=Text-na-reč
+Name[sl]=Besedilo v govor
+Name[sr]=Текст-у-говор
+Name[sr@Latn]=Tekst-u-govor
+Name[sv]=Text-till-tal
+Name[ta]=உரையில் இருந்து பேச்சுக்கு
+Name[tg]=Таҳлили овоз
+Name[tr]=Metinden Konuşmaya
+Name[uk]=Синтез мовлення з тексту
+Name[vi]=Văn bản sang Tiếng nói
+Name[zh_TW]=文字轉語音
+Comment=Text-to-Speech Control Module
+Comment[bg]=Модул за синтез на глас
+Comment[bs]=Kontrolni modul za izgovaranje teksta
+Comment[ca]=Mòdul de control de text a veu
+Comment[cs]=Modul ovládání hlasové syntézy
+Comment[da]=Kontrolmodul for tekst-til-tale
+Comment[de]=Kontrollmodul für die Sprachausgabe
+Comment[el]=Άρθρωμα ελέγχου κειμένου-σε-ομιλία
+Comment[es]=Modulo de control del sintetizador texto a voz
+Comment[et]=Juhtimiskeskuse teksti kõneks muutmise moodul
+Comment[eu]=Testutik hizketarako modulua
+Comment[fa]=پیمانۀ کنترل متن به گفتار
+Comment[fi]=Teksti puheeksi -hallintamoduuli
+Comment[fr]=Module de configuration de la synthèse vocale
+Comment[ga]=Modúl Rialaithe Téacs-go-Caint
+Comment[gl]=Módulo de Control do Texto-para-Fala
+Comment[he]=מודול מרכז בקרה עבור טקסט לדיבור
+Comment[hu]=A szövegfelolvasó szolgáltatás beállításai
+Comment[is]=Texti-í-tal stjórneining
+Comment[it]=Modulo di controllo di pronuncia
+Comment[ja]=テキスト読み上げ制御モジュール
+Comment[ka]=ტექსტი-სიტყვის მართვის მოდული
+Comment[km]=ម៉ូឌុល​ត្រួតពិនិត្យ​​អត្ថបទ​ដែល​ត្រូវ​និយាយ
+Comment[mk]=Контролен модул за текст-во-говор
+Comment[ms]=Modul Kawalan Teks-ke-Tutur
+Comment[nb]=Styremodul for tekst-til-tale
+Comment[nds]=Kuntrullmoduul för den Vörleser
+Comment[ne]=पाठ वाचक नियन्त्रण मोड्युल
+Comment[nl]=Tekst-tot-spraak configuratiemodule
+Comment[pa]=ਪਾਠ ਤੋਂ ਬੋਲੀ ਕੰਟਰੋਲ ਮੈਡੀਊਲ
+Comment[pl]=Moduł konfiguracji odczytywania tekstu
+Comment[pt]=Módulo de Controlo de Texto-para-Fala
+Comment[pt_BR]=Módulo de Controle de conversão de texto para fala
+Comment[ru]=Настройка синтеза речи
+Comment[sk]=Riadiaci modul text-na-reč
+Comment[sl]=Nadzorni modul besedila v govor
+Comment[sr]=Контролни модул за текст-у-говор
+Comment[sr@Latn]=Kontrolni modul za tekst-u-govor
+Comment[sv]=Text-till-tal inställningsmodul
+Comment[ta]=உரையில் இருந்து பேச்சு கட்டுப்பாட்டு பகுதி
+Comment[tg]=Танзими таҳлили овоз
+Comment[tr]=Metinden Konuşmaya Kontrol Modülü
+Comment[uk]=Модуль керування синтезом мовлення з тексту
+Comment[vi]=Mô đun Điều khiển Văn bản sang Tiếng nói
+Comment[zh_TW]=文字轉語音控制模組
+ServiceTypes=Application,KCModule
+DocPath=kttsd
+NoDisplay=false
+StartupNotify=false
+StartupWMClass=
+Exec=kcmshell kcmkttsd
+Icon=kttsd
+Categories=Qt;KDE;Utility;Accessibility;
+Keywords=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice
+Keywords[bg]=синтез, глас, говор, текст, kttsd, kcmkttsmgr, kttsmgr, tts, ttsd, ktts, text, to, speech, speak, synthesizer, synth, festival, command, freetts, proklam, via, voice
+Keywords[br]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,skrid,da,prezegenn,komz,synthesizer,synth,festival,urzhiad,freetts,proklam,via,mouezh
+Keywords[bs]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice,čitanje,izgovaranje
+Keywords[ca]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,a,veu,parla,sintetitzador,síntesi,festival,ordre,freetts,proklam,via,veu
+Keywords[cs]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,mluvit,syntéza,syntetizér,synth,festival,příkaz,freetts,proklam,hlasová,předčítání,čtení
+Keywords[da]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,tekst,til,tale,tal,synthesizer,synth,festival,kommando,freetts,proklam,via,stemme
+Keywords[de]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice,Sprachsynthese,Vorlesen,Sprache,Sprachausgabe
+Keywords[el]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,κείμενο,σε,ομιλία,εκφώνηση,synthesizer,synth,festival,εντολή,freetts,proklam,μέσω,φωνή
+Keywords[es]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,texto,a,voz,habla,sintetizador,festival,orden,freetts,proklam,via,voz
+Keywords[et]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,tekst,kõneks,kõne,süntesaator,festival,käsk,freetts,proklam,hääl
+Keywords[eu]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,testua, hizketa,ahoskatu,sintetizadorea,synth,festival,command, freetts,proklam,via,ahotsa
+Keywords[fa]=kttsd،kcmkttsmgr،kttsmgr،tts،ttsd،ktts،متن، به، گفتار، صحبت کردن دهنده، synth، Festival، فرمان، freetts،proklam، از طریق، صدا
+Keywords[fr]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,texte,to,prononcer,énoncer,synthétiseur,synth,festival,command,freetts,proklam,via,voix
+Keywords[ga]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,téacs,go,caint,abair,sintéiseoir,sintéis,festival,ordú,freetts,proklam,via,guth,glór
+Keywords[gl]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,texto,para,fala,falar,sintetizador,sintetizar,festival,comando,freetts,proklam,via,voz
+Keywords[he]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice,דיבור,טקסט,מקריא, קול,פסטיבל,מסנטז,סינטי,סינטיזייזר
+Keywords[hu]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,szöveg,hang,beszéd,beszél,szintetizátor,szintetizálás,festival,parancs,freetts,proklam,via,voice
+Keywords[is]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,texti,í,tal,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice
+Keywords[it]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,pronuncia,parlare,sintetizzatore,synth,festival,comando,freetts,proklam,via,voce
+Keywords[mk]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice,текст,во,говор,синтисајзер,фестивал,наредба,команда,глас
+Keywords[nb]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,tekst,til,tale,snakke,synthesizer,synth,festival,kommando,freetts,proklam,via,voice
+Keywords[nds]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,Vörleser,vörlesen,Blicksnuut,synth,festival,freetts,proklam,Stimm,Spraakutgaav
+Keywords[nl]=kttsd,tts,ttsd,ktts,text to speech,praten,synthesizer,synth,festival,command,freetts,proklam,via voice,spraakprogramma,geluid,stem,tekst tot spraak,spreken,computerstem
+Keywords[pl]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice,tekst,do,mowa,mówienie, synteza,festival,polecenie,głos,mówienie,odczytywanie tekstu
+Keywords[pt]=kttsd,kcmkttsmgr,kttsmgr,tts,TTS,ttsd,ktts,texto,fala,falar,sintetizador,festival,comandar,freetts,proklam,via,voice
+Keywords[pt_BR]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,texto,fala,conversa, sintentizador,ynth,festival,command,freetts,proklam,via,voz
+Keywords[ru]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text-to-speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice,голос,речь,синтез,синтез речи
+Keywords[sl]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,besedilo,v,govor,govori,sintetizator,,festival,ukaz,freetts,proklam,preko,glas
+Keywords[sr]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice,текст,говор,наредба
+Keywords[sr@Latn]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice,tekst,govor,naredba
+Keywords[sv]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,till,tal,läsa,syntes,synt,festival,kommando,freetts,proklam,via,röst
+Keywords[tg]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice,овоз,ибора,таҳлили овоз
+Keywords[uk]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,text,to,speech,speak,synthesizer,synth,festival,command,freetts,proklam,via,voice,мовлення,синтез,голос,текст,команда,через
+Keywords[vi]=kttsd,kcmkttsmgr,kttsmgr,tts,ttsd,ktts,văn bản,sang,tiếng nói,nói,tổng hợp,tạp,festival,lệnh,freets,proklam,qua,giọng nói
+X-KDE-FactoryName=kttsd
+X-KDE-ParentApp=kcontrol
+X-KDE-SubstituteUID=false
+X-KDE-ModuleType=Library
+X-KDE-Library=kttsd
+Terminal=false
diff --git a/kttsd/kcmkttsmgr/kcmkttsd_testmessage.desktop b/kttsd/kcmkttsmgr/kcmkttsd_testmessage.desktop
new file mode 100644
index 0000000..816bfd7
--- /dev/null
+++ b/kttsd/kcmkttsmgr/kcmkttsd_testmessage.desktop
@@ -0,0 +1,46 @@
+[Desktop Entry]
+NoDisplay=true
+Name=The text-to-speech system seems to be functioning properly.
+Name[bg]=Системата за синтез на глас изглежда, че функционира нормално.
+Name[ca]=El sistema de text a veu sembla que funciona correctament.
+Name[cs]=Zdá se, že systém hlasové syntézy funguje správně.
+Name[da]=Tekst-til-tale systemet synes at virke rigtigt.
+Name[de]=Die Sprachausgabe scheint ordnungsgemäß zu funktionieren.
+Name[el]=Το σύστημα κειμένου-σε-ομιλία φαίνεται να λειτουργεί κανονικά.
+Name[es]=El sintetizador de texto a voz parece estar funcionando correctamente.
+Name[et]=Teksti kõneks muutmise süsteem paistab korralikult töötavat.
+Name[eu]=Testutik-hizketarako sistemak ongi funtzionatzen duela dirudi.
+Name[fa]=به نظر می‌رسد که سیستم متن به گفتار درست عمل می‌کند.
+Name[fi]=Teksti puheeksi -järjestelmä näyttää toimivan hyvin.
+Name[fr]=Le système de synthèse vocale semble fonctionner correctement.
+Name[ga]=Dealraíonn sé go bhfuil an córas téacs-go-caint ag obair mar is ceart.
+Name[gl]=O sistema de texto-para-fala parece estar a funcionar correctamente.
+Name[he]=נראה כי מערכת הטקסט לדיבור עובדת כהלכה.
+Name[hu]=A szövegfelolvasó rendszer megfelelően működik.
+Name[is]=Texti-í-tal kerfið virðist virka eðlilega.
+Name[it]=Il sistema di pronuncia pare funzionare correttamente.
+Name[ja]=テキスト読み上げシステムは正しく動作しているようです。
+Name[ka]=ტექსტი-გახმოვანება სისტემა როგორც ჩანს სწორად მოქმედებს.
+Name[km]=ប្រព័ន្ធ​អត្ថបទ​ដែល​ត្រូវ​និយាយ​ហាក់ដូចជា​មាន​មុខងារ​ត្រឹមត្រូវ ។
+Name[mk]=Изгледа дека системот за текст-во-говор функционира како што треба.
+Name[ms]=Sistem teks-ke-Tutur berfungsi dengan baik.
+Name[nb]=Tekst-til-tale-systemet ser ut til å virke som det skal.
+Name[nds]=As dat lett funkscheneert de Vörleser as he schall.
+Name[ne]=पाठ वाचक प्रणालीले ठीक रुपमा कार्य गर्ने देखिन्छ
+Name[nl]=Het tekst-tot-spraaksysteem blijkt goed te functioneren.
+Name[pa]=ਇੱਕ ਪਾਠ ਤੋਂ ਬੋਲੀ ਸੰਸਲੇਸ਼ਣ ਸਿਸਟਮ, ਜੋ ਕਿ ਠੀਕ ਤਰਾਂ ਕੰਮ ਕਰਦਾ ਜਾਪਦਾ ਹੈ।
+Name[pl]=System odczytywania tekstu funkcjonuje prawidłowo.
+Name[pt]=O sistema de texto-para-voz parece estar a funcionar correctamente.
+Name[pt_BR]=O sistema de fala do KDE parece estar funcionando corretamente.
+Name[ru]=Система синтеза речи работает нормально.
+Name[sk]=Systém text-na-reč funguje správne.
+Name[sl]=Sistem besedila v govor očitno deluje pravilno.
+Name[sr]=Систем текст-у-говор изгледа да функционише исправно.
+Name[sr@Latn]=Sistem tekst-u-govor izgleda da funkcioniše ispravno.
+Name[sv]=Text till tal-systemet verkar fungera som det ska.
+Name[ta]=உரையில் இருந்து பேச்சு அமைப்பு சரியாக இயங்குகிறது.
+Name[tg]=Системаи таҳлили овоз мӯътадил кор мекунад.
+Name[tr]=Metinden Konuşmaya sistemi düzgün çalışıyor.
+Name[uk]=Система синтезу мовлення з тексту функціонує правильно.
+Name[vi]=Hệ thống văn bản sang tiếng nói có vẻ hoạt động tốt.
+Name[zh_TW]=文字轉語音的系統已正常運作。
diff --git a/kttsd/kcmkttsmgr/kcmkttsmgr.cpp b/kttsd/kcmkttsmgr/kcmkttsmgr.cpp
new file mode 100644
index 0000000..d890446
--- /dev/null
+++ b/kttsd/kcmkttsmgr/kcmkttsmgr.cpp
@@ -0,0 +1,2713 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ KControl module for KTTSD configuration and Job Management
+ -------------------
+ Copyright : (C) 2002-2003 by José Pablo Ezequiel "Pupeno" Fernández
+ Copyright : (C) 2004-2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
+ Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+// Note to programmers. There is a subtle difference between a plugIn name and a
+// synthesizer name. The latter is a translated name, for example, "Festival Interactivo",
+// while the former is alway an English name, example "Festival Interactive".
+
+// C++ includes.
+#include <math.h>
+
+// Qt includes.
+#include <qwidget.h>
+#include <qtabwidget.h>
+#include <qcheckbox.h>
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qradiobutton.h>
+#include <qslider.h>
+#include <qlabel.h>
+#include <qpopupmenu.h>
+#include <qbuttongroup.h>
+
+// KDE includes.
+#include <dcopclient.h>
+#include <klistview.h>
+#include <kparts/componentfactory.h>
+#include <klineedit.h>
+#include <kurlrequester.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+#include <kgenericfactory.h>
+#include <kstandarddirs.h>
+#include <kaboutdata.h>
+#include <kconfig.h>
+#include <knuminput.h>
+#include <kcombobox.h>
+#include <kinputdialog.h>
+#include <kmessagebox.h>
+#include <kfiledialog.h>
+
+// KTTS includes.
+#include "talkercode.h"
+#include "pluginconf.h"
+#include "filterconf.h"
+#include "testplayer.h"
+#include "player.h"
+#include "selecttalkerdlg.h"
+#include "selectevent.h"
+#include "notify.h"
+#include "utils.h"
+
+// KCMKttsMgr includes.
+#include "kcmkttsmgr.h"
+#include "kcmkttsmgr.moc"
+
+// Some constants.
+// Defaults set when clicking Defaults button.
+const bool embedInSysTrayCheckBoxValue = true;
+const bool showMainWindowOnStartupCheckBoxValue = true;
+
+const bool autostartMgrCheckBoxValue = true;
+const bool autoexitMgrCheckBoxValue = true;
+
+const bool notifyEnableCheckBoxValue = false;
+const bool notifyExcludeEventsWithSoundCheckBoxValue = true;
+
+const bool textPreMsgCheckValue = true;
+const QString textPreMsgValue = i18n("Text interrupted. Message.");
+
+const bool textPreSndCheckValue = false;
+const QString textPreSndValue = "";
+
+const bool textPostMsgCheckValue = true;
+const QString textPostMsgValue = i18n("Resuming text.");
+
+const bool textPostSndCheckValue = false;
+const QString textPostSndValue = "";
+
+const int timeBoxValue = 100;
+
+const bool keepAudioCheckBoxValue = false;
+
+// Make this a plug in.
+typedef KGenericFactory<KCMKttsMgr, QWidget> KCMKttsMgrFactory;
+K_EXPORT_COMPONENT_FACTORY( kcm_kttsd, KCMKttsMgrFactory("kttsd") )
+
+/**
+* Constructor.
+* Makes the list of plug ins.
+* And the languages acording to the plug ins.
+*/
+KCMKttsMgr::KCMKttsMgr(QWidget *parent, const char *name, const QStringList &) :
+ DCOPStub("kttsd", "KSpeech"),
+ DCOPObject("kcmkttsmgr_kspeechsink"),
+ KCModule(KCMKttsMgrFactory::instance(), parent, name)
+{
+ // kdDebug() << "KCMKttsMgr contructor running." << endl;
+
+ // Initialize some variables.
+ m_config = 0;
+ m_jobMgrPart = 0;
+ m_configDlg = 0;
+ m_changed = false;
+ m_suppressConfigChanged = false;
+
+ // Add the KTTS Manager widget
+ QGridLayout *layout = new QGridLayout(this, 0, 0);
+ m_kttsmgrw = new KCMKttsMgrWidget(this, "kttsmgrw");
+ // m_kttsmgrw = new KCMKttsMgrWidget(this);
+ layout->addWidget(m_kttsmgrw, 0, 0);
+
+ // Give buttons icons.
+ // Talkers tab.
+ m_kttsmgrw->higherTalkerPriorityButton->setIconSet(
+ KGlobal::iconLoader()->loadIconSet("up", KIcon::Small));
+ m_kttsmgrw->lowerTalkerPriorityButton->setIconSet(
+ KGlobal::iconLoader()->loadIconSet("down", KIcon::Small));
+ m_kttsmgrw->removeTalkerButton->setIconSet(
+ KGlobal::iconLoader()->loadIconSet("edittrash", KIcon::Small));
+ m_kttsmgrw->configureTalkerButton->setIconSet(
+ KGlobal::iconLoader()->loadIconSet("configure", KIcon::Small));
+
+ // Filters tab.
+ m_kttsmgrw->higherFilterPriorityButton->setIconSet(
+ KGlobal::iconLoader()->loadIconSet("up", KIcon::Small));
+ m_kttsmgrw->lowerFilterPriorityButton->setIconSet(
+ KGlobal::iconLoader()->loadIconSet("down", KIcon::Small));
+ m_kttsmgrw->removeFilterButton->setIconSet(
+ KGlobal::iconLoader()->loadIconSet("edittrash", KIcon::Small));
+ m_kttsmgrw->configureFilterButton->setIconSet(
+ KGlobal::iconLoader()->loadIconSet("configure", KIcon::Small));
+
+ // Notify tab.
+ m_kttsmgrw->notifyActionComboBox->clear();
+ for (int ndx = 0; ndx < NotifyAction::count(); ++ndx)
+ m_kttsmgrw->notifyActionComboBox->insertItem( NotifyAction::actionDisplayName( ndx ) );
+ m_kttsmgrw->notifyPresentComboBox->clear();
+ for (int ndx = 0; ndx < NotifyPresent::count(); ++ndx)
+ m_kttsmgrw->notifyPresentComboBox->insertItem( NotifyPresent::presentDisplayName( ndx ) );
+
+ m_kttsmgrw->notifyRemoveButton->setIconSet(
+ KGlobal::iconLoader()->loadIconSet("edittrash", KIcon::Small));
+ m_kttsmgrw->notifyTestButton->setIconSet(
+ KGlobal::iconLoader()->loadIconSet("speak", KIcon::Small));
+
+ m_kttsmgrw->sinkComboBox->setEditable(false);
+ m_kttsmgrw->pcmComboBox->setEditable(false);
+
+ // Construct a popup menu for the Sentence Boundary Detector buttons on Filter tab.
+ m_sbdPopmenu = new QPopupMenu( m_kttsmgrw, "SbdPopupMenu" );
+ m_sbdPopmenu->insertItem( i18n("&Edit..."), this, SLOT(slot_configureSbdFilter()), 0, sbdBtnEdit );
+ m_sbdPopmenu->insertItem( KGlobal::iconLoader()->loadIconSet("up", KIcon::Small),
+ i18n("U&p"), this, SLOT(slot_higherSbdFilterPriority()), 0, sbdBtnUp );
+ m_sbdPopmenu->insertItem( KGlobal::iconLoader()->loadIconSet("down", KIcon::Small),
+ i18n("Do&wn"), this, SLOT(slot_lowerSbdFilterPriority()), 0, sbdBtnDown );
+ m_sbdPopmenu->insertItem( i18n("&Add..."), this, SLOT(slot_addSbdFilter()), 0, sbdBtnAdd );
+ m_sbdPopmenu->insertItem( i18n("&Remove"), this, SLOT(slot_removeSbdFilter()), 0, sbdBtnRemove );
+ m_kttsmgrw->sbdButton->setPopup( m_sbdPopmenu );
+
+ // If aRts is available, enable its radio button.
+ // Determine if available by loading its plugin. If it fails, not available.
+ TestPlayer* testPlayer = new TestPlayer();
+ Player* player = testPlayer->createPlayerObject(0);
+ if (player)
+ m_kttsmgrw->artsRadioButton->setEnabled(true);
+ else
+ m_kttsmgrw->artsRadioButton->setEnabled(false);
+ delete player;
+ delete testPlayer;
+
+ // If GStreamer is available, enable its radio button.
+ // Determine if available by loading its plugin. If it fails, not available.
+ testPlayer = new TestPlayer();
+ player = testPlayer->createPlayerObject(1);
+ if (player)
+ {
+ m_kttsmgrw->gstreamerRadioButton->setEnabled(true);
+ m_kttsmgrw->sinkLabel->setEnabled(true);
+ m_kttsmgrw->sinkComboBox->setEnabled(true);
+ QStringList sinkList = player->getPluginList("Sink/Audio");
+ // kdDebug() << "KCMKttsMgr::KCMKttsMgr: GStreamer Sink List = " << sinkList << endl;
+ m_kttsmgrw->sinkComboBox->clear();
+ m_kttsmgrw->sinkComboBox->insertStringList(sinkList);
+ }
+ delete player;
+ delete testPlayer;
+
+ // If ALSA is available, enable its radio button.
+ // Determine if available by loading its plugin. If it fails, not available.
+ testPlayer = new TestPlayer();
+ player = testPlayer->createPlayerObject(2);
+ if (player)
+ {
+ m_kttsmgrw->alsaRadioButton->setEnabled(true);
+ m_kttsmgrw->pcmLabel->setEnabled(true);
+ m_kttsmgrw->pcmComboBox->setEnabled(true);
+ QStringList pcmList = player->getPluginList("");
+ pcmList.append("custom");
+ kdDebug() << "KCMKttsMgr::KCMKttsMgr: ALSA pcmList = " << pcmList << endl;
+ m_kttsmgrw->pcmComboBox->clear();
+ m_kttsmgrw->pcmComboBox->insertStringList(pcmList);
+ }
+ delete player;
+ delete testPlayer;
+
+ // If aKode is available, enable its radio button.
+ // Determine if available by loading its plugin. If it fails, not available.
+ testPlayer = new TestPlayer();
+ player = testPlayer->createPlayerObject(3);
+ if (player)
+ {
+ m_kttsmgrw->akodeRadioButton->setEnabled(true);
+ m_kttsmgrw->akodeSinkLabel->setEnabled(true);
+ m_kttsmgrw->akodeComboBox->setEnabled(true);
+ QStringList pcmList = player->getPluginList("");
+ kdDebug() << "KCMKttsMgr::KCMKttsMgr: aKode Sink List = " << pcmList << endl;
+ m_kttsmgrw->akodeComboBox->clear();
+ m_kttsmgrw->akodeComboBox->insertStringList(pcmList);
+ }
+ delete player;
+ delete testPlayer;
+
+ // Set up Keep Audio Path KURLRequestor.
+ m_kttsmgrw->keepAudioPath->setMode(KFile::Directory);
+ m_kttsmgrw->keepAudioPath->setURL(locateLocal("data", "kttsd/audio/"));
+
+ // Object for the KTTSD configuration.
+ m_config = new KConfig("kttsdrc");
+
+ // Load configuration.
+ load();
+
+ // Connect the signals from the KCMKtssMgrWidget to this class.
+
+ // Talker tab.
+ connect(m_kttsmgrw->addTalkerButton, SIGNAL(clicked()),
+ this, SLOT(slot_addTalker()));
+ connect(m_kttsmgrw->higherTalkerPriorityButton, SIGNAL(clicked()),
+ this, SLOT(slot_higherTalkerPriority()));
+ connect(m_kttsmgrw->lowerTalkerPriorityButton, SIGNAL(clicked()),
+ this, SLOT(slot_lowerTalkerPriority()));
+ connect(m_kttsmgrw->removeTalkerButton, SIGNAL(clicked()),
+ this, SLOT(slot_removeTalker()));
+ connect(m_kttsmgrw->configureTalkerButton, SIGNAL(clicked()),
+ this, SLOT(slot_configureTalker()));
+ connect(m_kttsmgrw->talkersList, SIGNAL(selectionChanged()),
+ this, SLOT(updateTalkerButtons()));
+
+ // Filter tab.
+ connect(m_kttsmgrw->addFilterButton, SIGNAL(clicked()),
+ this, SLOT(slot_addNormalFilter()));
+ connect(m_kttsmgrw->higherFilterPriorityButton, SIGNAL(clicked()),
+ this, SLOT(slot_higherNormalFilterPriority()));
+ connect(m_kttsmgrw->lowerFilterPriorityButton, SIGNAL(clicked()),
+ this, SLOT(slot_lowerNormalFilterPriority()));
+ connect(m_kttsmgrw->removeFilterButton, SIGNAL(clicked()),
+ this, SLOT(slot_removeNormalFilter()));
+ connect(m_kttsmgrw->configureFilterButton, SIGNAL(clicked()),
+ this, SLOT(slot_configureNormalFilter()));
+ connect(m_kttsmgrw->filtersList, SIGNAL(selectionChanged()),
+ this, SLOT(updateFilterButtons()));
+ //connect(m_kttsmgrw->filtersList, SIGNAL(stateChanged()),
+ // this, SLOT(configChanged()));
+ connect(m_kttsmgrw->sbdsList, SIGNAL(selectionChanged()),
+ this, SLOT(updateSbdButtons()));
+
+ // Audio tab.
+ connect(m_kttsmgrw->gstreamerRadioButton, SIGNAL(toggled(bool)),
+ this, SLOT(slotGstreamerRadioButton_toggled(bool)));
+ connect(m_kttsmgrw->alsaRadioButton, SIGNAL(toggled(bool)),
+ this, SLOT(slotAlsaRadioButton_toggled(bool)));
+ connect(m_kttsmgrw->pcmComboBox, SIGNAL(activated(int)),
+ this, SLOT(slotPcmComboBox_activated()));
+ connect(m_kttsmgrw->akodeRadioButton, SIGNAL(toggled(bool)),
+ this, SLOT(slotAkodeRadioButton_toggled(bool)));
+ connect(m_kttsmgrw->timeBox, SIGNAL(valueChanged(int)),
+ this, SLOT(timeBox_valueChanged(int)));
+ connect(m_kttsmgrw->timeSlider, SIGNAL(valueChanged(int)),
+ this, SLOT(timeSlider_valueChanged(int)));
+ connect(m_kttsmgrw->timeBox, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
+ connect(m_kttsmgrw->timeSlider, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
+ connect(m_kttsmgrw->keepAudioCheckBox, SIGNAL(toggled(bool)),
+ this, SLOT(keepAudioCheckBox_toggled(bool)));
+ connect(m_kttsmgrw->keepAudioPath, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()));
+
+ // General tab.
+ connect(m_kttsmgrw->enableKttsdCheckBox, SIGNAL(toggled(bool)),
+ SLOT(enableKttsdToggled(bool)));
+
+ // Notify tab.
+ connect(m_kttsmgrw->notifyEnableCheckBox, SIGNAL(toggled(bool)),
+ this, SLOT(slotNotifyEnableCheckBox_toggled(bool)));
+ connect(m_kttsmgrw->notifyExcludeEventsWithSoundCheckBox, SIGNAL(toggled(bool)),
+ this, SLOT(configChanged()));
+ connect(m_kttsmgrw->notifyAddButton, SIGNAL(clicked()),
+ this, SLOT(slotNotifyAddButton_clicked()));
+ connect(m_kttsmgrw->notifyRemoveButton, SIGNAL(clicked()),
+ this, SLOT(slotNotifyRemoveButton_clicked()));
+ connect(m_kttsmgrw->notifyClearButton, SIGNAL(clicked()),
+ this, SLOT(slotNotifyClearButton_clicked()));
+ connect(m_kttsmgrw->notifyLoadButton, SIGNAL(clicked()),
+ this, SLOT(slotNotifyLoadButton_clicked()));
+ connect(m_kttsmgrw->notifySaveButton, SIGNAL(clicked()),
+ this, SLOT(slotNotifySaveButton_clicked()));
+ connect(m_kttsmgrw->notifyListView, SIGNAL(selectionChanged()),
+ this, SLOT(slotNotifyListView_selectionChanged()));
+ connect(m_kttsmgrw->notifyPresentComboBox, SIGNAL(activated(int)),
+ this, SLOT(slotNotifyPresentComboBox_activated(int)));
+ connect(m_kttsmgrw->notifyActionComboBox, SIGNAL(activated(int)),
+ this, SLOT(slotNotifyActionComboBox_activated(int)));
+ connect(m_kttsmgrw->notifyTestButton, SIGNAL(clicked()),
+ this, SLOT(slotNotifyTestButton_clicked()));
+ connect(m_kttsmgrw->notifyMsgLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(slotNotifyMsgLineEdit_textChanged(const QString&)));
+ connect(m_kttsmgrw->notifyTalkerButton, SIGNAL(clicked()),
+ this, SLOT(slotNotifyTalkerButton_clicked()));
+
+ // Others.
+ connect(m_kttsmgrw, SIGNAL( configChanged() ),
+ this, SLOT( configChanged() ) );
+ connect(m_kttsmgrw->mainTab, SIGNAL(currentChanged(QWidget*)),
+ this, SLOT(slotTabChanged()));
+
+ // Connect KTTSD DCOP signals to our slots.
+ if (!connectDCOPSignal("kttsd", "KSpeech",
+ "kttsdStarted()",
+ "kttsdStarted()",
+ false)) kdDebug() << "connectDCOPSignal failed" << endl;
+ connectDCOPSignal("kttsd", "KSpeech",
+ "kttsdExiting()",
+ "kttsdExiting()",
+ false);
+
+ // See if KTTSD is already running, and if so, create jobs tab.
+ if (kapp->dcopClient()->isApplicationRegistered("kttsd"))
+ kttsdStarted();
+ else
+ // Start KTTSD if check box is checked.
+ enableKttsdToggled(m_kttsmgrw->enableKttsdCheckBox->isChecked());
+
+ // Switch to Talkers tab if none configured,
+ // otherwise switch to Jobs tab if it is active.
+ if (m_kttsmgrw->talkersList->childCount() == 0)
+ m_kttsmgrw->mainTab->setCurrentPage(wpTalkers);
+ else if (m_kttsmgrw->enableKttsdCheckBox->isChecked())
+ m_kttsmgrw->mainTab->setCurrentPage(wpJobs);
+}
+
+/**
+* Destructor.
+*/
+KCMKttsMgr::~KCMKttsMgr(){
+ // kdDebug() << "KCMKttsMgr::~KCMKttsMgr: Running" << endl;
+ delete m_config;
+}
+
+/**
+* This method is invoked whenever the module should read its
+* configuration (most of the times from a config file) and update the
+* user interface. This happens when the user clicks the "Reset" button in
+* the control center, to undo all of his changes and restore the currently
+* valid settings. NOTE that this is not called after the modules is loaded,
+* so you probably want to call this method in the constructor.
+*/
+void KCMKttsMgr::load()
+{
+ // kdDebug() << "KCMKttsMgr::load: Running" << endl;
+
+ m_changed = false;
+ // Don't emit changed() signal while loading.
+ m_suppressConfigChanged = true;
+
+ // Set the group general for the configuration of kttsd itself (no plug ins)
+ m_config->setGroup("General");
+
+ // Load the configuration of the text interruption messages and sound
+ m_kttsmgrw->textPreMsgCheck->setChecked(m_config->readBoolEntry("TextPreMsgEnabled", textPreMsgCheckValue));
+ m_kttsmgrw->textPreMsg->setText(m_config->readEntry("TextPreMsg", textPreMsgValue));
+ m_kttsmgrw->textPreMsg->setEnabled(m_kttsmgrw->textPreMsgCheck->isChecked());
+
+ m_kttsmgrw->textPreSndCheck->setChecked(m_config->readBoolEntry("TextPreSndEnabled", textPreSndCheckValue));
+ m_kttsmgrw->textPreSnd->setURL(m_config->readEntry("TextPreSnd", textPreSndValue));
+ m_kttsmgrw->textPreSnd->setEnabled(m_kttsmgrw->textPreSndCheck->isChecked());
+
+ m_kttsmgrw->textPostMsgCheck->setChecked(m_config->readBoolEntry("TextPostMsgEnabled", textPostMsgCheckValue));
+ m_kttsmgrw->textPostMsg->setText(m_config->readEntry("TextPostMsg", textPostMsgValue));
+ m_kttsmgrw->textPostMsg->setEnabled(m_kttsmgrw->textPostMsgCheck->isChecked());
+
+ m_kttsmgrw->textPostSndCheck->setChecked(m_config->readBoolEntry("TextPostSndEnabled", textPostSndCheckValue));
+ m_kttsmgrw->textPostSnd->setURL(m_config->readEntry("TextPostSnd", textPostSndValue));
+ m_kttsmgrw->textPostSnd->setEnabled(m_kttsmgrw->textPostSndCheck->isChecked());
+
+ // Overall settings.
+ m_kttsmgrw->embedInSysTrayCheckBox->setChecked(m_config->readBoolEntry("EmbedInSysTray",
+ m_kttsmgrw->embedInSysTrayCheckBox->isChecked()));
+ m_kttsmgrw->showMainWindowOnStartupCheckBox->setChecked(m_config->readBoolEntry(
+ "ShowMainWindowOnStartup", m_kttsmgrw->showMainWindowOnStartupCheckBox->isChecked()));
+ m_kttsmgrw->showMainWindowOnStartupCheckBox->setEnabled(
+ m_kttsmgrw->embedInSysTrayCheckBox->isChecked());
+
+ m_kttsmgrw->enableKttsdCheckBox->setChecked(m_config->readBoolEntry("EnableKttsd",
+ m_kttsmgrw->enableKttsdCheckBox->isChecked()));
+
+ m_kttsmgrw->autostartMgrCheckBox->setChecked(m_config->readBoolEntry("AutoStartManager", true));
+ m_kttsmgrw->autoexitMgrCheckBox->setChecked(m_config->readBoolEntry("AutoExitManager", true));
+
+ // Notification settings.
+ m_kttsmgrw->notifyEnableCheckBox->setChecked(m_config->readBoolEntry("Notify",
+ m_kttsmgrw->notifyEnableCheckBox->isChecked()));
+ m_kttsmgrw->notifyExcludeEventsWithSoundCheckBox->setChecked(
+ m_config->readBoolEntry("ExcludeEventsWithSound",
+ m_kttsmgrw->notifyExcludeEventsWithSoundCheckBox->isChecked()));
+ slotNotifyClearButton_clicked();
+ loadNotifyEventsFromFile( locateLocal("config", "kttsd_notifyevents.xml"), true );
+ slotNotifyEnableCheckBox_toggled( m_kttsmgrw->notifyEnableCheckBox->isChecked() );
+ // Auto-expand and position on the Default item.
+ QListViewItem* item = m_kttsmgrw->notifyListView->findItem( "default", nlvcEventSrc );
+ if ( item )
+ if ( item->childCount() > 0 ) item = item->firstChild();
+ if ( item ) m_kttsmgrw->notifyListView->ensureItemVisible( item );
+
+ // Audio Output.
+ int audioOutputMethod = 0;
+ if (m_kttsmgrw->gstreamerRadioButton->isChecked()) audioOutputMethod = 1;
+ if (m_kttsmgrw->alsaRadioButton->isChecked()) audioOutputMethod = 2;
+ if (m_kttsmgrw->akodeRadioButton->isChecked()) audioOutputMethod = 3;
+ audioOutputMethod = m_config->readNumEntry("AudioOutputMethod", audioOutputMethod);
+ switch (audioOutputMethod)
+ {
+ case 0:
+ m_kttsmgrw->artsRadioButton->setChecked(true);
+ break;
+ case 1:
+ m_kttsmgrw->gstreamerRadioButton->setChecked(true);
+ break;
+ case 2:
+ m_kttsmgrw->alsaRadioButton->setChecked(true);
+ break;
+ case 3:
+ m_kttsmgrw->akodeRadioButton->setChecked(true);
+ break;
+ }
+ m_kttsmgrw->timeBox->setValue(m_config->readNumEntry("AudioStretchFactor", timeBoxValue));
+ timeBox_valueChanged(m_kttsmgrw->timeBox->value());
+ m_kttsmgrw->keepAudioCheckBox->setChecked(
+ m_config->readBoolEntry("KeepAudio", m_kttsmgrw->keepAudioCheckBox->isChecked()));
+ m_kttsmgrw->keepAudioPath->setURL(
+ m_config->readEntry("KeepAudioPath",
+ m_kttsmgrw->keepAudioPath->url()));
+ m_kttsmgrw->keepAudioPath->setEnabled(m_kttsmgrw->keepAudioCheckBox->isChecked());
+
+ // Last plugin ID. Used to generate a new ID for an added talker.
+ m_lastTalkerID = 0;
+
+ // Last filter ID. Used to generate a new ID for an added filter.
+ m_lastFilterID = 0;
+
+ // Dictionary mapping languages to language codes.
+ m_languagesToCodes.clear();
+
+ // Load existing Talkers into the listview.
+ m_kttsmgrw->talkersList->clear();
+ m_kttsmgrw->talkersList->setSortColumn(-1);
+ QStringList talkerIDsList = m_config->readListEntry("TalkerIDs", ',');
+ if (!talkerIDsList.isEmpty())
+ {
+ QListViewItem* talkerItem = 0;
+ QStringList::ConstIterator itEnd = talkerIDsList.constEnd();
+ for (QStringList::ConstIterator it = talkerIDsList.constBegin(); it != itEnd; ++it)
+ {
+ QString talkerID = *it;
+ // kdDebug() << "KCMKttsMgr::load: talkerID = " << talkerID << endl;
+ m_config->setGroup(QString("Talker_") + talkerID);
+ QString talkerCode = m_config->readEntry("TalkerCode");
+ QString fullLanguageCode;
+ talkerCode = TalkerCode::normalizeTalkerCode(talkerCode, fullLanguageCode);
+ QString language = TalkerCode::languageCodeToLanguage(fullLanguageCode);
+ QString desktopEntryName = m_config->readEntry("DesktopEntryName", QString::null);
+ // If a DesktopEntryName is not in the config file, it was configured before
+ // we started using them, when we stored translated plugin names instead.
+ // Try to convert the translated plugin name to a DesktopEntryName.
+ // DesktopEntryNames are better because user can change their desktop language
+ // and DesktopEntryName won't change.
+ QString synthName;
+ if (desktopEntryName.isEmpty())
+ {
+ synthName = m_config->readEntry("PlugIn", QString::null);
+ // See if the translated name will untranslate. If not, well, sorry.
+ desktopEntryName = TalkerCode::TalkerNameToDesktopEntryName(synthName);
+ // Record the DesktopEntryName from now on.
+ if (!desktopEntryName.isEmpty()) m_config->writeEntry("DesktopEntryName", desktopEntryName);
+ }
+ synthName = TalkerCode::TalkerDesktopEntryNameToName(desktopEntryName);
+ if (!synthName.isEmpty())
+ {
+ // kdDebug() << "KCMKttsMgr::load: talkerCode = " << talkerCode << endl;
+ if (talkerItem)
+ talkerItem = new KListViewItem(m_kttsmgrw->talkersList, talkerItem,
+ talkerID, language, synthName);
+ else
+ talkerItem = new KListViewItem(m_kttsmgrw->talkersList,
+ talkerID, language, synthName);
+ updateTalkerItem(talkerItem, talkerCode);
+ m_languagesToCodes[language] = fullLanguageCode;
+ if (talkerID.toInt() > m_lastTalkerID) m_lastTalkerID = talkerID.toInt();
+ }
+ }
+ }
+
+ // Query for all the KCMKTTSD SynthPlugins and store the list in offers.
+ KTrader::OfferList offers = KTrader::self()->query("KTTSD/SynthPlugin");
+
+ // Iterate thru the possible plug ins getting their language support codes.
+ for(unsigned int i=0; i < offers.count() ; ++i)
+ {
+ QString synthName = offers[i]->name();
+ QStringList languageCodes = offers[i]->property("X-KDE-Languages").toStringList();
+ // Add language codes to the language-to-language code map.
+ QStringList::ConstIterator endLanguages(languageCodes.constEnd());
+ for( QStringList::ConstIterator it = languageCodes.constBegin(); it != endLanguages; ++it )
+ {
+ QString language = TalkerCode::languageCodeToLanguage(*it);
+ m_languagesToCodes[language] = *it;
+ }
+
+ // All plugins support "Other".
+ // TODO: Eventually, this should not be necessary, since all plugins will know
+ // the languages they support and report them in call to getSupportedLanguages().
+ if (!languageCodes.contains("other")) languageCodes.append("other");
+
+ // Add supported language codes to synthesizer-to-language map.
+ m_synthToLangMap[synthName] = languageCodes;
+ }
+
+ // Add "Other" language.
+ m_languagesToCodes[i18n("Other")] = "other";
+
+ // Load Filters.
+ QListViewItem* filterItem = 0;
+ m_kttsmgrw->filtersList->clear();
+ m_kttsmgrw->sbdsList->clear();
+ m_kttsmgrw->filtersList->setSortColumn(-1);
+ m_kttsmgrw->sbdsList->setSortColumn(-1);
+ m_config->setGroup("General");
+ QStringList filterIDsList = m_config->readListEntry("FilterIDs", ',');
+ // kdDebug() << "KCMKttsMgr::load: FilterIDs = " << filterIDsList << endl;
+ if (!filterIDsList.isEmpty())
+ {
+ QStringList::ConstIterator itEnd = filterIDsList.constEnd();
+ for (QStringList::ConstIterator it = filterIDsList.constBegin(); it != itEnd; ++it)
+ {
+ QString filterID = *it;
+ // kdDebug() << "KCMKttsMgr::load: filterID = " << filterID << endl;
+ m_config->setGroup("Filter_" + filterID);
+ QString desktopEntryName = m_config->readEntry("DesktopEntryName", QString::null);
+ // If a DesktopEntryName is not in the config file, it was configured before
+ // we started using them, when we stored translated plugin names instead.
+ // Try to convert the translated plugin name to a DesktopEntryName.
+ // DesktopEntryNames are better because user can change their desktop language
+ // and DesktopEntryName won't change.
+ QString filterPlugInName;
+ if (desktopEntryName.isEmpty())
+ {
+ filterPlugInName = m_config->readEntry("PlugInName", QString::null);
+ // See if the translated name will untranslate. If not, well, sorry.
+ desktopEntryName = FilterNameToDesktopEntryName(filterPlugInName);
+ // Record the DesktopEntryName from now on.
+ if (!desktopEntryName.isEmpty()) m_config->writeEntry("DesktopEntryName", desktopEntryName);
+ }
+ filterPlugInName = FilterDesktopEntryNameToName(desktopEntryName);
+ if (!filterPlugInName.isEmpty())
+ {
+ QString userFilterName = m_config->readEntry("UserFilterName", filterPlugInName);
+ bool multiInstance = m_config->readBoolEntry("MultiInstance", false);
+ // Determine if this filter is a Sentence Boundary Detector (SBD).
+ bool isSbd = m_config->readBoolEntry("IsSBD", false);
+ bool checked = m_config->readBoolEntry("Enabled", false);
+ if (isSbd)
+ {
+ filterItem = m_kttsmgrw->sbdsList->lastChild();
+ if (!filterItem)
+ filterItem = new KListViewItem(m_kttsmgrw->sbdsList,
+ userFilterName, filterID, filterPlugInName);
+ else
+ filterItem = new KListViewItem(m_kttsmgrw->sbdsList, filterItem,
+ userFilterName, filterID, filterPlugInName);
+ } else {
+ filterItem = m_kttsmgrw->filtersList->lastChild();
+ if (!filterItem)
+ filterItem = new KttsCheckListItem(m_kttsmgrw->filtersList,
+ userFilterName, QCheckListItem::CheckBox, this);
+ else
+ filterItem = new KttsCheckListItem(m_kttsmgrw->filtersList, filterItem,
+ userFilterName, QCheckListItem::CheckBox, this);
+ dynamic_cast<QCheckListItem*>(filterItem)->setOn(checked);
+ }
+ filterItem->setText(flvcFilterID, filterID);
+ filterItem->setText(flvcPlugInName, filterPlugInName);
+ if (multiInstance)
+ filterItem->setText(flvcMultiInstance, "T");
+ else
+ filterItem->setText(flvcMultiInstance, "F");
+ if (filterID.toInt() > m_lastFilterID) m_lastFilterID = filterID.toInt();
+ }
+ }
+ }
+
+ // Add at least one unchecked instance of each available filter plugin if there is
+ // not already at least one instance and the filter can autoconfig itself.
+ offers = KTrader::self()->query("KTTSD/FilterPlugin");
+ for (unsigned int i=0; i < offers.count() ; ++i)
+ {
+ QString filterPlugInName = offers[i]->name();
+ QString desktopEntryName = FilterNameToDesktopEntryName(filterPlugInName);
+ if (!desktopEntryName.isEmpty() && (countFilterPlugins(filterPlugInName) == 0))
+ {
+ // Must load plugin to determine if it supports multiple instances
+ // and to see if it can autoconfigure itself.
+ KttsFilterConf* filterPlugIn = loadFilterPlugin(desktopEntryName);
+ if (filterPlugIn)
+ {
+ ++m_lastFilterID;
+ QString filterID = QString::number(m_lastFilterID);
+ QString groupName = "Filter_" + filterID;
+ filterPlugIn->load(m_config, groupName);
+ QString userFilterName = filterPlugIn->userPlugInName();
+ if (!userFilterName.isEmpty())
+ {
+ kdDebug() << "KCMKttsMgr::load: auto-configuring filter " << userFilterName << endl;
+ // Determine if plugin is an SBD filter.
+ bool multiInstance = filterPlugIn->supportsMultiInstance();
+ bool isSbd = filterPlugIn->isSBD();
+ if (isSbd)
+ {
+ filterItem = m_kttsmgrw->sbdsList->lastChild();
+ if (!filterItem)
+ filterItem = new KListViewItem(m_kttsmgrw->sbdsList,
+ userFilterName, filterID, filterPlugInName);
+ else
+ filterItem = new KListViewItem(m_kttsmgrw->sbdsList, filterItem,
+ userFilterName, filterID, filterPlugInName);
+ } else {
+ filterItem = m_kttsmgrw->filtersList->lastChild();
+ if (!filterItem)
+ filterItem = new KttsCheckListItem(m_kttsmgrw->filtersList,
+ userFilterName, QCheckListItem::CheckBox, this);
+ else
+ filterItem = new KttsCheckListItem(m_kttsmgrw->filtersList, filterItem,
+ userFilterName, QCheckListItem::CheckBox, this);
+ dynamic_cast<QCheckListItem*>(filterItem)->setOn(false);
+ }
+ filterItem->setText(flvcFilterID, filterID);
+ filterItem->setText(flvcPlugInName, filterPlugInName);
+ if (multiInstance)
+ filterItem->setText(flvcMultiInstance, "T");
+ else
+ filterItem->setText(flvcMultiInstance, "F");
+ m_config->setGroup(groupName);
+ filterPlugIn->save(m_config, groupName);
+ m_config->setGroup(groupName);
+ m_config->writeEntry("DesktopEntryName", desktopEntryName);
+ m_config->writeEntry("UserFilterName", userFilterName);
+ m_config->writeEntry("Enabled", isSbd);
+ m_config->writeEntry("MultiInstance", multiInstance);
+ m_config->writeEntry("IsSBD", isSbd);
+ filterIDsList.append(filterID);
+ } else m_lastFilterID--;
+ } else
+ kdDebug() << "KCMKttsMgr::load: Unable to load filter plugin " << filterPlugInName
+ << " DesktopEntryName " << desktopEntryName << endl;
+ delete filterPlugIn;
+ }
+ }
+ // Rewrite list of FilterIDs in case we added any.
+ QString filterIDs = filterIDsList.join(",");
+ m_config->setGroup("General");
+ m_config->writeEntry("FilterIDs", filterIDs);
+ m_config->sync();
+
+ // Uncheck and disable KTTSD checkbox if no Talkers are configured.
+ if (m_kttsmgrw->talkersList->childCount() == 0)
+ {
+ m_kttsmgrw->enableKttsdCheckBox->setChecked(false);
+ m_kttsmgrw->enableKttsdCheckBox->setEnabled(false);
+ enableKttsdToggled(false);
+ }
+
+ // Enable ShowMainWindowOnStartup checkbox based on EmbedInSysTray checkbox.
+ m_kttsmgrw->showMainWindowOnStartupCheckBox->setEnabled(
+ m_kttsmgrw->embedInSysTrayCheckBox->isChecked());
+
+ // GStreamer settings.
+ m_config->setGroup("GStreamerPlayer");
+ KttsUtils::setCbItemFromText(m_kttsmgrw->sinkComboBox, m_config->readEntry("SinkName", "osssink"));
+
+ // ALSA settings.
+ m_config->setGroup("ALSAPlayer");
+ KttsUtils::setCbItemFromText(m_kttsmgrw->pcmComboBox, m_config->readEntry("PcmName", "default"));
+ m_kttsmgrw->pcmCustom->setText(m_config->readEntry("CustomPcmName", ""));
+
+ // aKode settings.
+ m_config->setGroup("aKodePlayer");
+ KttsUtils::setCbItemFromText(m_kttsmgrw->akodeComboBox, m_config->readEntry("SinkName", "auto"));
+
+ // Update controls based on new states.
+ slotNotifyListView_selectionChanged();
+ updateTalkerButtons();
+ updateFilterButtons();
+ updateSbdButtons();
+ slotGstreamerRadioButton_toggled(m_kttsmgrw->gstreamerRadioButton->isChecked());
+ slotAlsaRadioButton_toggled(m_kttsmgrw->alsaRadioButton->isChecked());
+ slotAkodeRadioButton_toggled(m_kttsmgrw->akodeRadioButton->isChecked());
+
+ m_changed = false;
+ m_suppressConfigChanged = false;
+}
+
+/**
+* This function gets called when the user wants to save the settings in
+* the user interface, updating the config files or wherever the
+* configuration is stored. The method is called when the user clicks "Apply"
+* or "Ok".
+*/
+void KCMKttsMgr::save()
+{
+ // kdDebug() << "KCMKttsMgr::save: Running" << endl;
+ m_changed = false;
+
+ // Clean up config.
+ m_config->deleteGroup("General");
+
+ // Set the group general for the configuration of kttsd itself (no plug ins)
+ m_config->setGroup("General");
+
+ // Set text interrumption messages and paths
+ m_config->writeEntry("TextPreMsgEnabled", m_kttsmgrw->textPreMsgCheck->isChecked());
+ m_config->writeEntry("TextPreMsg", m_kttsmgrw->textPreMsg->text());
+
+ m_config->writeEntry("TextPreSndEnabled", m_kttsmgrw->textPreSndCheck->isChecked());
+ m_config->writeEntry("TextPreSnd", PlugInConf::realFilePath(m_kttsmgrw->textPreSnd->url()));
+
+ m_config->writeEntry("TextPostMsgEnabled", m_kttsmgrw->textPostMsgCheck->isChecked());
+ m_config->writeEntry("TextPostMsg", m_kttsmgrw->textPostMsg->text());
+
+ m_config->writeEntry("TextPostSndEnabled", m_kttsmgrw->textPostSndCheck->isChecked());
+ m_config->writeEntry("TextPostSnd", PlugInConf::realFilePath(m_kttsmgrw->textPostSnd->url()));
+
+ // Overall settings.
+ m_config->writeEntry("EmbedInSysTray", m_kttsmgrw->embedInSysTrayCheckBox->isChecked());
+ m_config->writeEntry("ShowMainWindowOnStartup",
+ m_kttsmgrw->showMainWindowOnStartupCheckBox->isChecked());
+ m_config->writeEntry("AutoStartManager", m_kttsmgrw->autostartMgrCheckBox->isChecked());
+ m_config->writeEntry("AutoExitManager", m_kttsmgrw->autoexitMgrCheckBox->isChecked());
+
+ // Uncheck and disable KTTSD checkbox if no Talkers are configured.
+ // Enable checkbox if at least one Talker is configured.
+ bool enableKttsdWasToggled = false;
+ if (m_kttsmgrw->talkersList->childCount() == 0)
+ {
+ enableKttsdWasToggled = m_kttsmgrw->enableKttsdCheckBox->isChecked();
+ m_kttsmgrw->enableKttsdCheckBox->setChecked(false);
+ m_kttsmgrw->enableKttsdCheckBox->setEnabled(false);
+ // Might as well zero LastTalkerID as well.
+ m_lastTalkerID = 0;
+ }
+ else
+ m_kttsmgrw->enableKttsdCheckBox->setEnabled(true);
+
+ m_config->writeEntry("EnableKttsd", m_kttsmgrw->enableKttsdCheckBox->isChecked());
+
+ // Notification settings.
+ m_config->writeEntry("Notify", m_kttsmgrw->notifyEnableCheckBox->isChecked());
+ m_config->writeEntry("ExcludeEventsWithSound",
+ m_kttsmgrw->notifyExcludeEventsWithSoundCheckBox->isChecked());
+ saveNotifyEventsToFile( locateLocal("config", "kttsd_notifyevents.xml") );
+
+ // Audio Output.
+ int audioOutputMethod = 0;
+ if (m_kttsmgrw->gstreamerRadioButton->isChecked()) audioOutputMethod = 1;
+ if (m_kttsmgrw->alsaRadioButton->isChecked()) audioOutputMethod = 2;
+ if (m_kttsmgrw->akodeRadioButton->isChecked()) audioOutputMethod = 3;
+ m_config->writeEntry("AudioOutputMethod", audioOutputMethod);
+ m_config->writeEntry("AudioStretchFactor", m_kttsmgrw->timeBox->value());
+ m_config->writeEntry("KeepAudio", m_kttsmgrw->keepAudioCheckBox->isChecked());
+ m_config->writeEntry("KeepAudioPath", m_kttsmgrw->keepAudioPath->url());
+
+ // Get ordered list of all talker IDs.
+ QStringList talkerIDsList;
+ QListViewItem* talkerItem = m_kttsmgrw->talkersList->firstChild();
+ while (talkerItem)
+ {
+ QListViewItem* nextTalkerItem = talkerItem->itemBelow();
+ QString talkerID = talkerItem->text(tlvcTalkerID);
+ talkerIDsList.append(talkerID);
+ talkerItem = nextTalkerItem;
+ }
+ QString talkerIDs = talkerIDsList.join(",");
+ m_config->writeEntry("TalkerIDs", talkerIDs);
+
+ // Erase obsolete Talker_nn sections.
+ QStringList groupList = m_config->groupList();
+ int groupListCount = groupList.count();
+ for (int groupNdx = 0; groupNdx < groupListCount; ++groupNdx)
+ {
+ QString groupName = groupList[groupNdx];
+ if (groupName.left(7) == "Talker_")
+ {
+ QString groupTalkerID = groupName.mid(7);
+ if (!talkerIDsList.contains(groupTalkerID)) m_config->deleteGroup(groupName);
+ }
+ }
+
+ // Get ordered list of all filter IDs. Record enabled state of each filter.
+ QStringList filterIDsList;
+ QListViewItem* filterItem = m_kttsmgrw->filtersList->firstChild();
+ while (filterItem)
+ {
+ QListViewItem* nextFilterItem = filterItem->itemBelow();
+ QString filterID = filterItem->text(flvcFilterID);
+ filterIDsList.append(filterID);
+ bool checked = dynamic_cast<QCheckListItem*>(filterItem)->isOn();
+ m_config->setGroup("Filter_" + filterID);
+ m_config->writeEntry("Enabled", checked);
+ m_config->writeEntry("IsSBD", false);
+ filterItem = nextFilterItem;
+ }
+ QListViewItem* sbdItem = m_kttsmgrw->sbdsList->firstChild();
+ while (sbdItem)
+ {
+ QListViewItem* nextSbdItem = sbdItem->itemBelow();
+ QString filterID = sbdItem->text(slvcFilterID);
+ filterIDsList.append(filterID);
+ m_config->setGroup("Filter_" + filterID);
+ m_config->writeEntry("Enabled", true);
+ m_config->writeEntry("IsSBD", true);
+ sbdItem = nextSbdItem;
+ }
+ QString filterIDs = filterIDsList.join(",");
+ m_config->setGroup("General");
+ m_config->writeEntry("FilterIDs", filterIDs);
+
+ // Erase obsolete Filter_nn sections.
+ for (int groupNdx = 0; groupNdx < groupListCount; ++groupNdx)
+ {
+ QString groupName = groupList[groupNdx];
+ if (groupName.left(7) == "Filter_")
+ {
+ QString groupFilterID = groupName.mid(7);
+ if (!filterIDsList.contains(groupFilterID)) m_config->deleteGroup(groupName);
+ }
+ }
+
+ // GStreamer settings.
+ m_config->setGroup("GStreamerPlayer");
+ m_config->writeEntry("SinkName", m_kttsmgrw->sinkComboBox->currentText());
+
+ // ALSA settings.
+ m_config->setGroup("ALSAPlayer");
+ m_config->writeEntry("PcmName", m_kttsmgrw->pcmComboBox->currentText());
+ m_config->writeEntry("CustomPcmName", m_kttsmgrw->pcmCustom->text());
+
+ // aKode settings.
+ m_config->setGroup("aKodePlayer");
+ m_config->writeEntry("SinkName", m_kttsmgrw->akodeComboBox->currentText());
+
+ m_config->sync();
+
+ // If we automatically unchecked the Enable KTTSD checkbox, stop KTTSD.
+ if (enableKttsdWasToggled)
+ enableKttsdToggled(false);
+ else
+ {
+ // If KTTSD is running, reinitialize it.
+ DCOPClient *client = kapp->dcopClient();
+ bool kttsdRunning = (client->isApplicationRegistered("kttsd"));
+ if (kttsdRunning)
+ {
+ kdDebug() << "Restarting KTTSD" << endl;
+ QByteArray data;
+ client->send("kttsd", "KSpeech", "reinit()", data);
+ }
+ }
+}
+
+void KCMKttsMgr::slotTabChanged()
+{
+ setButtons(buttons());
+ int currentPageIndex = m_kttsmgrw->mainTab->currentPageIndex();
+ if (currentPageIndex == wpJobs)
+ {
+ if (m_changed)
+ {
+ KMessageBox::information(m_kttsmgrw,
+ i18n("You have made changes to the configuration but have not saved them yet. "
+ "Click Apply to save the changes or Cancel to abandon the changes."));
+ }
+ }
+}
+
+/**
+* This function is called to set the settings in the module to sensible
+* default values. It gets called when hitting the "Default" button. The
+* default values should probably be the same as the ones the application
+* uses when started without a config file.
+*/
+void KCMKttsMgr::defaults() {
+ // kdDebug() << "Running: KCMKttsMgr::defaults: Running"<< endl;
+
+ int currentPageIndex = m_kttsmgrw->mainTab->currentPageIndex();
+ bool changed = false;
+ switch (currentPageIndex)
+ {
+ case wpGeneral:
+ if (m_kttsmgrw->embedInSysTrayCheckBox->isChecked() != embedInSysTrayCheckBoxValue)
+ {
+ changed = true;
+ m_kttsmgrw->embedInSysTrayCheckBox->setChecked(embedInSysTrayCheckBoxValue);
+ }
+ if (m_kttsmgrw->showMainWindowOnStartupCheckBox->isChecked() !=
+ showMainWindowOnStartupCheckBoxValue)
+ {
+ changed = true;
+ m_kttsmgrw->showMainWindowOnStartupCheckBox->setChecked(
+ showMainWindowOnStartupCheckBoxValue);
+ }
+ if (m_kttsmgrw->autostartMgrCheckBox->isChecked() != autostartMgrCheckBoxValue)
+ {
+ changed = true;
+ m_kttsmgrw->autostartMgrCheckBox->setChecked(
+ autostartMgrCheckBoxValue);
+ }
+ if (m_kttsmgrw->autoexitMgrCheckBox->isChecked() != autoexitMgrCheckBoxValue)
+ {
+ changed = true;
+ m_kttsmgrw->autoexitMgrCheckBox->setChecked(
+ autoexitMgrCheckBoxValue);
+ }
+ break;
+
+ case wpNotify:
+ if (m_kttsmgrw->notifyEnableCheckBox->isChecked() != notifyEnableCheckBoxValue)
+ {
+ changed = true;
+ m_kttsmgrw->notifyEnableCheckBox->setChecked(notifyEnableCheckBoxValue);
+ m_kttsmgrw->notifyGroup->setChecked( notifyEnableCheckBoxValue );
+ }
+ if (m_kttsmgrw->notifyExcludeEventsWithSoundCheckBox->isChecked() !=
+ notifyExcludeEventsWithSoundCheckBoxValue )
+ {
+ changed = true;
+ m_kttsmgrw->notifyExcludeEventsWithSoundCheckBox->setChecked(
+ notifyExcludeEventsWithSoundCheckBoxValue );
+ }
+ break;
+
+ case wpInterruption:
+ if (m_kttsmgrw->textPreMsgCheck->isChecked() != textPreMsgCheckValue)
+ {
+ changed = true;
+ m_kttsmgrw->textPreMsgCheck->setChecked(textPreMsgCheckValue);
+ }
+ if (m_kttsmgrw->textPreMsg->text() != i18n(textPreMsgValue.utf8()))
+ {
+ changed = true;
+ m_kttsmgrw->textPreMsg->setText(i18n(textPreMsgValue.utf8()));
+ }
+ if (m_kttsmgrw->textPreSndCheck->isChecked() != textPreSndCheckValue)
+ {
+ changed = true;
+ m_kttsmgrw->textPreSndCheck->setChecked(textPreSndCheckValue);
+ }
+ if (m_kttsmgrw->textPreSnd->url() != textPreSndValue)
+ {
+ changed = true;
+ m_kttsmgrw->textPreSnd->setURL(textPreSndValue);
+ }
+ if (m_kttsmgrw->textPostMsgCheck->isChecked() != textPostMsgCheckValue)
+ {
+ changed = true;
+ m_kttsmgrw->textPostMsgCheck->setChecked(textPostMsgCheckValue);
+ }
+ if (m_kttsmgrw->textPostMsg->text() != i18n(textPostMsgValue.utf8()))
+ {
+ changed = true;
+ m_kttsmgrw->textPostMsg->setText(i18n(textPostMsgValue.utf8()));
+ }
+ if (m_kttsmgrw->textPostSndCheck->isChecked() != textPostSndCheckValue)
+ {
+ changed = true;
+ m_kttsmgrw->textPostSndCheck->setChecked(textPostSndCheckValue);
+ }
+ if (m_kttsmgrw->textPostSnd->url() != textPostSndValue)
+ {
+ changed = true;
+ m_kttsmgrw->textPostSnd->setURL(textPostSndValue);
+ }
+ break;
+
+ case wpAudio:
+ if (!m_kttsmgrw->artsRadioButton->isChecked())
+ {
+ changed = true;
+ m_kttsmgrw->artsRadioButton->setChecked(true);
+ }
+ if (m_kttsmgrw->timeBox->value() != timeBoxValue)
+ {
+ changed = true;
+ m_kttsmgrw->timeBox->setValue(timeBoxValue);
+ }
+ if (m_kttsmgrw->keepAudioCheckBox->isChecked() !=
+ keepAudioCheckBoxValue)
+ {
+ changed = true;
+ m_kttsmgrw->keepAudioCheckBox->setChecked(keepAudioCheckBoxValue);
+ }
+ if (m_kttsmgrw->keepAudioPath->url() != locateLocal("data", "kttsd/audio/"))
+ {
+ changed = true;
+ m_kttsmgrw->keepAudioPath->setURL(locateLocal("data", "kttsd/audio/"));
+ }
+ m_kttsmgrw->keepAudioPath->setEnabled(m_kttsmgrw->keepAudioCheckBox->isEnabled());
+ }
+ if (changed) configChanged();
+}
+
+/**
+* This is a static method which gets called to realize the modules settings
+* during the startup of KDE. NOTE that most modules do not implement this
+* method, but modules like the keyboard and mouse modules, which directly
+* interact with the X-server, need this method. As this method is static,
+* it can avoid to create an instance of the user interface, which is often
+* not needed in this case.
+*/
+void KCMKttsMgr::init(){
+ // kdDebug() << "KCMKttsMgr::init: Running" << endl;
+}
+
+/**
+* The control center calls this function to decide which buttons should
+* be displayed. For example, it does not make sense to display an "Apply"
+* button for one of the information modules. The value returned can be set by
+* modules using setButtons.
+*/
+int KCMKttsMgr::buttons() {
+ // kdDebug() << "KCMKttsMgr::buttons: Running"<< endl;
+ return KCModule::Ok|KCModule::Apply|KCModule::Help|KCModule::Default;
+}
+
+/**
+* This function returns the small quickhelp.
+* That is displayed in the sidebar in the KControl
+*/
+QString KCMKttsMgr::quickHelp() const{
+ // kdDebug() << "KCMKttsMgr::quickHelp: Running"<< endl;
+ return i18n(
+ "<h1>Text-to-Speech</h1>"
+ "<p>This is the configuration for the text-to-speech dcop service</p>"
+ "<p>This allows other applications to access text-to-speech resources</p>"
+ "<p>Be sure to configure a default language for the language you are using as this will be the language used by most of the applications</p>");
+}
+
+const KAboutData* KCMKttsMgr::aboutData() const{
+ KAboutData *about =
+ new KAboutData(I18N_NOOP("kttsd"), I18N_NOOP("KCMKttsMgr"),
+ 0, 0, KAboutData::License_GPL,
+ I18N_NOOP("(c) 2002, José Pablo Ezequiel Fernández"));
+
+ about->addAuthor("José Pablo Ezequiel Fernández", I18N_NOOP("Author") , "pupeno@kde.org");
+ about->addAuthor("Gary Cramblitt", I18N_NOOP("Maintainer") , "garycramblitt@comcast.net");
+ about->addAuthor("Olaf Schmidt", I18N_NOOP("Contributor"), "ojschmidt@kde.org");
+ about->addAuthor("Paul Giannaros", I18N_NOOP("Contributor"), "ceruleanblaze@gmail.com");
+
+ return about;
+}
+
+/**
+* Loads the configuration plug in for a named talker plug in and type.
+* @param name DesktopEntryName of the Synthesizer.
+* @return Pointer to the configuration plugin for the Talker.
+*/
+PlugInConf* KCMKttsMgr::loadTalkerPlugin(const QString& name)
+{
+ // kdDebug() << "KCMKttsMgr::loadPlugin: Running"<< endl;
+
+ // Find the plugin.
+ KTrader::OfferList offers = KTrader::self()->query("KTTSD/SynthPlugin",
+ QString("DesktopEntryName == '%1'").arg(name));
+
+ if (offers.count() == 1)
+ {
+ // When the entry is found, load the plug in
+ // First create a factory for the library
+ KLibFactory *factory = KLibLoader::self()->factory(offers[0]->library().latin1());
+ if(factory){
+ // If the factory is created successfully, instantiate the PlugInConf class for the
+ // specific plug in to get the plug in configuration object.
+ PlugInConf *plugIn = KParts::ComponentFactory::createInstanceFromLibrary<PlugInConf>(
+ offers[0]->library().latin1(), NULL, offers[0]->library().latin1());
+ if(plugIn){
+ // If everything went ok, return the plug in pointer.
+ return plugIn;
+ } else {
+ // Something went wrong, returning null.
+ kdDebug() << "KCMKttsMgr::loadTalkerPlugin: Unable to instantiate PlugInConf class for plugin " << name << endl;
+ return NULL;
+ }
+ } else {
+ // Something went wrong, returning null.
+ kdDebug() << "KCMKttsMgr::loadTalkerPlugin: Unable to create Factory object for plugin "
+ << name << endl;
+ return NULL;
+ }
+ }
+ // The plug in was not found (unexpected behaviour, returns null).
+ kdDebug() << "KCMKttsMgr::loadTalkerPlugin: KTrader did not return an offer for plugin "
+ << name << endl;
+ return NULL;
+}
+
+/**
+ * Loads the configuration plug in for a named filter plug in.
+ * @param plugInName DesktopEntryName of the plugin.
+ * @return Pointer to the configuration plugin for the Filter.
+ */
+KttsFilterConf* KCMKttsMgr::loadFilterPlugin(const QString& plugInName)
+{
+ // kdDebug() << "KCMKttsMgr::loadPlugin: Running"<< endl;
+
+ // Find the plugin.
+ KTrader::OfferList offers = KTrader::self()->query("KTTSD/FilterPlugin",
+ QString("DesktopEntryName == '%1'").arg(plugInName));
+
+ if (offers.count() == 1)
+ {
+ // When the entry is found, load the plug in
+ // First create a factory for the library
+ KLibFactory *factory = KLibLoader::self()->factory(offers[0]->library().latin1());
+ if(factory){
+ // If the factory is created successfully, instantiate the KttsFilterConf class for the
+ // specific plug in to get the plug in configuration object.
+ int errorNo = 0;
+ KttsFilterConf *plugIn =
+ KParts::ComponentFactory::createInstanceFromLibrary<KttsFilterConf>(
+ offers[0]->library().latin1(), NULL, offers[0]->library().latin1(),
+ QStringList(), &errorNo);
+ if(plugIn){
+ // If everything went ok, return the plug in pointer.
+ return plugIn;
+ } else {
+ // Something went wrong, returning null.
+ kdDebug() << "KCMKttsMgr::loadFilterPlugin: Unable to instantiate KttsFilterConf class for plugin " << plugInName << " error: " << errorNo << endl;
+ return NULL;
+ }
+ } else {
+ // Something went wrong, returning null.
+ kdDebug() << "KCMKttsMgr::loadFilterPlugin: Unable to create Factory object for plugin " << plugInName << endl;
+ return NULL;
+ }
+ }
+ // The plug in was not found (unexpected behaviour, returns null).
+ kdDebug() << "KCMKttsMgr::loadFilterPlugin: KTrader did not return an offer for plugin " << plugInName << endl;
+ return NULL;
+}
+
+/**
+* Given an item in the talker listview and a talker code, sets the columns of the item.
+* @param talkerItem QListViewItem.
+* @param talkerCode Talker Code.
+*/
+void KCMKttsMgr::updateTalkerItem(QListViewItem* talkerItem, const QString &talkerCode)
+{
+ TalkerCode parsedTalkerCode(talkerCode);
+ QString fullLanguageCode = parsedTalkerCode.fullLanguageCode();
+ if (!fullLanguageCode.isEmpty())
+ {
+ QString language = TalkerCode::languageCodeToLanguage(fullLanguageCode);
+ if (!language.isEmpty())
+ {
+ m_languagesToCodes[language] = fullLanguageCode;
+ talkerItem->setText(tlvcLanguage, language);
+ }
+ }
+ // Don't update the Synthesizer name with plugInName. The former is a translated
+ // name; the latter an English name.
+ // if (!plugInName.isEmpty()) talkerItem->setText(tlvcSynthName, plugInName);
+ if (!parsedTalkerCode.voice().isEmpty())
+ talkerItem->setText(tlvcVoice, parsedTalkerCode.voice());
+ if (!parsedTalkerCode.gender().isEmpty())
+ talkerItem->setText(tlvcGender, TalkerCode::translatedGender(parsedTalkerCode.gender()));
+ if (!parsedTalkerCode.volume().isEmpty())
+ talkerItem->setText(tlvcVolume, TalkerCode::translatedVolume(parsedTalkerCode.volume()));
+ if (!parsedTalkerCode.rate().isEmpty())
+ talkerItem->setText(tlvcRate, TalkerCode::translatedRate(parsedTalkerCode.rate()));
+}
+
+/**
+ * Add a talker.
+ */
+void KCMKttsMgr::slot_addTalker()
+{
+ AddTalker* addTalkerWidget = new AddTalker(m_synthToLangMap, this, "AddTalker_widget");
+ KDialogBase* dlg = new KDialogBase(
+ KDialogBase::Swallow,
+ i18n("Add Talker"),
+ KDialogBase::Help|KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Cancel,
+ m_kttsmgrw,
+ "AddTalker_dlg",
+ true,
+ true);
+ dlg->setMainWidget(addTalkerWidget);
+ dlg->setHelp("select-plugin", "kttsd");
+ int dlgResult = dlg->exec();
+ QString languageCode = addTalkerWidget->getLanguageCode();
+ QString synthName = addTalkerWidget->getSynthesizer();
+ delete dlg;
+ // TODO: Also delete addTalkerWidget?
+ if (dlgResult != QDialog::Accepted) return;
+
+ // If user chose "Other", must now get a language from him.
+ if(languageCode == "other")
+ {
+ // Create a QHBox to host KListView.
+ QHBox* hBox = new QHBox(m_kttsmgrw, "SelectLanguage_hbox");
+ // Create a KListView and fill with all known languages.
+ KListView* langLView = new KListView(hBox, "SelectLanguage_lview");
+ langLView->addColumn(i18n("Language"));
+ langLView->addColumn(i18n("Code"));
+ QStringList allLocales = KGlobal::locale()->allLanguagesTwoAlpha();
+ QString locale;
+ QString countryCode;
+ QString charSet;
+ QString language;
+ const int allLocalesCount = allLocales.count();
+ for (int ndx=0; ndx < allLocalesCount; ++ndx)
+ {
+ locale = allLocales[ndx];
+ language = TalkerCode::languageCodeToLanguage(locale);
+ new KListViewItem(langLView, language, locale);
+ }
+ // Sort by language.
+ langLView->setSorting(0);
+ langLView->sort();
+ // Display the box in a dialog.
+ KDialogBase* dlg = new KDialogBase(
+ KDialogBase::Swallow,
+ i18n("Select Language"),
+ KDialogBase::Help|KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Cancel,
+ m_kttsmgrw,
+ "SelectLanguage_dlg",
+ true,
+ true);
+ dlg->setMainWidget(hBox);
+ dlg->setHelp("select-plugin", "kttsd");
+ dlg->setInitialSize(QSize(200, 500), false);
+ dlgResult = dlg->exec();
+ languageCode = QString::null;
+ if (langLView->selectedItem()) languageCode = langLView->selectedItem()->text(1);
+ delete dlg;
+ // TODO: Also delete KListView and QHBox?
+ if (dlgResult != QDialog::Accepted) return;
+ }
+
+ if (languageCode.isEmpty()) return;
+ QString language = TalkerCode::languageCodeToLanguage(languageCode);
+ if (language.isEmpty()) return;
+
+ m_languagesToCodes[language] = languageCode;
+
+ // Assign a new Talker ID for the talker. Wraps around to 1.
+ QString talkerID = QString::number(m_lastTalkerID + 1);
+
+ // Erase extraneous Talker configuration entries that might be there.
+ m_config->deleteGroup(QString("Talker_")+talkerID);
+ m_config->sync();
+
+ // Convert translated plugin name to DesktopEntryName.
+ QString desktopEntryName = TalkerCode::TalkerNameToDesktopEntryName(synthName);
+ // This shouldn't happen, but just in case.
+ if (desktopEntryName.isEmpty()) return;
+
+ // Load the plugin.
+ m_loadedTalkerPlugIn = loadTalkerPlugin(desktopEntryName);
+ if (!m_loadedTalkerPlugIn) return;
+
+ // Give plugin the user's language code and permit plugin to autoconfigure itself.
+ m_loadedTalkerPlugIn->setDesiredLanguage(languageCode);
+ m_loadedTalkerPlugIn->load(m_config, QString("Talker_")+talkerID);
+
+ // If plugin was able to configure itself, it returns a full talker code.
+ // If not, display configuration dialog for user to configure the plugin.
+ QString talkerCode = m_loadedTalkerPlugIn->getTalkerCode();
+ if (talkerCode.isEmpty())
+ {
+ // Display configuration dialog.
+ configureTalker();
+ // Did user Cancel?
+ if (!m_loadedTalkerPlugIn)
+ {
+ m_configDlg->setMainWidget(0);
+ delete m_configDlg;
+ m_configDlg = 0;
+ return;
+ }
+ talkerCode = m_loadedTalkerPlugIn->getTalkerCode();
+ }
+
+ // If still no Talker Code, abandon.
+ if (!talkerCode.isEmpty())
+ {
+ // Let plugin save its configuration.
+ m_config->setGroup(QString("Talker_")+talkerID);
+ m_loadedTalkerPlugIn->save(m_config, QString("Talker_"+talkerID));
+
+ // Record last Talker ID used for next add.
+ m_lastTalkerID = talkerID.toInt();
+
+ // Record configuration data. Note, might as well do this now.
+ m_config->setGroup(QString("Talker_")+talkerID);
+ m_config->writeEntry("DesktopEntryName", desktopEntryName);
+ talkerCode = TalkerCode::normalizeTalkerCode(talkerCode, languageCode);
+ m_config->writeEntry("TalkerCode", talkerCode);
+ m_config->sync();
+
+ // Add listview item.
+ QListViewItem* talkerItem = m_kttsmgrw->talkersList->lastChild();
+ if (talkerItem)
+ talkerItem = new KListViewItem(m_kttsmgrw->talkersList, talkerItem,
+ QString::number(m_lastTalkerID), language, synthName);
+ else
+ talkerItem = new KListViewItem(m_kttsmgrw->talkersList,
+ QString::number(m_lastTalkerID), language, synthName);
+
+ // Set additional columns of the listview item.
+ updateTalkerItem(talkerItem, talkerCode);
+
+ // Make sure visible.
+ m_kttsmgrw->talkersList->ensureItemVisible(talkerItem);
+
+ // Select the new item, update buttons.
+ m_kttsmgrw->talkersList->setSelected(talkerItem, true);
+ updateTalkerButtons();
+
+ // Inform Control Center that change has been made.
+ configChanged();
+ }
+
+ // Don't need plugin in memory anymore.
+ delete m_loadedTalkerPlugIn;
+ m_loadedTalkerPlugIn = 0;
+ if (m_configDlg)
+ {
+ m_configDlg->setMainWidget(0);
+ delete m_configDlg;
+ m_configDlg = 0;
+ }
+
+ // kdDebug() << "KCMKttsMgr::addTalker: done." << endl;
+}
+
+void KCMKttsMgr::slot_addNormalFilter()
+{
+ addFilter( false );
+}
+
+void KCMKttsMgr:: slot_addSbdFilter()
+{
+ addFilter( true );
+}
+
+/**
+* Add a filter.
+*/
+void KCMKttsMgr::addFilter( bool sbd)
+{
+ // Build a list of filters that support multiple instances and let user choose.
+ KListView* lView = m_kttsmgrw->filtersList;
+ if (sbd) lView = m_kttsmgrw->sbdsList;
+
+ QStringList filterPlugInNames;
+ QListViewItem* item = lView->firstChild();
+ while (item)
+ {
+ if (item->text(flvcMultiInstance) == "T")
+ {
+ if (!filterPlugInNames.contains(item->text(flvcPlugInName)))
+ filterPlugInNames.append(item->text(flvcPlugInName));
+ }
+ item = item->nextSibling();
+ }
+ // Append those available plugins not yet in the list at all.
+ KTrader::OfferList offers = KTrader::self()->query("KTTSD/FilterPlugin");
+ for (unsigned int i=0; i < offers.count() ; ++i)
+ {
+ QString filterPlugInName = offers[i]->name();
+ if (countFilterPlugins(filterPlugInName) == 0)
+ {
+ QString desktopEntryName = FilterNameToDesktopEntryName(filterPlugInName);
+ KttsFilterConf* filterConf = loadFilterPlugin(desktopEntryName);
+ if (filterConf)
+ {
+ if (filterConf->isSBD() == sbd)
+ filterPlugInNames.append(filterPlugInName);
+ delete filterConf;
+ }
+ }
+ }
+
+ // If no choice (shouldn't happen), bail out.
+ // kdDebug() << "KCMKttsMgr::addFilter: filterPluginNames = " << filterPlugInNames << endl;
+ if (filterPlugInNames.count() == 0) return;
+
+ // If exactly one choice, skip selection dialog, otherwise display list to user to select from.
+ bool okChosen = false;
+ QString filterPlugInName;
+ if (filterPlugInNames.count() > 1)
+ {
+ filterPlugInName = KInputDialog::getItem(
+ i18n("Select Filter"),
+ i18n("Filter"),
+ filterPlugInNames,
+ 0,
+ false,
+ &okChosen,
+ m_kttsmgrw,
+ "selectfilter_kttsd");
+ if (!okChosen) return;
+ } else
+ filterPlugInName = filterPlugInNames[0];
+
+ // Assign a new Filter ID for the filter. Wraps around to 1.
+ QString filterID = QString::number(m_lastFilterID + 1);
+
+ // Erase extraneous Filter configuration entries that might be there.
+ m_config->deleteGroup(QString("Filter_")+filterID);
+ m_config->sync();
+
+ // Get DesktopEntryName from the translated name.
+ QString desktopEntryName = FilterNameToDesktopEntryName(filterPlugInName);
+ // This shouldn't happen, but just in case.
+ if (desktopEntryName.isEmpty()) return;
+
+ // Load the plugin.
+ m_loadedFilterPlugIn = loadFilterPlugin(desktopEntryName);
+ if (!m_loadedFilterPlugIn) return;
+
+ // Permit plugin to autoconfigure itself.
+ m_loadedFilterPlugIn->load(m_config, QString("Filter_")+filterID);
+
+ // Display configuration dialog for user to configure the plugin.
+ configureFilter();
+
+ // Did user Cancel?
+ if (!m_loadedFilterPlugIn)
+ {
+ m_configDlg->setMainWidget(0);
+ delete m_configDlg;
+ m_configDlg = 0;
+ return;
+ }
+
+ // Get user's name for Filter.
+ QString userFilterName = m_loadedFilterPlugIn->userPlugInName();
+
+ // If user properly configured the plugin, save its configuration.
+ if ( !userFilterName.isEmpty() )
+ {
+ // Let plugin save its configuration.
+ m_config->setGroup(QString("Filter_")+filterID);
+ m_loadedFilterPlugIn->save(m_config, QString("Filter_"+filterID));
+
+ // Record last Filter ID used for next add.
+ m_lastFilterID = filterID.toInt();
+
+ // Determine if filter supports multiple instances.
+ bool multiInstance = m_loadedFilterPlugIn->supportsMultiInstance();
+
+ // Record configuration data. Note, might as well do this now.
+ m_config->setGroup(QString("Filter_")+filterID);
+ m_config->writeEntry("DesktopEntryName", desktopEntryName);
+ m_config->writeEntry("UserFilterName", userFilterName);
+ m_config->writeEntry("MultiInstance", multiInstance);
+ m_config->writeEntry("Enabled", true);
+ m_config->writeEntry("IsSBD", sbd);
+ m_config->sync();
+
+ // Add listview item.
+ QListViewItem* filterItem = lView->lastChild();
+ if (sbd)
+ {
+ if (filterItem)
+ filterItem = new KListViewItem( lView, filterItem, userFilterName );
+ else
+ filterItem = new KListViewItem( lView, userFilterName );
+ }
+ else
+ {
+ if (filterItem)
+ filterItem = new KttsCheckListItem(lView, filterItem,
+ userFilterName, QCheckListItem::CheckBox, this);
+ else
+ filterItem = new KttsCheckListItem(lView,
+ userFilterName, QCheckListItem::CheckBox, this);
+ dynamic_cast<QCheckListItem*>(filterItem)->setOn(true);
+ }
+ filterItem->setText(flvcFilterID, QString::number(m_lastFilterID));
+ filterItem->setText(flvcPlugInName, filterPlugInName);
+ if (multiInstance)
+ filterItem->setText(flvcMultiInstance, "T");
+ else
+ filterItem->setText(flvcMultiInstance, "F");
+
+ // Make sure visible.
+ lView->ensureItemVisible(filterItem);
+
+ // Select the new item, update buttons.
+ lView->setSelected(filterItem, true);
+ if (sbd)
+ updateSbdButtons();
+ else
+ updateFilterButtons();
+
+ // Inform Control Center that change has been made.
+ configChanged();
+ }
+
+ // Don't need plugin in memory anymore.
+ delete m_loadedFilterPlugIn;
+ m_loadedFilterPlugIn = 0;
+ m_configDlg->setMainWidget(0);
+ delete m_configDlg;
+ m_configDlg = 0;
+
+ // kdDebug() << "KCMKttsMgr::addFilter: done." << endl;
+}
+
+/**
+* Remove talker.
+*/
+void KCMKttsMgr::slot_removeTalker(){
+ // kdDebug() << "KCMKttsMgr::removeTalker: Running"<< endl;
+
+ // Get the selected talker.
+ QListViewItem *itemToRemove = m_kttsmgrw->talkersList->selectedItem();
+ if (!itemToRemove) return;
+
+ // Delete the talker from configuration file.
+// QString talkerID = itemToRemove->text(tlvcTalkerID);
+// m_config->deleteGroup("Talker_"+talkerID, true, false);
+
+ // Delete the talker from list view.
+ delete itemToRemove;
+
+ updateTalkerButtons();
+
+ // Emit configuraton changed.
+ configChanged();
+}
+
+void KCMKttsMgr::slot_removeNormalFilter()
+{
+ removeFilter( false );
+}
+
+void KCMKttsMgr::slot_removeSbdFilter()
+{
+ removeFilter( true );
+}
+
+/**
+* Remove filter.
+*/
+void KCMKttsMgr::removeFilter( bool sbd )
+{
+ // kdDebug() << "KCMKttsMgr::removeFilter: Running"<< endl;
+
+ KListView* lView = m_kttsmgrw->filtersList;
+ if (sbd) lView = m_kttsmgrw->sbdsList;
+ // Get the selected filter.
+ QListViewItem *itemToRemove = lView->selectedItem();
+ if (!itemToRemove) return;
+
+ // Delete the filter from configuration file.
+// QString filterID = itemToRemove->text(flvcFilterID);
+// m_config->deleteGroup("Filter_"+filterID, true, false);
+
+ // Delete the filter from list view.
+ delete itemToRemove;
+
+ if (sbd)
+ updateSbdButtons();
+ else
+ updateFilterButtons();
+
+ // Emit configuraton changed.
+ configChanged();
+}
+
+void KCMKttsMgr::slot_higherTalkerPriority()
+{
+ higherItemPriority( m_kttsmgrw->talkersList );
+ updateTalkerButtons();
+}
+
+void KCMKttsMgr::slot_higherNormalFilterPriority()
+{
+ higherItemPriority( m_kttsmgrw->filtersList );
+ updateFilterButtons();
+}
+
+void KCMKttsMgr::slot_higherSbdFilterPriority()
+{
+ higherItemPriority( m_kttsmgrw->sbdsList );
+ updateSbdButtons();
+}
+
+/**
+* This is called whenever user clicks the Up button.
+*/
+void KCMKttsMgr::higherItemPriority( KListView* lView )
+{
+ QListViewItem* item = lView->selectedItem();
+ if (!item) return;
+ QListViewItem* prevItem = item->itemAbove();
+ if (!prevItem) return;
+ prevItem->moveItem(item);
+ lView->setSelected(item, true);
+ lView->ensureItemVisible( item );
+ configChanged();
+}
+
+void KCMKttsMgr::slot_lowerTalkerPriority()
+{
+ lowerItemPriority( m_kttsmgrw->talkersList );
+ updateTalkerButtons();
+}
+
+void KCMKttsMgr::slot_lowerNormalFilterPriority()
+{
+ lowerItemPriority( m_kttsmgrw->filtersList );
+ updateFilterButtons();
+}
+
+void KCMKttsMgr::slot_lowerSbdFilterPriority()
+{
+ lowerItemPriority( m_kttsmgrw->sbdsList );
+ updateSbdButtons();
+}
+
+/**
+* This is called whenever user clicks the Down button.
+*/
+void KCMKttsMgr::lowerItemPriority( KListView* lView )
+{
+ QListViewItem* item = lView->selectedItem();
+ if (!item) return;
+ QListViewItem* nextItem = item->itemBelow();
+ if (!nextItem) return;
+ item->moveItem(nextItem);
+ lView->setSelected(item, true);
+ lView->ensureItemVisible( item );
+ configChanged();
+}
+
+/**
+* Update the status of the Talker buttons.
+*/
+void KCMKttsMgr::updateTalkerButtons(){
+ // kdDebug() << "KCMKttsMgr::updateTalkerButtons: Running"<< endl;
+ if(m_kttsmgrw->talkersList->selectedItem()){
+ m_kttsmgrw->removeTalkerButton->setEnabled(true);
+ m_kttsmgrw->configureTalkerButton->setEnabled(true);
+ m_kttsmgrw->higherTalkerPriorityButton->setEnabled(
+ m_kttsmgrw->talkersList->selectedItem()->itemAbove() != 0);
+ m_kttsmgrw->lowerTalkerPriorityButton->setEnabled(
+ m_kttsmgrw->talkersList->selectedItem()->itemBelow() != 0);
+ } else {
+ m_kttsmgrw->removeTalkerButton->setEnabled(false);
+ m_kttsmgrw->configureTalkerButton->setEnabled(false);
+ m_kttsmgrw->higherTalkerPriorityButton->setEnabled(false);
+ m_kttsmgrw->lowerTalkerPriorityButton->setEnabled(false);
+ }
+ // kdDebug() << "KCMKttsMgr::updateTalkerButtons: Exiting"<< endl;
+}
+
+/**
+* Update the status of the normal Filter buttons.
+*/
+void KCMKttsMgr::updateFilterButtons(){
+ // kdDebug() << "KCMKttsMgr::updateFilterButtons: Running"<< endl;
+ QListViewItem* item = m_kttsmgrw->filtersList->selectedItem();
+ if (item) {
+ m_kttsmgrw->removeFilterButton->setEnabled(true);
+ m_kttsmgrw->configureFilterButton->setEnabled(true);
+ m_kttsmgrw->higherFilterPriorityButton->setEnabled(
+ m_kttsmgrw->filtersList->selectedItem()->itemAbove() != 0);
+ m_kttsmgrw->lowerFilterPriorityButton->setEnabled(
+ m_kttsmgrw->filtersList->selectedItem()->itemBelow() != 0);
+ } else {
+ m_kttsmgrw->removeFilterButton->setEnabled(false);
+ m_kttsmgrw->configureFilterButton->setEnabled(false);
+ m_kttsmgrw->higherFilterPriorityButton->setEnabled(false);
+ m_kttsmgrw->lowerFilterPriorityButton->setEnabled(false);
+ }
+ // kdDebug() << "KCMKttsMgr::updateFilterButtons: Exiting"<< endl;
+}
+
+/**
+ * Update the status of the SBD buttons.
+ */
+void KCMKttsMgr::updateSbdButtons(){
+ // kdDebug() << "KCMKttsMgr::updateSbdButtons: Running"<< endl;
+ QListViewItem* item = m_kttsmgrw->sbdsList->selectedItem();
+ if (item) {
+ m_sbdPopmenu->setItemEnabled( sbdBtnEdit, true );
+ m_sbdPopmenu->setItemEnabled( sbdBtnUp,
+ m_kttsmgrw->sbdsList->selectedItem()->itemAbove() != 0 );
+ m_sbdPopmenu->setItemEnabled( sbdBtnDown,
+ m_kttsmgrw->sbdsList->selectedItem()->itemBelow() != 0 );
+ m_sbdPopmenu->setItemEnabled( sbdBtnRemove, true );
+ } else {
+ m_sbdPopmenu->setItemEnabled( sbdBtnEdit, false );
+ m_sbdPopmenu->setItemEnabled( sbdBtnUp, false );
+ m_sbdPopmenu->setItemEnabled( sbdBtnDown, false );
+ m_sbdPopmenu->setItemEnabled( sbdBtnRemove, false );
+ }
+ // kdDebug() << "KCMKttsMgr::updateSbdButtons: Exiting"<< endl;
+}
+
+/**
+* This signal is emitted whenever user checks/unchecks the Enable TTS System check box.
+*/
+void KCMKttsMgr::enableKttsdToggled(bool)
+{
+ // Prevent re-entrancy.
+ static bool reenter;
+ if (reenter) return;
+ reenter = true;
+ // See if KTTSD is running.
+ DCOPClient *client = kapp->dcopClient();
+ bool kttsdRunning = (client->isApplicationRegistered("kttsd"));
+ // kdDebug() << "KCMKttsMgr::enableKttsdToggled: kttsdRunning = " << kttsdRunning << endl;
+ // If Enable KTTSD check box is checked and it is not running, then start KTTSD.
+ if (m_kttsmgrw->enableKttsdCheckBox->isChecked())
+ {
+ if (!kttsdRunning)
+ {
+ // kdDebug() << "KCMKttsMgr::enableKttsdToggled:: Starting KTTSD" << endl;
+ QString error;
+ if (KApplication::startServiceByDesktopName("kttsd", QStringList(), &error))
+ {
+ kdDebug() << "Starting KTTSD failed with message " << error << endl;
+ m_kttsmgrw->enableKttsdCheckBox->setChecked(false);
+ m_kttsmgrw->notifyTestButton->setEnabled(false);
+ }
+ }
+ }
+ else
+ // If check box is not checked and it is running, then stop KTTSD.
+ {
+ if (kttsdRunning)
+ {
+ // kdDebug() << "KCMKttsMgr::enableKttsdToggled:: Stopping KTTSD" << endl;
+ QByteArray data;
+ client->send("kttsd", "KSpeech", "kttsdExit()", data);
+ }
+ }
+ reenter = false;
+}
+
+/**
+* This signal is emitted whenever user checks/unchecks the GStreamer radio button.
+*/
+void KCMKttsMgr::slotGstreamerRadioButton_toggled(bool state)
+{
+ m_kttsmgrw->sinkLabel->setEnabled(state);
+ m_kttsmgrw->sinkComboBox->setEnabled(state);
+}
+
+/**
+* This signal is emitted whenever user checks/unchecks the ALSA radio button.
+*/
+void KCMKttsMgr::slotAlsaRadioButton_toggled(bool state)
+{
+ m_kttsmgrw->pcmLabel->setEnabled(state);
+ m_kttsmgrw->pcmComboBox->setEnabled(state);
+ m_kttsmgrw->pcmCustom->setEnabled(state && m_kttsmgrw->pcmComboBox->currentText() == "custom");
+}
+
+/**
+* This is emitted whenever user activates the ALSA pcm combobox.
+*/
+void KCMKttsMgr::slotPcmComboBox_activated()
+{
+ m_kttsmgrw->pcmCustom->setEnabled(m_kttsmgrw->pcmComboBox->currentText() == "custom");
+}
+
+/**
+* This signal is emitted whenever user checks/unchecks the aKode radio button.
+*/
+void KCMKttsMgr::slotAkodeRadioButton_toggled(bool state)
+{
+ m_kttsmgrw->akodeSinkLabel->setEnabled(state);
+ m_kttsmgrw->akodeComboBox->setEnabled(state);
+}
+
+/**
+* This slot is called whenever KTTSD starts or restarts.
+*/
+void KCMKttsMgr::kttsdStarted()
+{
+ // kdDebug() << "KCMKttsMgr::kttsdStarted: Running" << endl;
+ bool kttsdLoaded = (m_jobMgrPart != 0);
+ // Load Job Manager Part library.
+ if (!kttsdLoaded)
+ {
+ KLibFactory *factory = KLibLoader::self()->factory( "libkttsjobmgrpart" );
+ if (factory)
+ {
+ // Create the Job Manager part
+ m_jobMgrPart = (KParts::ReadOnlyPart *)factory->create( m_kttsmgrw->mainTab, "kttsjobmgr",
+ "KParts::ReadOnlyPart" );
+ if (m_jobMgrPart)
+ {
+ // Add the Job Manager part as a new tab.
+ m_kttsmgrw->mainTab->addTab(m_jobMgrPart->widget(), i18n("&Jobs"));
+ kttsdLoaded = true;
+ }
+ else
+ kdDebug() << "Could not create kttsjobmgr part." << endl;
+ }
+ else kdDebug() << "Could not load libkttsjobmgrpart. Is libkttsjobmgrpart installed?" << endl;
+ }
+ // Check/Uncheck the Enable KTTSD check box.
+ if (kttsdLoaded)
+ {
+ m_kttsmgrw->enableKttsdCheckBox->setChecked(true);
+ // Enable/disable notify Test button.
+ slotNotifyListView_selectionChanged();
+ } else {
+ m_kttsmgrw->enableKttsdCheckBox->setChecked(false);
+ m_kttsmgrw->notifyTestButton->setEnabled(false);
+ }
+}
+
+/**
+* This slot is called whenever KTTSD is about to exit.
+*/
+void KCMKttsMgr::kttsdExiting()
+{
+ // kdDebug() << "KCMKttsMgr::kttsdExiting: Running" << endl;
+ if (m_jobMgrPart)
+ {
+ m_kttsmgrw->mainTab->removePage(m_jobMgrPart->widget());
+ delete m_jobMgrPart;
+ m_jobMgrPart = 0;
+ }
+ m_kttsmgrw->enableKttsdCheckBox->setChecked(false);
+ m_kttsmgrw->notifyTestButton->setEnabled(false);
+}
+
+/**
+* User has requested display of talker configuration dialog.
+*/
+void KCMKttsMgr::slot_configureTalker()
+{
+ // Get highlighted plugin from Talker ListView and load into memory.
+ QListViewItem* talkerItem = m_kttsmgrw->talkersList->selectedItem();
+ if (!talkerItem) return;
+ QString talkerID = talkerItem->text(tlvcTalkerID);
+ QString synthName = talkerItem->text(tlvcSynthName);
+ QString language = talkerItem->text(tlvcLanguage);
+ QString languageCode = m_languagesToCodes[language];
+ QString desktopEntryName = TalkerCode::TalkerNameToDesktopEntryName(synthName);
+ m_loadedTalkerPlugIn = loadTalkerPlugin(desktopEntryName);
+ if (!m_loadedTalkerPlugIn) return;
+ // kdDebug() << "KCMKttsMgr::slot_configureTalker: plugin for " << synthName << " loaded successfully." << endl;
+
+ // Tell plugin to load its configuration.
+ m_config->setGroup(QString("Talker_")+talkerID);
+ m_loadedTalkerPlugIn->setDesiredLanguage(languageCode);
+ // kdDebug() << "KCMKttsMgr::slot_configureTalker: about to call plugin load() method with Talker ID = " << talkerID << endl;
+ m_loadedTalkerPlugIn->load(m_config, QString("Talker_")+talkerID);
+
+ // Display configuration dialog.
+ configureTalker();
+
+ // Did user Cancel?
+ if (!m_loadedTalkerPlugIn)
+ {
+ m_configDlg->setMainWidget(0);
+ delete m_configDlg;
+ m_configDlg = 0;
+ return;
+ }
+
+ // Get Talker Code. Note that plugin may return a code different from before.
+ QString talkerCode = m_loadedTalkerPlugIn->getTalkerCode();
+
+ // If plugin was successfully configured, save its configuration.
+ if (!talkerCode.isEmpty())
+ {
+ m_config->setGroup(QString("Talker_")+talkerID);
+ m_loadedTalkerPlugIn->save(m_config, QString("Talker_")+talkerID);
+ m_config->setGroup(QString("Talker_")+talkerID);
+ talkerCode = TalkerCode::normalizeTalkerCode(talkerCode, languageCode);
+ m_config->writeEntry("TalkerCode", talkerCode);
+ m_config->sync();
+
+ // Update display.
+ updateTalkerItem(talkerItem, talkerCode);
+
+ // Inform Control Center that configuration has changed.
+ configChanged();
+ }
+
+ delete m_loadedTalkerPlugIn;
+ m_loadedTalkerPlugIn = 0;
+ m_configDlg->setMainWidget(0);
+ delete m_configDlg;
+ m_configDlg = 0;
+}
+
+void KCMKttsMgr::slot_configureNormalFilter()
+{
+ configureFilterItem( false );
+}
+
+void KCMKttsMgr::slot_configureSbdFilter()
+{
+ configureFilterItem( true );
+}
+
+/**
+ * User has requested display of filter configuration dialog.
+ */
+void KCMKttsMgr::configureFilterItem( bool sbd )
+{
+ // Get highlighted plugin from Filter ListView and load into memory.
+ KListView* lView = m_kttsmgrw->filtersList;
+ if (sbd) lView = m_kttsmgrw->sbdsList;
+ QListViewItem* filterItem = lView->selectedItem();
+ if (!filterItem) return;
+ QString filterID = filterItem->text(flvcFilterID);
+ QString filterPlugInName = filterItem->text(flvcPlugInName);
+ QString desktopEntryName = FilterNameToDesktopEntryName(filterPlugInName);
+ if (desktopEntryName.isEmpty()) return;
+ m_loadedFilterPlugIn = loadFilterPlugin(desktopEntryName);
+ if (!m_loadedFilterPlugIn) return;
+ // kdDebug() << "KCMKttsMgr::slot_configureFilter: plugin for " << filterPlugInName << " loaded successfully." << endl;
+
+ // Tell plugin to load its configuration.
+ m_config->setGroup(QString("Filter_")+filterID);
+ // kdDebug() << "KCMKttsMgr::slot_configureFilter: about to call plugin load() method with Filter ID = " << filterID << endl;
+ m_loadedFilterPlugIn->load(m_config, QString("Filter_")+filterID);
+
+ // Display configuration dialog.
+ configureFilter();
+
+ // Did user Cancel?
+ if (!m_loadedFilterPlugIn)
+ {
+ m_configDlg->setMainWidget(0);
+ delete m_configDlg;
+ m_configDlg = 0;
+ return;
+ }
+
+ // Get user's name for the plugin.
+ QString userFilterName = m_loadedFilterPlugIn->userPlugInName();
+
+ // If user properly configured the plugin, save the configuration.
+ if ( !userFilterName.isEmpty() )
+ {
+
+ // Let plugin save its configuration.
+ m_config->setGroup(QString("Filter_")+filterID);
+ m_loadedFilterPlugIn->save(m_config, QString("Filter_")+filterID);
+
+ // Save configuration.
+ m_config->setGroup("Filter_"+filterID);
+ m_config->writeEntry("DesktopEntryName", desktopEntryName);
+ m_config->writeEntry("UserFilterName", userFilterName);
+ m_config->writeEntry("Enabled", true);
+ m_config->writeEntry("MultiInstance", m_loadedFilterPlugIn->supportsMultiInstance());
+ m_config->writeEntry("IsSBD", sbd);
+
+ m_config->sync();
+
+ // Update display.
+ filterItem->setText(flvcUserName, userFilterName);
+ if (!sbd)
+ dynamic_cast<QCheckListItem*>(filterItem)->setOn(true);
+
+ // Inform Control Center that configuration has changed.
+ configChanged();
+ }
+
+ delete m_loadedFilterPlugIn;
+ m_loadedFilterPlugIn = 0;
+ m_configDlg->setMainWidget(0);
+ delete m_configDlg;
+ m_configDlg = 0;
+}
+
+/**
+* Display talker configuration dialog. The plugin is assumed already loaded into
+* memory referenced by m_loadedTalkerPlugIn.
+*/
+void KCMKttsMgr::configureTalker()
+{
+ if (!m_loadedTalkerPlugIn) return;
+ m_configDlg = new KDialogBase(
+ KDialogBase::Swallow,
+ i18n("Talker Configuration"),
+ KDialogBase::Help|KDialogBase::Default|KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Cancel,
+ m_kttsmgrw,
+ "configureTalker_dlg",
+ true,
+ true);
+ m_configDlg->setInitialSize(QSize(700, 300), false);
+ m_configDlg->setMainWidget(m_loadedTalkerPlugIn);
+ m_configDlg->setHelp("configure-plugin", "kttsd");
+ m_configDlg->enableButtonOK(false);
+ connect(m_loadedTalkerPlugIn, SIGNAL( changed(bool) ), this, SLOT( slotConfigTalkerDlg_ConfigChanged() ));
+ connect(m_configDlg, SIGNAL( defaultClicked() ), this, SLOT( slotConfigTalkerDlg_DefaultClicked() ));
+ connect(m_configDlg, SIGNAL( cancelClicked() ), this, SLOT (slotConfigTalkerDlg_CancelClicked() ));
+ // Create a Player object for the plugin to use for testing.
+ int playerOption = 0;
+ QString sinkName;
+ if (m_kttsmgrw->gstreamerRadioButton->isChecked()) {
+ playerOption = 1;
+ sinkName = m_kttsmgrw->sinkComboBox->currentText();
+ }
+ if (m_kttsmgrw->alsaRadioButton->isChecked()) {
+ playerOption = 2;
+ if (m_kttsmgrw->pcmComboBox->currentText() == "custom")
+ sinkName = m_kttsmgrw->pcmCustom->text();
+ else
+ sinkName = m_kttsmgrw->pcmComboBox->currentText();
+ }
+ if (m_kttsmgrw->akodeRadioButton->isChecked()) {
+ playerOption = 3;
+ sinkName = m_kttsmgrw->akodeComboBox->currentText();
+ }
+ float audioStretchFactor = 1.0/(float(m_kttsmgrw->timeBox->value())/100.0);
+ // kdDebug() << "KCMKttsMgr::configureTalker: playerOption = " << playerOption << " audioStretchFactor = " << audioStretchFactor << " sink name = " << sinkName << endl;
+ TestPlayer* testPlayer = new TestPlayer(this, "ktts_testplayer",
+ playerOption, audioStretchFactor, sinkName);
+ m_loadedTalkerPlugIn->setPlayer(testPlayer);
+ // Display the dialog.
+ m_configDlg->exec();
+ // Done with Player object.
+ if (m_loadedTalkerPlugIn)
+ {
+ delete testPlayer;
+ m_loadedTalkerPlugIn->setPlayer(0);
+ }
+}
+
+/**
+* Display filter configuration dialog. The plugin is assumed already loaded into
+* memory referenced by m_loadedFilterPlugIn.
+*/
+void KCMKttsMgr::configureFilter()
+{
+ if (!m_loadedFilterPlugIn) return;
+ m_configDlg = new KDialogBase(
+ KDialogBase::Swallow,
+ i18n("Filter Configuration"),
+ KDialogBase::Help|KDialogBase::Default|KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Cancel,
+ m_kttsmgrw,
+ "configureFilter_dlg",
+ true,
+ true);
+ m_configDlg->setInitialSize(QSize(600, 450), false);
+ m_loadedFilterPlugIn->setMinimumSize(m_loadedFilterPlugIn->minimumSizeHint());
+ m_loadedFilterPlugIn->show();
+ m_configDlg->setMainWidget(m_loadedFilterPlugIn);
+ m_configDlg->setHelp("configure-filter", "kttsd");
+ m_configDlg->enableButtonOK(false);
+ connect(m_loadedFilterPlugIn, SIGNAL( changed(bool) ), this, SLOT( slotConfigFilterDlg_ConfigChanged() ));
+ connect(m_configDlg, SIGNAL( defaultClicked() ), this, SLOT( slotConfigFilterDlg_DefaultClicked() ));
+ connect(m_configDlg, SIGNAL( cancelClicked() ), this, SLOT (slotConfigFilterDlg_CancelClicked() ));
+ // Display the dialog.
+ m_configDlg->exec();
+}
+
+/**
+* Count number of configured Filters with the specified plugin name.
+*/
+int KCMKttsMgr::countFilterPlugins(const QString& filterPlugInName)
+{
+ int cnt = 0;
+ QListViewItem* item = m_kttsmgrw->filtersList->firstChild();
+ while (item)
+ {
+ if (item->text(flvcPlugInName) == filterPlugInName) ++cnt;
+ item = item->nextSibling();
+ }
+ item = m_kttsmgrw->sbdsList->firstChild();
+ while (item)
+ {
+ if (item->text(slvcPlugInName) == filterPlugInName) ++cnt;
+ item = item->nextSibling();
+ }
+ return cnt;
+}
+
+void KCMKttsMgr::keepAudioCheckBox_toggled(bool checked)
+{
+ m_kttsmgrw->keepAudioPath->setEnabled(checked);
+ configChanged();
+}
+
+// Basically the slider values are logarithmic (0,...,1000) whereas percent
+// values are linear (50%,...,200%).
+//
+// slider = alpha * (log(percent)-log(50))
+// with alpha = 1000/(log(200)-log(50))
+
+int KCMKttsMgr::percentToSlider(int percentValue) {
+ double alpha = 1000 / (log(200) - log(50));
+ return (int)floor (0.5 + alpha * (log(percentValue)-log(50)));
+}
+
+int KCMKttsMgr::sliderToPercent(int sliderValue) {
+ double alpha = 1000 / (log(200) - log(50));
+ return (int)floor(0.5 + exp (sliderValue/alpha + log(50)));
+}
+
+void KCMKttsMgr::timeBox_valueChanged(int percentValue) {
+ m_kttsmgrw->timeSlider->setValue (percentToSlider (percentValue));
+}
+
+void KCMKttsMgr::timeSlider_valueChanged(int sliderValue) {
+ m_kttsmgrw->timeBox->setValue (sliderToPercent (sliderValue));
+}
+
+void KCMKttsMgr::slotConfigTalkerDlg_ConfigChanged()
+{
+ m_configDlg->enableButtonOK(!m_loadedTalkerPlugIn->getTalkerCode().isEmpty());
+}
+
+void KCMKttsMgr::slotConfigFilterDlg_ConfigChanged()
+{
+ m_configDlg->enableButtonOK( !m_loadedFilterPlugIn->userPlugInName().isEmpty() );
+}
+
+void KCMKttsMgr::slotConfigTalkerDlg_DefaultClicked()
+{
+ m_loadedTalkerPlugIn->defaults();
+}
+
+void KCMKttsMgr::slotConfigFilterDlg_DefaultClicked()
+{
+ m_loadedFilterPlugIn->defaults();
+}
+
+void KCMKttsMgr::slotConfigTalkerDlg_CancelClicked()
+{
+ delete m_loadedTalkerPlugIn;
+ m_loadedTalkerPlugIn = 0;
+}
+
+void KCMKttsMgr::slotConfigFilterDlg_CancelClicked()
+{
+ delete m_loadedFilterPlugIn;
+ m_loadedFilterPlugIn = 0;
+}
+
+/**
+* This slot is called whenever user checks/unchecks item in Filters list.
+*/
+void KCMKttsMgr::slotFiltersList_stateChanged()
+{
+ // kdDebug() << "KCMKttsMgr::slotFiltersList_stateChanged: calling configChanged" << endl;
+ configChanged();
+}
+
+/**
+ * Uses KTrader to convert a translated Filter Plugin Name to DesktopEntryName.
+ * @param name The translated plugin name. From Name= line in .desktop file.
+ * @return DesktopEntryName. The name of the .desktop file (less .desktop).
+ * QString::null if not found.
+ */
+QString KCMKttsMgr::FilterNameToDesktopEntryName(const QString& name)
+{
+ if (name.isEmpty()) return QString::null;
+ KTrader::OfferList offers = KTrader::self()->query("KTTSD/FilterPlugin");
+ for (uint ndx = 0; ndx < offers.count(); ++ndx)
+ if (offers[ndx]->name() == name) return offers[ndx]->desktopEntryName();
+ return QString::null;
+}
+
+/**
+ * Uses KTrader to convert a DesktopEntryName into a translated Filter Plugin Name.
+ * @param desktopEntryName The DesktopEntryName.
+ * @return The translated Name of the plugin, from Name= line in .desktop file.
+ */
+QString KCMKttsMgr::FilterDesktopEntryNameToName(const QString& desktopEntryName)
+{
+ if (desktopEntryName.isEmpty()) return QString::null;
+ KTrader::OfferList offers = KTrader::self()->query("KTTSD/FilterPlugin",
+ QString("DesktopEntryName == '%1'").arg(desktopEntryName));
+
+ if (offers.count() == 1)
+ return offers[0]->name();
+ else
+ return QString::null;
+}
+
+/**
+ * Loads notify events from a file. Clearing listview if clear is True.
+ */
+QString KCMKttsMgr::loadNotifyEventsFromFile( const QString& filename, bool clear)
+{
+ // Open existing event list.
+ QFile file( filename );
+ if ( !file.open( IO_ReadOnly ) )
+ {
+ return i18n("Unable to open file.") + filename;
+ }
+ // QDomDocument doc( "http://www.kde.org/share/apps/kttsd/stringreplacer/wordlist.dtd []" );
+ QDomDocument doc( "" );
+ if ( !doc.setContent( &file ) ) {
+ file.close();
+ return i18n("File not in proper XML format.");
+ }
+ // kdDebug() << "StringReplacerConf::load: document successfully parsed." << endl;
+ file.close();
+
+ // Clear list view.
+ if ( clear ) m_kttsmgrw->notifyListView->clear();
+
+ // Event list.
+ QDomNodeList eventList = doc.elementsByTagName("notifyEvent");
+ const int eventListCount = eventList.count();
+ for (int eventIndex = 0; eventIndex < eventListCount; ++eventIndex)
+ {
+ QDomNode eventNode = eventList.item(eventIndex);
+ QDomNodeList propList = eventNode.childNodes();
+ QString eventSrc;
+ QString event;
+ QString actionName;
+ QString message;
+ TalkerCode talkerCode;
+ const int propListCount = propList.count();
+ for (int propIndex = 0; propIndex < propListCount; ++propIndex)
+ {
+ QDomNode propNode = propList.item(propIndex);
+ QDomElement prop = propNode.toElement();
+ if (prop.tagName() == "eventSrc") eventSrc = prop.text();
+ if (prop.tagName() == "event") event = prop.text();
+ if (prop.tagName() == "action") actionName = prop.text();
+ if (prop.tagName() == "message") message = prop.text();
+ if (prop.tagName() == "talker") talkerCode = TalkerCode(prop.text(), false);
+ }
+ addNotifyItem(eventSrc, event, NotifyAction::action( actionName ), message, talkerCode);
+ }
+
+ return QString::null;
+}
+
+/**
+ * Saves notify events to a file.
+ */
+QString KCMKttsMgr::saveNotifyEventsToFile(const QString& filename)
+{
+ QFile file( filename );
+ if ( !file.open( IO_WriteOnly ) )
+ return i18n("Unable to open file ") + filename;
+
+ QDomDocument doc( "" );
+
+ QDomElement root = doc.createElement( "notifyEventList" );
+ doc.appendChild( root );
+
+ // Events.
+ KListView* lv = m_kttsmgrw->notifyListView;
+ QListViewItemIterator it(lv);
+ while ( it.current() )
+ {
+ QListViewItem* item = *it;
+ if ( item->depth() > 0 )
+ {
+ QDomElement wordTag = doc.createElement( "notifyEvent" );
+ root.appendChild( wordTag );
+
+ QDomElement propTag = doc.createElement( "eventSrc" );
+ wordTag.appendChild( propTag);
+ QDomText t = doc.createTextNode( item->text(nlvcEventSrc) );
+ propTag.appendChild( t );
+
+ propTag = doc.createElement( "event" );
+ wordTag.appendChild( propTag);
+ t = doc.createTextNode( item->text(nlvcEvent) );
+ propTag.appendChild( t );
+
+ propTag = doc.createElement( "action" );
+ wordTag.appendChild( propTag);
+ t = doc.createTextNode( item->text(nlvcAction) );
+ propTag.appendChild( t );
+
+ if ( item->text(nlvcAction) == NotifyAction::actionName( NotifyAction::SpeakCustom ) )
+ {
+ propTag = doc.createElement( "message" );
+ wordTag.appendChild( propTag);
+ QString msg = item->text(nlvcActionName);
+ int msglen = msg.length();
+ msg = msg.mid( 1, msglen-2 );
+ t = doc.createCDATASection( msg );
+ propTag.appendChild( t );
+ }
+
+ propTag = doc.createElement( "talker" );
+ wordTag.appendChild( propTag);
+ t = doc.createCDATASection( item->text(nlvcTalker) );
+ propTag.appendChild( t );
+ }
+ ++it;
+ }
+
+ // Write it all out.
+ QTextStream ts( &file );
+ ts.setEncoding( QTextStream::UnicodeUTF8 );
+ ts << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ ts << doc.toString();
+ file.close();
+
+ return QString::null;
+}
+
+void KCMKttsMgr::slotNotifyEnableCheckBox_toggled(bool checked)
+{
+ m_kttsmgrw->notifyExcludeEventsWithSoundCheckBox->setEnabled( checked );
+ m_kttsmgrw->notifyGroup->setEnabled( checked );
+ configChanged();
+}
+
+void KCMKttsMgr::slotNotifyPresentComboBox_activated(int index)
+{
+ QListViewItem* item = m_kttsmgrw->notifyListView->selectedItem();
+ if ( !item ) return; // should not happen
+ item->setText( nlvcEvent, NotifyPresent::presentName( index ) );
+ item->setText( nlvcEventName, NotifyPresent::presentDisplayName( index ) );
+ bool enableIt = ( index != NotifyPresent::None);
+ m_kttsmgrw->notifyActionComboBox->setEnabled( enableIt );
+ m_kttsmgrw->notifyTalkerButton->setEnabled( enableIt );
+ if (!enableIt)
+ {
+ m_kttsmgrw->notifyTalkerLineEdit->clear();
+ } else {
+ if ( m_kttsmgrw->notifyTalkerLineEdit->text().isEmpty() )
+ {
+ m_kttsmgrw->notifyTalkerLineEdit->setText( i18n("default") );
+ }
+ }
+ configChanged();
+}
+
+void KCMKttsMgr::slotNotifyListView_selectionChanged()
+{
+ QListViewItem* item = m_kttsmgrw->notifyListView->selectedItem();
+ if ( item )
+ {
+ bool topLevel = ( item->depth() == 0 );
+ if ( topLevel )
+ {
+ m_kttsmgrw->notifyPresentComboBox->setEnabled( false );
+ m_kttsmgrw->notifyActionComboBox->setEnabled( false );
+ m_kttsmgrw->notifyTestButton->setEnabled( false );
+ m_kttsmgrw->notifyMsgLineEdit->setEnabled( false );
+ m_kttsmgrw->notifyMsgLineEdit->clear();
+ m_kttsmgrw->notifyTalkerButton->setEnabled( false );
+ m_kttsmgrw->notifyTalkerLineEdit->clear();
+ bool defaultItem = ( item->text(nlvcEventSrc) == "default" );
+ m_kttsmgrw->notifyRemoveButton->setEnabled( !defaultItem );
+ } else {
+ bool defaultItem = ( item->parent()->text(nlvcEventSrc) == "default" );
+ m_kttsmgrw->notifyPresentComboBox->setEnabled( defaultItem );
+ if ( defaultItem )
+ m_kttsmgrw->notifyPresentComboBox->setCurrentItem( NotifyPresent::present( item->text( nlvcEvent ) ) );
+ m_kttsmgrw->notifyActionComboBox->setEnabled( true );
+ int action = NotifyAction::action( item->text( nlvcAction ) );
+ m_kttsmgrw->notifyActionComboBox->setCurrentItem( action );
+ m_kttsmgrw->notifyTalkerButton->setEnabled( true );
+ TalkerCode talkerCode( item->text( nlvcTalker ) );
+ m_kttsmgrw->notifyTalkerLineEdit->setText( talkerCode.getTranslatedDescription() );
+ if ( action == NotifyAction::SpeakCustom )
+ {
+ m_kttsmgrw->notifyMsgLineEdit->setEnabled( true );
+ QString msg = item->text( nlvcActionName );
+ int msglen = msg.length();
+ msg = msg.mid( 1, msglen-2 );
+ m_kttsmgrw->notifyMsgLineEdit->setText( msg );
+ } else {
+ m_kttsmgrw->notifyMsgLineEdit->setEnabled( false );
+ m_kttsmgrw->notifyMsgLineEdit->clear();
+ }
+ m_kttsmgrw->notifyRemoveButton->setEnabled( !defaultItem );
+ m_kttsmgrw->notifyTestButton->setEnabled(
+ action != NotifyAction::DoNotSpeak &&
+ m_kttsmgrw->enableKttsdCheckBox->isChecked());
+ }
+ } else {
+ m_kttsmgrw->notifyPresentComboBox->setEnabled( false );
+ m_kttsmgrw->notifyActionComboBox->setEnabled( false );
+ m_kttsmgrw->notifyTestButton->setEnabled( false );
+ m_kttsmgrw->notifyMsgLineEdit->setEnabled( false );
+ m_kttsmgrw->notifyMsgLineEdit->clear();
+ m_kttsmgrw->notifyTalkerButton->setEnabled( false );
+ m_kttsmgrw->notifyTalkerLineEdit->clear();
+ m_kttsmgrw->notifyRemoveButton->setEnabled( false );
+ }
+}
+
+void KCMKttsMgr::slotNotifyActionComboBox_activated(int index)
+{
+ QListViewItem* item = m_kttsmgrw->notifyListView->selectedItem();
+ if ( item )
+ if ( item->depth() == 0 ) item = 0;
+ if ( !item ) return; // This shouldn't happen.
+ item->setText( nlvcAction, NotifyAction::actionName( index ) );
+ item->setText( nlvcActionName, NotifyAction::actionDisplayName( index ) );
+ if ( index == NotifyAction::SpeakCustom )
+ item->setText( nlvcActionName, "\"" + m_kttsmgrw->notifyMsgLineEdit->text() + "\"" );
+ if ( index == NotifyAction::DoNotSpeak )
+ item->setPixmap( nlvcActionName, SmallIcon( "nospeak" ) );
+ else
+ item->setPixmap( nlvcActionName, SmallIcon( "speak" ) );
+ slotNotifyListView_selectionChanged();
+ configChanged();
+}
+
+void KCMKttsMgr::slotNotifyMsgLineEdit_textChanged(const QString& text)
+{
+ QListViewItem* item = m_kttsmgrw->notifyListView->selectedItem();
+ if ( item )
+ if ( item->depth() == 0 ) item = 0;
+ if ( !item ) return; // This shouldn't happen.
+ if ( m_kttsmgrw->notifyActionComboBox->currentItem() != NotifyAction::SpeakCustom) return;
+ item->setText( nlvcActionName, "\"" + text + "\"" );
+ m_kttsmgrw->notifyTestButton->setEnabled(
+ !text.isEmpty() && m_kttsmgrw->enableKttsdCheckBox->isChecked());
+ configChanged();
+}
+
+void KCMKttsMgr::slotNotifyTestButton_clicked()
+{
+ QListViewItem* item = m_kttsmgrw->notifyListView->selectedItem();
+ if (item)
+ {
+ QString msg;
+ int action = NotifyAction::action(item->text(nlvcAction));
+ switch (action)
+ {
+ case NotifyAction::SpeakEventName:
+ msg = item->text(nlvcEventName);
+ break;
+ case NotifyAction::SpeakMsg:
+ msg = i18n("sample notification message");
+ break;
+ case NotifyAction::SpeakCustom:
+ msg = m_kttsmgrw->notifyMsgLineEdit->text();
+ msg.replace("%a", i18n("sample application"));
+ msg.replace("%e", i18n("sample event"));
+ msg.replace("%m", i18n("sample notification message"));
+ break;
+ }
+ if (!msg.isEmpty()) sayMessage(msg, item->text(nlvcTalker));
+ }
+}
+
+void KCMKttsMgr::slotNotifyTalkerButton_clicked()
+{
+ QListViewItem* item = m_kttsmgrw->notifyListView->selectedItem();
+ if ( item )
+ if ( item->depth() == 0 ) item = 0;
+ if ( !item ) return; // This shouldn't happen.
+ QString talkerCode = item->text( nlvcTalker );
+ SelectTalkerDlg dlg( m_kttsmgrw, "selecttalkerdialog", i18n("Select Talker"), talkerCode, true );
+ int dlgResult = dlg.exec();
+ if ( dlgResult != KDialogBase::Accepted ) return;
+ item->setText( nlvcTalker, dlg.getSelectedTalkerCode() );
+ QString talkerName = dlg.getSelectedTranslatedDescription();
+ item->setText( nlvcTalkerName, talkerName );
+ m_kttsmgrw->notifyTalkerLineEdit->setText( talkerName );
+ configChanged();
+}
+
+/**
+ * Adds an item to the notify listview.
+ * message is only needed if action = naSpeakCustom.
+ */
+QListViewItem* KCMKttsMgr::addNotifyItem(
+ const QString& eventSrc,
+ const QString& event,
+ int action,
+ const QString& message,
+ TalkerCode& talkerCode)
+{
+ KListView* lv = m_kttsmgrw->notifyListView;
+ QListViewItem* item = 0;
+ QString iconName;
+ QString eventSrcName;
+ if (eventSrc == "default")
+ eventSrcName = i18n("Default (all other events)");
+ else
+ eventSrcName = NotifyEvent::getEventSrcName(eventSrc, iconName);
+ QString eventName;
+ if (eventSrc == "default")
+ eventName = NotifyPresent::presentDisplayName( event );
+ else
+ {
+ if (event == "default")
+ eventName = i18n("All other %1 events").arg(eventSrcName);
+ else
+ eventName = NotifyEvent::getEventName(eventSrc, event);
+ }
+ QString actionName = NotifyAction::actionName( action );
+ QString actionDisplayName = NotifyAction::actionDisplayName( action );
+ if (action == NotifyAction::SpeakCustom) actionDisplayName = "\"" + message + "\"";
+ QString talkerName = talkerCode.getTranslatedDescription();
+ if (!eventSrcName.isEmpty() && !eventName.isEmpty() && !actionName.isEmpty() && !talkerName.isEmpty())
+ {
+ QListViewItem* parentItem = lv->findItem(eventSrcName, nlvcEventSrcName);
+ if (!parentItem)
+ {
+ item = lv->lastItem();
+ if (!item)
+ parentItem = new KListViewItem(lv, eventSrcName, QString::null, QString::null,
+ eventSrc);
+ else
+ parentItem = new KListViewItem(lv, item, eventSrcName, QString::null, QString::null,
+ eventSrc);
+ if ( !iconName.isEmpty() )
+ parentItem->setPixmap( nlvcEventSrcName, SmallIcon( iconName ) );
+ }
+ // No duplicates.
+ item = lv->findItem( event, nlvcEvent );
+ if ( !item || item->parent() != parentItem )
+ item = new KListViewItem(parentItem, eventName, actionDisplayName, talkerName,
+ eventSrc, event, actionName, talkerCode.getTalkerCode());
+ if ( action == NotifyAction::DoNotSpeak )
+ item->setPixmap( nlvcActionName, SmallIcon( "nospeak" ) );
+ else
+ item->setPixmap( nlvcActionName, SmallIcon( "speak" ) );
+ }
+ return item;
+}
+
+void KCMKttsMgr::slotNotifyAddButton_clicked()
+{
+ QListView* lv = m_kttsmgrw->notifyListView;
+ QListViewItem* item = lv->selectedItem();
+ QString eventSrc;
+ if ( item ) eventSrc = item->text( nlvcEventSrc );
+ SelectEvent* selectEventWidget = new SelectEvent( this, "SelectEvent_widget", 0, eventSrc );
+ KDialogBase* dlg = new KDialogBase(
+ KDialogBase::Swallow,
+ i18n("Select Event"),
+ KDialogBase::Help|KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Cancel,
+ m_kttsmgrw,
+ "SelectEvent_dlg",
+ true,
+ true);
+ dlg->setMainWidget( selectEventWidget );
+ dlg->setInitialSize( QSize(500, 400) );
+ // dlg->setHelp("select-plugin", "kttsd");
+ int dlgResult = dlg->exec();
+ eventSrc = selectEventWidget->getEventSrc();
+ QString event = selectEventWidget->getEvent();
+ delete dlg;
+ if ( dlgResult != QDialog::Accepted ) return;
+ if ( eventSrc.isEmpty() || event.isEmpty() ) return;
+ // Use Default action, message, and talker.
+ QString actionName;
+ int action = NotifyAction::DoNotSpeak;
+ QString msg;
+ TalkerCode talkerCode;
+ item = lv->findItem( "default", nlvcEventSrc );
+ if ( item )
+ {
+ if ( item->childCount() > 0 ) item = item->firstChild();
+ if ( item )
+ {
+ actionName = item->text( nlvcAction );
+ action = NotifyAction::action( actionName );
+ talkerCode = TalkerCode( item->text( nlvcTalker ) );
+ if (action == NotifyAction::SpeakCustom )
+ {
+ msg = item->text(nlvcActionName);
+ int msglen = msg.length();
+ msg = msg.mid( 1, msglen-2 );
+ }
+ }
+ }
+ item = addNotifyItem( eventSrc, event, action, msg, talkerCode );
+ lv->ensureItemVisible( item );
+ lv->setSelected( item, true );
+ slotNotifyListView_selectionChanged();
+ configChanged();
+}
+
+void KCMKttsMgr::slotNotifyClearButton_clicked()
+{
+ m_kttsmgrw->notifyListView->clear();
+ TalkerCode talkerCode( QString::null );
+ QListViewItem* item = addNotifyItem(
+ QString("default"),
+ NotifyPresent::presentName(NotifyPresent::Passive),
+ NotifyAction::SpeakEventName,
+ QString::null,
+ talkerCode );
+ QListView* lv = m_kttsmgrw->notifyListView;
+ lv->ensureItemVisible( item );
+ lv->setSelected( item, true );
+ slotNotifyListView_selectionChanged();
+ configChanged();
+}
+
+void KCMKttsMgr::slotNotifyRemoveButton_clicked()
+{
+ QListViewItem* item = m_kttsmgrw->notifyListView->selectedItem();
+ if (!item) return;
+ QListViewItem* parentItem = item->parent();
+ delete item;
+ if (parentItem)
+ {
+ if (parentItem->childCount() == 0) delete parentItem;
+ }
+ slotNotifyListView_selectionChanged();
+ configChanged();
+}
+
+void KCMKttsMgr::slotNotifyLoadButton_clicked()
+{
+ // QString dataDir = KGlobal::dirs()->resourceDirs("data").last() + "/kttsd/stringreplacer/";
+ QString dataDir = KGlobal::dirs()->findAllResources("data", "kttsd/notify/").last();
+ QString filename = KFileDialog::getOpenFileName(
+ dataDir,
+ "*.xml|" + i18n("file type", "Notification Event List") + " (*.xml)",
+ m_kttsmgrw,
+ "event_loadfile");
+ if ( filename.isEmpty() ) return;
+ QString errMsg = loadNotifyEventsFromFile( filename, true );
+ slotNotifyListView_selectionChanged();
+ if ( !errMsg.isEmpty() )
+ KMessageBox::sorry( m_kttsmgrw, errMsg, i18n("Error Opening File") );
+ else
+ configChanged();
+}
+
+void KCMKttsMgr::slotNotifySaveButton_clicked()
+{
+ QString filename = KFileDialog::getSaveFileName(
+ KGlobal::dirs()->saveLocation( "data" ,"kttsd/notify/", false ),
+ "*.xml|" + i18n("file type", "Notification Event List") + " (*.xml)",
+ m_kttsmgrw,
+ "event_savefile");
+ if ( filename.isEmpty() ) return;
+ QString errMsg = saveNotifyEventsToFile( filename );
+ slotNotifyListView_selectionChanged();
+ if ( !errMsg.isEmpty() )
+ KMessageBox::sorry( m_kttsmgrw, errMsg, i18n("Error Opening File") );
+}
+
+// ----------------------------------------------------------------------------
+
+KttsCheckListItem::KttsCheckListItem( QListView *parent, QListViewItem *after,
+ const QString &text, Type tt,
+ KCMKttsMgr* kcmkttsmgr ) :
+ QCheckListItem(parent, after, text, tt),
+ m_kcmkttsmgr(kcmkttsmgr) { }
+
+KttsCheckListItem::KttsCheckListItem( QListView *parent,
+ const QString &text, Type tt,
+ KCMKttsMgr* kcmkttsmgr ) :
+ QCheckListItem(parent, text, tt),
+ m_kcmkttsmgr(kcmkttsmgr) { }
+
+/*virtual*/ void KttsCheckListItem::stateChange(bool)
+{
+ if (m_kcmkttsmgr) m_kcmkttsmgr->slotFiltersList_stateChanged();
+}
+
+/*virtual*/ /*void resizeEvent( QResizeEvent ev )
+{
+ dynamic_cast<KCModule>(resizeEvent(ev));
+ updateGeometry();
+}
+*/
diff --git a/kttsd/kcmkttsmgr/kcmkttsmgr.h b/kttsd/kcmkttsmgr/kcmkttsmgr.h
new file mode 100644
index 0000000..39481b9
--- /dev/null
+++ b/kttsd/kcmkttsmgr/kcmkttsmgr.h
@@ -0,0 +1,530 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ KControl module for KTTSD configuration and job management
+ -------------------
+ Copyright : (C) 2002-2003 by José Pablo Ezequiel "Pupeno" Fernández
+ Copyright : (C) 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
+ Current Maintainer: 2004 by Gary Cramblitt <garycramblitt@comcast.net>
+ ******************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; version 2 of the License. *
+ * *
+ ***************************************************************************/
+
+#ifndef KCMKTTSMGR_H
+#define KCMKTTSMGR_H
+
+#include "config.h"
+
+// Qt includes.
+#include <qmap.h>
+#include <qlistview.h>
+
+// KDE includes.
+#include <kcmodule.h>
+#include <ktrader.h>
+#include <kdebug.h>
+#include <kparts/part.h>
+
+// KTTS includes.
+#include "addtalker.h"
+#include "kcmkttsmgrwidget.h"
+#include "kspeech_stub.h"
+#include "kspeechsink.h"
+
+class PlugInConf;
+class KttsFilterConf;
+class KListViewItem;
+class KAboutData;
+class KConfig;
+class QPopupMenu;
+
+/**
+* @author José Pablo Ezequiel "Pupeno" Fernández
+* @author Gary Cramblitt
+*/
+
+class KCMKttsMgr :
+ public KCModule,
+ public KSpeech_stub,
+ virtual public KSpeechSink
+{
+ Q_OBJECT
+
+ public:
+ KCMKttsMgr(QWidget *parent, const char *name, const QStringList &);
+
+ ~KCMKttsMgr();
+
+ /**
+ * This method is invoked whenever the module should read its
+ * configuration (most of the times from a config file) and update the
+ * user interface. This happens when the user clicks the "Reset" button in
+ * the control center, to undo all of his changes and restore the currently
+ * valid settings. NOTE that this is not called after the modules is loaded,
+ * so you probably want to call this method in the constructor.
+ */
+ void load();
+
+ /**
+ * This function gets called when the user wants to save the settings in
+ * the user interface, updating the config files or wherever the
+ * configuration is stored. The method is called when the user clicks "Apply"
+ * or "Ok".
+ */
+ void save();
+
+ /**
+ * This function is called to set the settings in the module to sensible
+ * default values. It gets called when hitting the "Default" button. The
+ * default values should probably be the same as the ones the application
+ * uses when started without a config file.
+ */
+ void defaults();
+
+ /**
+ * This is a static method which gets called to realize the modules settings
+ * durign the startup of KDE. NOTE that most modules do not implement this
+ * method, but modules like the keyboard and mouse modules, which directly
+ * interact with the X-server, need this method. As this method is static,
+ * it can avoid to create an instance of the user interface, which is often
+ * not needed in this case.
+ */
+ static void init();
+
+ /**
+ * The control center calls this function to decide which buttons should
+ * be displayed. For example, it does not make sense to display an "Apply"
+ * button for one of the information modules. The value returned can be set by
+ * modules using setButtons.
+ */
+ int buttons();
+
+ /**
+ * This function returns the small quickhelp.
+ * That is displayed in the sidebar in the KControl
+ */
+ QString quickHelp() const;
+
+ /**
+ * Return the about information for this module
+ */
+ const KAboutData* aboutData() const;
+
+ public slots:
+ /**
+ * This slot is used to emit the signal changed when any widget changes the configuration
+ */
+ void configChanged()
+ {
+ if (!m_suppressConfigChanged)
+ {
+ // kdDebug() << "KCMKttsMgr::configChanged: Running"<< endl;
+ m_changed = true;
+ emit changed(true);
+ }
+ };
+ /**
+ * This slot is called whenever user checks/unchecks item in Filters list.
+ */
+ void slotFiltersList_stateChanged();
+
+ protected:
+ /** DCOP Methods connected to DCOP Signals emitted by KTTSD. */
+ /** Most of these are not used */
+
+ /**
+ * This signal is emitted when KTTSD starts or restarts after a call to reinit.
+ */
+ virtual void kttsdStarted();
+ /**
+ * This signal is emitted just before KTTSD exits.
+ */
+ virtual void kttsdExiting();
+
+ // virtual void resizeEvent( QResizeEvent ev );
+
+ private:
+ enum widgetPages
+ {
+ wpGeneral = 0, // General tab.
+ wpTalkers = 1, // Talkers tab.
+ wpNotify = 2, // Notify tab.
+ wpFilters = 3, // Filters tab.
+ wpInterruption = 4, // Interruption tab.
+ wpAudio = 5, // Audio tab.
+ wpJobs = 6 // Jobs tab.
+ };
+
+ enum NotifyListViewColumn
+ {
+ nlvcEventSrcName = 0,
+ nlvcEventName = 0,
+ nlvcActionName = 1,
+ nlvcTalkerName = 2,
+ nlvcEventSrc = 3, // hidden
+ nlvcEvent = 4, // hidden
+ nlvcAction = 5, // hidden
+ nlvcTalker = 6 // hidden
+ };
+
+ enum TalkerListViewColumn
+ {
+ tlvcTalkerID,
+ tlvcLanguage,
+ tlvcSynthName,
+ tlvcVoice,
+ tlvcGender,
+ tlvcVolume,
+ tlvcRate
+ };
+
+ enum FilterListViewColumn
+ {
+ flvcUserName, // Name of filter as set by user and displayed.
+ flvcFilterID, // Internal ID assigned to the filter (hidden).
+ flvcPlugInName, // Name of the filter plugin (from .desktop file, hidden).
+ flvcMultiInstance // True if multiple instances of this plugin are possible. (hidden)
+ };
+
+ enum SbdListViewColumn
+ {
+ slvcUserName, // Name of filter as set by user and displayed.
+ slvcFilterID, // Internal ID assigned to the filter (hidden).
+ slvcPlugInName, // Name of the filter plugin (from .desktop file, hidden).
+ slvcMultiInstance // True if multiple instances of this plugin are possible. (hidden)
+ };
+
+ enum SbdButtonIDs
+ {
+ sbdBtnEdit = 1,
+ sbdBtnUp = 2,
+ sbdBtnDown = 3,
+ sbdBtnAdd = 4,
+ sbdBtnRemove = 5
+ };
+
+ /**
+ * Conversion functions for percent boxes to/from sliders.
+ */
+ int percentToSlider(int percentValue);
+ int sliderToPercent(int sliderValue);
+
+ /**
+ * Given a language code and plugin name, returns a normalized default talker code.
+ * @param languageCode Language code.
+ * @param plugInName Name of the plugin.
+ * @return Full normalized talker code.
+ *
+ * Example returned from defaultTalkerCode("en", "Festival")
+ * <voice lang="en" name="fixed" gender="neutral"/>
+ * <prosody volume="medium" rate="medium"/>
+ * <kttsd synthesizer="Festival" />
+ */
+ QString defaultTalkerCode(const QString &languageCode, const QString &plugInName);
+
+ /**
+ * Given an item in the talker listview and a talker code, sets the columns of the item.
+ * @param talkerItem QListViewItem.
+ * @param talkerCode Talker Code.
+ */
+ void updateTalkerItem(QListViewItem* talkerItem, const QString &talkerCode);
+
+ /**
+ * Loads the configuration plugin for a named Talker plugin.
+ * @param name DesktopEntryName of the Synthesizer.
+ * @return Pointer to the configuration plugin for the Talker.
+ */
+ PlugInConf* loadTalkerPlugin(const QString& name);
+
+ /**
+ * Loads the configuration plugin for a named Filter plugin.
+ * @param plugInName DesktopEntryName of the plugin.
+ * @return Pointer to the configuration plugin for the Filter.
+ */
+ KttsFilterConf* loadFilterPlugin(const QString& plugInName);
+
+ /**
+ * Display the Talker Configuration Dialog.
+ */
+ void configureTalker();
+
+ /**
+ * Display the Filter Configuration Dialog.
+ */
+ void configureFilterItem( bool sbd );
+ void configureFilter();
+
+ /**
+ * Add a filter.
+ */
+ void addFilter( bool sbd );
+
+ /**
+ * Remove a filter.
+ */
+ void removeFilter( bool sbd );
+
+ /**
+ * Move an item in a KListView up or down.
+ */
+ void lowerItemPriority( KListView* lView );
+ void higherItemPriority( KListView* lView );
+
+ /**
+ * Count number of configured Filters with the specified plugin name.
+ */
+ int countFilterPlugins(const QString& filterPlugInName);
+
+ /**
+ * Uses KTrader to convert a translated Filter Plugin Name to DesktopEntryName.
+ * @param name The translated plugin name. From Name= line in .desktop file.
+ * @return DesktopEntryName. The name of the .desktop file (less .desktop).
+ * QString::null if not found.
+ */
+ QString FilterNameToDesktopEntryName(const QString& name);
+
+ /**
+ * Uses KTrader to convert a DesktopEntryName into a translated Filter Plugin Name.
+ * @param desktopEntryName The DesktopEntryName.
+ * @return The translated Name of the plugin, from Name= line in .desktop file.
+ */
+ QString FilterDesktopEntryNameToName(const QString& desktopEntryName);
+
+ /**
+ * Loads notify events from a file. Clearing listview if clear is True.
+ */
+ QString loadNotifyEventsFromFile( const QString& filename, bool clear);
+
+ /**
+ * Saves notify events to a file.
+ */
+ QString saveNotifyEventsToFile(const QString& filename);
+
+ /**
+ * Adds an item to the notify listview.
+ * message is only needed if action = nactSpeakCustom.
+ */
+ QListViewItem* addNotifyItem(
+ const QString& eventSrc,
+ const QString& event,
+ int action,
+ const QString& message,
+ TalkerCode& talkerCode);
+
+ /**
+ * Main widget
+ */
+ KCMKttsMgrWidget *m_kttsmgrw;
+
+ /**
+ * Object holding all the configuration
+ */
+ KConfig *m_config;
+
+ /**
+ * KTTS Job Manager.
+ */
+ KParts::ReadOnlyPart *m_jobMgrPart;
+
+ /**
+ * Plugin configuration dialog.
+ */
+ KDialogBase* m_configDlg;
+
+ /**
+ * Sentence Boundary Detector button popup menu.
+ */
+ QPopupMenu* m_sbdPopmenu;
+
+ /**
+ * Talker(synth) Plugin currently loaded into configuration dialog.
+ */
+ PlugInConf *m_loadedTalkerPlugIn;
+
+ /**
+ * Filter Plugin currently loaded into configuration dialog.
+ */
+ KttsFilterConf *m_loadedFilterPlugIn;
+
+ /**
+ * Last talker ID. Used to generate a new ID.
+ */
+ int m_lastTalkerID;
+
+ /**
+ * Last filter ID. Used to generate a new ID.
+ */
+ int m_lastFilterID;
+
+ /**
+ * Last SBD filter ID. Used to generate to new ID.
+ */
+ int m_lastSbdID;
+
+ /**
+ * True if the configuration has been changed.
+ */
+ bool m_changed;
+
+ /**
+ * When True, suppresses emission of changed() signal. Used to suppress this
+ * signal while loading configuration.
+ */
+ bool m_suppressConfigChanged;
+
+ /**
+ * Dictionary mapping language names to codes.
+ */
+ QMap<QString, QString> m_languagesToCodes;
+
+ /**
+ * A QMap of languages codes indexed by synthesizer that supports them.
+ */
+ SynthToLangMap m_synthToLangMap;
+
+ /**
+ * Default Talker Code for notifications.
+ */
+ QString m_defaultNotifyTalkerCode;
+
+ private slots:
+ /**
+ * Add a talker/filter.
+ * This is a wrapper function that takes the parameters for the real talker from the
+ * widgets to later call it.
+ */
+ void slot_addTalker();
+ void slot_addNormalFilter();
+ void slot_addSbdFilter();
+
+ /**
+ * Remove talker/filter.
+ * This is a wrapper function that takes the parameters for the real removeTalker from the
+ * widgets to later call it.
+ */
+ void slot_removeTalker();
+ void slot_removeNormalFilter();
+ void slot_removeSbdFilter();
+
+ /**
+ * This slot is called whenever user clicks the higher*Priority button (up).
+ */
+ void slot_higherTalkerPriority();
+ void slot_higherNormalFilterPriority();
+ void slot_higherSbdFilterPriority();
+
+ /**
+ * This slot is called whenever user clicks the lower*Priority button (down).
+ */
+ void slot_lowerTalkerPriority();
+ void slot_lowerNormalFilterPriority();
+ void slot_lowerSbdFilterPriority();
+
+ /**
+ * Update the status of the Talker/Filter buttons.
+ */
+ void updateTalkerButtons();
+ void updateFilterButtons();
+ void updateSbdButtons();
+
+ /**
+ * This signal is emitted whenever user checks/unchecks the Enable TTS System check box.
+ */
+ void enableKttsdToggled(bool checked);
+
+ /**
+ * This signal is emitted whenever user checks/unchecks the GStreamer radio button.
+ */
+ void slotGstreamerRadioButton_toggled(bool state);
+
+ /**
+ * This signal is emitted whenever user checks/unchecks the ALSA radio button.
+ */
+ void slotAlsaRadioButton_toggled(bool state);
+
+ /**
+ * This is emitted whenever user activates the ALSA pcm combobox.
+ */
+ void slotPcmComboBox_activated();
+
+ /**
+ * This signal is emitted whenever user checks/unchecks the aKode radio button.
+ */
+ void slotAkodeRadioButton_toggled(bool state);
+
+ /**
+ * User has requested to display the Talker/Filter Configuration Dialog.
+ */
+ void slot_configureTalker();
+ void slot_configureNormalFilter();
+ void slot_configureSbdFilter();
+
+ /**
+ * Slots for the Talker/Filter Configuration dialogs.
+ */
+ void slotConfigTalkerDlg_ConfigChanged();
+ void slotConfigFilterDlg_ConfigChanged();
+ void slotConfigTalkerDlg_DefaultClicked();
+ void slotConfigFilterDlg_DefaultClicked();
+ void slotConfigTalkerDlg_CancelClicked();
+ void slotConfigFilterDlg_CancelClicked();
+
+ /**
+ * Slots for Speed setting.
+ */
+ void timeBox_valueChanged(int percentValue);
+ void timeSlider_valueChanged(int sliderValue);
+
+ /**
+ * Keep Audio CheckBox slot.
+ */
+ void keepAudioCheckBox_toggled(bool checked);
+
+ /**
+ * Notify tab slots.
+ */
+ void slotNotifyEnableCheckBox_toggled(bool checked);
+ void slotNotifyAddButton_clicked();
+ void slotNotifyRemoveButton_clicked();
+ void slotNotifyClearButton_clicked();
+ void slotNotifyLoadButton_clicked();
+ void slotNotifySaveButton_clicked();
+ void slotNotifyListView_selectionChanged();
+ void slotNotifyPresentComboBox_activated(int index);
+ void slotNotifyActionComboBox_activated(int index);
+ void slotNotifyTestButton_clicked();
+ void slotNotifyMsgLineEdit_textChanged(const QString& text);
+ void slotNotifyTalkerButton_clicked();
+
+ /**
+ * Other slots.
+ */
+ void slotTabChanged();
+};
+
+/// This is a small helper class to detect when user checks/unchecks a Filter in Filters tab
+/// and emit changed() signal.
+class KttsCheckListItem : public QCheckListItem
+{
+ public:
+ KttsCheckListItem( QListView *parent,
+ const QString &text, Type tt = RadioButtonController,
+ KCMKttsMgr* kcmkttsmgr = 0);
+ KttsCheckListItem( QListView *parent, QListViewItem *after,
+ const QString &text, Type tt = RadioButtonController,
+ KCMKttsMgr* kcmkttsmgr = 0);
+
+ protected:
+ virtual void stateChange(bool);
+
+ private:
+ KCMKttsMgr* m_kcmkttsmgr;
+};
+
+#endif
diff --git a/kttsd/kcmkttsmgr/kcmkttsmgrwidget.ui b/kttsd/kcmkttsmgr/kcmkttsmgrwidget.ui
new file mode 100644
index 0000000..36942a3
--- /dev/null
+++ b/kttsd/kcmkttsmgr/kcmkttsmgrwidget.ui
@@ -0,0 +1,1928 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>KCMKttsMgrWidget</class>
+<author>Gary Cramblitt</author>
+<widget class="KCModule">
+ <property name="name">
+ <cstring>KCMKttsMgrWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>638</width>
+ <height>382</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>mainTab</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>&amp;General</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>enableKttsdCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Enable Text-to-Speech System (KTTSD)</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check to start the KTTS Deamon and enable Text-to-Speech.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>embedInSysTrayCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>Always em&amp;bed Text-to-Speech Manager in system tray</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>When checked, KTTSMgr displays an icon in the system tray, and clicking OK or Cancel buttons does not stop KTTSMgr. Use system tray context menu to quit KTTSMgr. This setting takes effect when KTTSMgr is next started. This setting has no effect when running in the KDE Control Center.</string>
+ </property>
+ </widget>
+ <spacer row="6" column="1">
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget" row="3" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>showMainWindowOnStartupCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>Show &amp;main window on startup</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>When checked, the KTTSMgr window is displayed when KTTSMgr starts. When unchecked, click on the icon in the system tray to display the KTTSMgr window.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="5" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout5_2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer5_2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>autoexitMgrCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>E&amp;xit when speaking is finished</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>When checked, and KTTSMgr was automatically started when speech began, automatically exits when speech has finished. Does not automatically exit if KTTSMgr was started manually or started from the Control Center.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QCheckBox" row="4" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>autostartMgrCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>Sta&amp;rt minimized in system tray when speaking</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>When checked, if KTTSMgr is not already running and speech begins, starts KTTSMgr and displays an icon in the system tray. &lt;em&gt;Note&lt;em&gt;: KTTSMgr only automatically starts for text jobs having 5 sentences or more.</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>&amp;Talkers</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KListView" row="0" column="0">
+ <column>
+ <property name="text">
+ <string>ID</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Language</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Speech Synthesizer</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Voice</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Gender</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Volume</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Rate</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>talkersList</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is a list of all the configured Talkers. A Talker is a speech synthesizer that has been configured with a language, voice, gender, speaking rate, and volume. Talkers higher in the list have higher priority. The topmost Talker will be used when no talker attributes have been specified by an application.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout9</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>addTalkerButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Add...</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to add and configure a new Talker (speech synthesizer).</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>higherTalkerPriorityButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>U&amp;p</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>lowerTalkerPriorityButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Do&amp;wn</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>configureTalkerButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Edit...</string>
+ </property>
+ <property name="toggleButton">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to configure options for the highlighted Talker.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>removeTalkerButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Remove</string>
+ </property>
+ <property name="toggleButton">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to remove the highlighted Talker.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer11</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>&amp;Notifications</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox" row="1" column="0">
+ <property name="name">
+ <cstring>notifyGroup</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="KListView" row="1" column="0">
+ <column>
+ <property name="text">
+ <string>Application/Event</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Action</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Talker</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>notifyListView</cstring>
+ </property>
+ <property name="rootIsDecorated">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is a list of configured application events and actions to be taken when received. The "default" event governs all events not specifically configured.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="0">
+ <property name="name">
+ <cstring>layout21</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>notifyPresentLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Notifications to speak:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>notifyWhatComboBox</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Applies only to the default event. Does not affect application-specific events. Only events that display in the manner which you select will be spoken.</string>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <property name="name">
+ <cstring>notifyPresentComboBox</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Applies only to the default event. Does not affect application-specific events. Only events that display in the manner which you select will be spoken.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout28</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>notifyAddButton</cstring>
+ </property>
+ <property name="text">
+ <string>Add...</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to configure notification for a specific application event.</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>notifyRemoveButton</cstring>
+ </property>
+ <property name="text">
+ <string>Re&amp;move</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to remove a specific notification event from the list. You cannot remove the default event.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer16</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>152</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>notifyClearButton</cstring>
+ </property>
+ <property name="text">
+ <string>Cl&amp;ear</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Removes all the application specific events. The default event remains.</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>notifyLoadButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Load...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to read configured notification events from a file.</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>notifySaveButton</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Save...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to write all the configured application events to a file.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="3" column="0">
+ <property name="name">
+ <cstring>notifyExceptionActionLayout</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton" row="0" column="2">
+ <property name="name">
+ <cstring>notifyTestButton</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Click to test notification</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click this button to test the notification. A sample message will be spoken. Note: The Text-to-Speech system must be enabled.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>notifyActionLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Ac&amp;tion:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>notifyActionComboBox</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Specifies how KTTS should speak the event when received. If you select "Speak custom text", enter the text in the box. You may use the following substitution strings in the text:&lt;dl&gt;&lt;dt&gt;%e&lt;/dt&gt;&lt;dd&gt;Name of the event&lt;/dd&gt;&lt;dt&gt;%a&lt;/dt&gt;&lt;dd&gt;Application that sent the event&lt;/dd&gt;&lt;dt&gt;%m&lt;/dt&gt;&lt;dd&gt;The message sent by the application&lt;/dd&gt;&lt;/dl&gt;&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit" row="0" column="3">
+ <property name="name">
+ <cstring>notifyMsgLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Specifies how KTTS should speak the event when received. If you select "Speak custom text", enter the text in the box. You may use the following substitution strings in the text:&lt;dl&gt;&lt;dt&gt;%e&lt;/dt&gt;&lt;dd&gt;Name of the event&lt;/dd&gt;&lt;dt&gt;%a&lt;/dt&gt;&lt;dd&gt;Application that sent the event&lt;/dd&gt;&lt;dt&gt;%m&lt;/dt&gt;&lt;dd&gt;The message sent by the application&lt;/dd&gt;&lt;/dl&gt;&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="1">
+ <property name="name">
+ <cstring>notifyActionComboBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Specifies how KTTS should speak the event when received. If you select "Speak custom text", enter the text in the box. You may use the following substitution strings in the text:&lt;dl&gt;&lt;dt&gt;%e&lt;/dt&gt;&lt;dd&gt;Name of the event&lt;/dd&gt;&lt;dt&gt;%a&lt;/dt&gt;&lt;dd&gt;Application that sent the event&lt;/dd&gt;&lt;dt&gt;%m&lt;/dt&gt;&lt;dd&gt;The message sent by the application&lt;/dd&gt;&lt;/dl&gt;&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget" row="4" column="0">
+ <property name="name">
+ <cstring>layout19_2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>notifyTalkerLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Talke&amp;r:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>notifyTalkerLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The Talker that will speak the notification. The "default" Talker is the topmost talker listed on the Talkers tab.</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>notifyTalkerLineEdit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="paletteForegroundColor">
+ <color>
+ <red>0</red>
+ <green>0</green>
+ <blue>0</blue>
+ </color>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The Talker that will speak the notification. The "default" Talker is the topmost talker listed on the Talkers tab.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>notifyTalkerButton</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to select the Talker to speak the notification.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout17</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>notifyEnableCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>Speak notifications (&amp;KNotify)</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>When checked and KTTS is enabled, notification events from applications sent via KNotify will be spoken according to the options you set on this tab.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer12</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>16</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>notifyExcludeEventsWithSoundCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>E&amp;xclude notifications with a sound</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>When checked, notification events that have a sound will not be spoken.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>&amp;Filters</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout14</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KListView">
+ <column>
+ <property name="text">
+ <string>Filter</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>filtersList</cstring>
+ </property>
+ <property name="fullWidth">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is a list of all the configured Filters. Filters higher in the list are applied first. Filters modify text before it is spoken. They can be used to substitute for mispronounced words, transform XML from one form to another, or change the default Talker to be used for speech output.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout9_2</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>addFilterButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Add...</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to add and configure a new Filter.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>higherFilterPriorityButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>U&amp;p</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to move selected filter up in the list. Filters higher in the list are applied first.</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>lowerFilterPriorityButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Do&amp;wn</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to move a filter down in the list. Filters lower in the list are applied last.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>configureFilterButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Edit...</string>
+ </property>
+ <property name="toggleButton">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to configure options for the highlighted Filter.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>removeFilterButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Remove</string>
+ </property>
+ <property name="toggleButton">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to remove the highlighted Filter.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer11_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>layout18</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KListView">
+ <column>
+ <property name="text">
+ <string>Sentence Boundary Detector</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>sbdsList</cstring>
+ </property>
+ <property name="fullWidth">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is a list of all the configured Sentence Boundary Detector (SBD) Filters. SBDs break long text jobs up into sentences, which reduces the time before a job begins speaking, and permits you to advance or rewind through a job. SBDs are applied in the order listed (top to bottom) after all the normal filters at the top of this screen have been applied. Filtering stops when the first SBD modifies the text.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout16</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>sbdButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Co&amp;nfigure</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click this button to edit the Sentence Boundary Detector (SBD) configuration or add additional SBD filters.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer11_2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>11</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>&amp;Interruption</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout15</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KURLRequester" row="1" column="1">
+ <property name="name">
+ <cstring>textPreSnd</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check the Pre-sound box and choose a Pre-sound audio file, which will sound when a text job is interrupted by another message.</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="2" column="1">
+ <property name="name">
+ <cstring>textPostMsg</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check the Post-message box and enter a Post-message, which will be spoken when a text job resumes after being interrupted by another message.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="0">
+ <property name="name">
+ <cstring>textPostMsgCheck</cstring>
+ </property>
+ <property name="text">
+ <string>Post-&amp;message:</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check the Post-message box and enter a Post-message, which will be spoken when a text job resumes after being interrupted by another message.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>textPreSndCheck</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Pre-sou&amp;nd:</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check the Pre-sound box and choose a Pre-sound audio file, which will sound when a text job is interrupted by another message.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>textPreMsgCheck</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Pre-message:</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="tristate">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check the Pre-message box and enter a Pre-message, which will be spoken whenever a text job is interrupted by another message.</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="3" column="1">
+ <property name="name">
+ <cstring>textPostSnd</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check the Post-sound and choose a Post-sound audio file, which will sound before a text job resumes after being interrupted by another message.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="3" column="0">
+ <property name="name">
+ <cstring>textPostSndCheck</cstring>
+ </property>
+ <property name="text">
+ <string>Post-s&amp;ound:</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check the Post-sound and choose a Post-sound audio file, which will sound before a text job resumes after being interrupted by another message.</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>textPreMsg</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check the Pre-message box and enter a Pre-message, which will be spoken whenever a text job is interrupted by another message.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>180</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>A&amp;udio</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout12</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>keepAudioCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Keep audio files:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check this if you want to keep the generated audio (wav) files. You will find them in the indicated directory.</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester">
+ <property name="name">
+ <cstring>keepAudioPath</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Specify the directory in which the audio files will be copied.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout13</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>timeLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Speed:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>timeBox</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the speed of speech. Slide the slider to the left to slow speech down; to the right to increase talking speed. Anything less than 75 percent is considered "slow", and anything greater than 125 percent is considered "fast". You cannot change the speed of MultiSyn voices.</string>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox">
+ <property name="name">
+ <cstring>timeBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="suffix">
+ <string> %</string>
+ </property>
+ <property name="maxValue">
+ <number>200</number>
+ </property>
+ <property name="minValue">
+ <number>50</number>
+ </property>
+ <property name="value">
+ <number>100</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the speed of speech. Slide the slider to the left to slow speech down; to the right to increase talking speed. Anything less than 75 percent is considered "slow", and anything greater than 125 percent is considered "fast". You cannot change the speed of MultiSyn voices.</string>
+ </property>
+ </widget>
+ <widget class="QSlider">
+ <property name="name">
+ <cstring>timeSlider</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="focusPolicy">
+ <enum>NoFocus</enum>
+ </property>
+ <property name="maxValue">
+ <number>1000</number>
+ </property>
+ <property name="lineStep">
+ <number>10</number>
+ </property>
+ <property name="pageStep">
+ <number>100</number>
+ </property>
+ <property name="value">
+ <number>500</number>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Sets the speed of speech. Slide the slider to the left to slow speech down; to the right to increase talking speed. Anything less than 75 percent is considered "slow", and anything greater than 125 percent is considered "fast". You cannot change the speed of MultiSyn voices.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <spacer row="3" column="0">
+ <property name="name">
+ <cstring>spacer8</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="0" column="1">
+ <property name="name">
+ <cstring>spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>90</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QButtonGroup" row="0" column="0">
+ <property name="name">
+ <cstring>audioButtonGroup</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Out&amp;put Using</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;Select the audio output method desired. If you select &lt;b&gt;GStreamer&lt;/b&gt;, you must also select a &lt;b&gt;Sink&lt;/b&gt;.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: You must have GStreamer &gt;= 0.87 to use GStreamer.&lt;/p&gt;</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="1" column="1">
+ <property name="name">
+ <cstring>layout8</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>sinkLabel</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Sink:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the sound sink to be used for GStreamer output.</string>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>sinkComboBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the sound sink to be used for GStreamer output.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="3" column="1">
+ <property name="name">
+ <cstring>layout8_2_2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>akodeSinkLabel</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Sink:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the sound sink to be used for aKode output.</string>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>akodeComboBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the sink to be used for aKode output. Select "auto" to let aKode pick the best output method.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>gstreamerRadioButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>GStrea&amp;mer</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>0</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;Check to use the GStreamer audio output system. You must also select a &lt;b&gt;Sink&lt;/b&gt; plugin.&lt;/p&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>artsRadioButton</cstring>
+ </property>
+ <property name="text">
+ <string>a&amp;Rts</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="buttonGroupId">
+ <number>0</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check to use the KDE aRts system for audio output.</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="3" column="0">
+ <property name="name">
+ <cstring>akodeRadioButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>aKode</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="buttonGroupId">
+ <number>0</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;Check to use aKode for audio output. You must also select a &lt;b&gt;Sink&lt;/b&gt;.&lt;/p&gt;</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout21</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>alsaRadioButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>ALSA</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="buttonGroupId">
+ <number>-1</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check to use Advanced Linux Sound Architecture (ALSA) for audio output.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout8_2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>pcmLabel</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Device:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the sound sink to be used for GStreamer output.</string>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>pcmComboBox</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Select the PCM device to be used for ALSA output. Select "default" to use the default ALSA device.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>pcmCustom</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>enableKttsdCheckBox</sender>
+ <signal>clicked()</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>embedInSysTrayCheckBox</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>showMainWindowOnStartupCheckBox</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>embedInSysTrayCheckBox</sender>
+ <signal>clicked()</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>showMainWindowOnStartupCheckBox</sender>
+ <signal>clicked()</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>artsRadioButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>gstreamerRadioButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>sinkComboBox</sender>
+ <signal>activated(int)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>autostartMgrCheckBox</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>autoexitMgrCheckBox</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>autostartMgrCheckBox</sender>
+ <signal>clicked()</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>autoexitMgrCheckBox</sender>
+ <signal>clicked()</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>pcmComboBox</sender>
+ <signal>activated(int)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>alsaRadioButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>akodeRadioButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>akodeComboBox</sender>
+ <signal>activated(int)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>textPreMsg</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>textPreMsgCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>textPreMsg</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>textPreMsgCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>textPreSndCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>textPreSnd</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>textPreSndCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>textPreSnd</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>textPostMsgCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>textPostMsg</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>textPostMsgCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>textPostMsg</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>textPostSndCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>textPostSnd</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>textPostSndCheck</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>textPostSnd</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+ <connection>
+ <sender>pcmCustom</sender>
+ <signal>textChanged(const QString&amp;)</signal>
+ <receiver>KCMKttsMgrWidget</receiver>
+ <slot>slotConfigChanged()</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>mainTab</tabstop>
+ <tabstop>enableKttsdCheckBox</tabstop>
+ <tabstop>embedInSysTrayCheckBox</tabstop>
+ <tabstop>showMainWindowOnStartupCheckBox</tabstop>
+ <tabstop>autostartMgrCheckBox</tabstop>
+ <tabstop>autoexitMgrCheckBox</tabstop>
+ <tabstop>talkersList</tabstop>
+ <tabstop>addTalkerButton</tabstop>
+ <tabstop>higherTalkerPriorityButton</tabstop>
+ <tabstop>lowerTalkerPriorityButton</tabstop>
+ <tabstop>configureTalkerButton</tabstop>
+ <tabstop>removeTalkerButton</tabstop>
+ <tabstop>notifyEnableCheckBox</tabstop>
+ <tabstop>notifyExcludeEventsWithSoundCheckBox</tabstop>
+ <tabstop>notifyAddButton</tabstop>
+ <tabstop>notifyRemoveButton</tabstop>
+ <tabstop>notifyClearButton</tabstop>
+ <tabstop>notifyLoadButton</tabstop>
+ <tabstop>notifySaveButton</tabstop>
+ <tabstop>notifyListView</tabstop>
+ <tabstop>notifyPresentComboBox</tabstop>
+ <tabstop>notifyActionComboBox</tabstop>
+ <tabstop>notifyTestButton</tabstop>
+ <tabstop>notifyMsgLineEdit</tabstop>
+ <tabstop>notifyTalkerLineEdit</tabstop>
+ <tabstop>notifyTalkerButton</tabstop>
+ <tabstop>filtersList</tabstop>
+ <tabstop>addFilterButton</tabstop>
+ <tabstop>higherFilterPriorityButton</tabstop>
+ <tabstop>lowerFilterPriorityButton</tabstop>
+ <tabstop>configureFilterButton</tabstop>
+ <tabstop>removeFilterButton</tabstop>
+ <tabstop>sbdsList</tabstop>
+ <tabstop>sbdButton</tabstop>
+ <tabstop>textPreMsgCheck</tabstop>
+ <tabstop>textPreMsg</tabstop>
+ <tabstop>textPreSndCheck</tabstop>
+ <tabstop>textPreSnd</tabstop>
+ <tabstop>textPostMsgCheck</tabstop>
+ <tabstop>textPostMsg</tabstop>
+ <tabstop>textPostSndCheck</tabstop>
+ <tabstop>textPostSnd</tabstop>
+ <tabstop>artsRadioButton</tabstop>
+ <tabstop>sinkComboBox</tabstop>
+ <tabstop>pcmComboBox</tabstop>
+ <tabstop>akodeComboBox</tabstop>
+ <tabstop>timeBox</tabstop>
+ <tabstop>keepAudioCheckBox</tabstop>
+ <tabstop>keepAudioPath</tabstop>
+</tabstops>
+<includes>
+ <include location="global" impldecl="in declaration">klocale.h</include>
+ <include location="global" impldecl="in implementation">klocale.h</include>
+ <include location="global" impldecl="in implementation">kdebug.h</include>
+</includes>
+<signals>
+ <signal>configChanged()</signal>
+</signals>
+<slots>
+ <slot access="private">slotConfigChanged()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="6"/>
+<includehints>
+ <includehint>kcmodule.h</includehint>
+ <includehint>klistview.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klistview.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klistview.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klistview.h</includehint>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kurlrequester.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>knuminput.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kcombobox.h</includehint>
+ <includehint>kcombobox.h</includehint>
+</includehints>
+</UI>
diff --git a/kttsd/kcmkttsmgr/kcmkttsmgrwidget.ui.h b/kttsd/kcmkttsmgr/kcmkttsmgrwidget.ui.h
new file mode 100644
index 0000000..206524a
--- /dev/null
+++ b/kttsd/kcmkttsmgr/kcmkttsmgrwidget.ui.h
@@ -0,0 +1,16 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+void KCMKttsMgrWidget::slotConfigChanged(){
+ // kdDebug() << "Running: KCMKttsMgrWidget:slotConfigChanged():" << endl;
+ emit configChanged();
+}
+
+
+
diff --git a/kttsd/kcmkttsmgr/selectevent.cpp b/kttsd/kcmkttsmgr/selectevent.cpp
new file mode 100644
index 0000000..dc65fa4
--- /dev/null
+++ b/kttsd/kcmkttsmgr/selectevent.cpp
@@ -0,0 +1,149 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Dialog to allow user to select a KNotify application and event.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+// Qt includes.
+#include <qcombobox.h>
+
+// KDE includes
+#include <kstandarddirs.h>
+#include <kconfig.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <klistview.h>
+#include <kiconloader.h>
+
+// KTTS includes
+#include "utils.h"
+#include "selectevent.h"
+
+SelectEvent::SelectEvent(QWidget* parent, const char* name, WFlags fl, const QString& initEventSrc)
+ : SelectEventWidget(parent,name,fl)
+{
+ // Load list of event sources (applications).
+ QStringList fullpaths =
+ KGlobal::dirs()->findAllResources("data", "*/eventsrc", false, true );
+ QStringList::ConstIterator it = fullpaths.begin();
+ QStringList relativePaths;
+ for ( ; it != fullpaths.end(); ++it)
+ {
+ QString relativePath = *it;
+ if ( relativePath.at(0) == '/' && KStandardDirs::exists( relativePath ) )
+ {
+ relativePath = makeRelative( relativePath );
+ relativePaths.append(relativePath);
+ }
+ }
+ relativePaths.sort();
+ it = relativePaths.begin();
+ for ( ; it != relativePaths.end(); ++it)
+ {
+ QString relativePath = *it;
+ if ( !relativePath.isEmpty() )
+ {
+ KConfig* config = new KConfig(relativePath, true, false, "data");
+ config->setGroup( QString::fromLatin1("!Global!") );
+ QString icon = config->readEntry(QString::fromLatin1("IconName"),
+ QString::fromLatin1("misc"));
+ QString description = config->readEntry( QString::fromLatin1("Comment"),
+ i18n("No description available") );
+ delete config;
+ int index = relativePath.find( '/' );
+ QString appname;
+ if ( index >= 0 )
+ appname = relativePath.left( index );
+ else
+ kdDebug() << "Cannot determine application name from path: " << relativePath << endl;
+ eventSrcComboBox->insertItem( SmallIcon( icon ), description );
+ m_eventSrcNames.append( appname );
+ if ( appname == initEventSrc ) KttsUtils::setCbItemFromText(eventSrcComboBox, description);
+ }
+ }
+ slotEventSrcComboBox_activated(eventSrcComboBox->currentItem());
+ connect (eventSrcComboBox, SIGNAL(activated(int)), this, SLOT(slotEventSrcComboBox_activated(int)));
+}
+
+SelectEvent::~SelectEvent() { }
+
+void SelectEvent::slotEventSrcComboBox_activated(int index)
+{
+ eventsListView->clear();
+ QListViewItem* item = 0;
+ QString eventSrc = m_eventSrcNames[index];
+ QString configFilename = eventSrc + QString::fromLatin1( "/eventsrc" );
+ KConfig* config = new KConfig( configFilename, true, false, "data" );
+ QStringList eventNames = config->groupList();
+ uint eventNamesCount = eventNames.count();
+ for (uint ndx = 0; ndx < eventNamesCount; ++ndx)
+ {
+ QString eventName = eventNames[ndx];
+ if ( eventName != "!Global!" )
+ {
+ config->setGroup( eventName );
+ QString eventDesc = config->readEntry( QString::fromLatin1( "Comment" ),
+ config->readEntry( QString::fromLatin1( "Name" )));
+ if ( !item )
+ item = new KListViewItem( eventsListView, eventDesc, eventName );
+ else
+ item = new KListViewItem( eventsListView, item, eventDesc, eventName );
+ }
+ }
+ delete config;
+ eventsListView->sort();
+ item = eventsListView->lastChild();
+ QString eventDesc = i18n("All other %1 events").arg(eventSrcComboBox->currentText());
+ if ( !item )
+ item = new KListViewItem( eventsListView, eventDesc, "default" );
+ else
+ item = new KListViewItem( eventsListView, item, eventDesc, "default" );
+
+}
+
+QString SelectEvent::getEventSrc()
+{
+ return m_eventSrcNames[eventSrcComboBox->currentItem()];
+}
+
+QString SelectEvent::getEvent()
+{
+ QListViewItem* item = eventsListView->currentItem();
+ if ( item )
+ return item->text(1);
+ else
+ return QString::null;
+}
+
+// returns e.g. "kwin/eventsrc" from a given path
+// "/opt/kde3/share/apps/kwin/eventsrc"
+QString SelectEvent::makeRelative( const QString& fullPath )
+{
+ int slash = fullPath.findRev( '/' ) - 1;
+ slash = fullPath.findRev( '/', slash );
+
+ if ( slash < 0 )
+ return QString::null;
+
+ return fullPath.mid( slash+1 );
+}
+
+
+#include "selectevent.moc"
diff --git a/kttsd/kcmkttsmgr/selectevent.h b/kttsd/kcmkttsmgr/selectevent.h
new file mode 100644
index 0000000..1ca4e21
--- /dev/null
+++ b/kttsd/kcmkttsmgr/selectevent.h
@@ -0,0 +1,69 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Dialog to allow user to select a KNotify application and event.
+ -------------------
+ Copyright:
+ (C) 2005 by Gary Cramblitt <garycramblitt@comcast.net>
+ -------------------
+ Original author: Gary Cramblitt <garycramblitt@comcast.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ ******************************************************************************/
+
+#ifndef _SELECTEVENT_H_
+#define _SELECTEVENT_H_
+
+#include "selecteventwidget.h"
+
+class SelectEvent : public SelectEventWidget
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructor.
+ * @param parent Inherited KDialog parameter.
+ * @param name Inherited KDialog parameter.
+ * @param initEventSrc Event source to start with.
+ */
+ SelectEvent(QWidget* parent = 0, const char* name = 0, WFlags fl = 0,
+ const QString& initEventSrc = QString::null );
+
+ /**
+ * Destructor.
+ */
+ ~SelectEvent();
+
+ /**
+ * Returns the chosen event source (app name).
+ */
+ QString getEventSrc();
+
+ /**
+ * Returns the chosen event.
+ */
+ QString getEvent();
+
+private slots:
+ void slotEventSrcComboBox_activated(int index);
+
+private:
+ // returns e.g. "kwin/eventsrc" from a given path
+ // "/opt/kde3/share/apps/kwin/eventsrc"
+ QString makeRelative( const QString& fullPath );
+
+ QStringList m_eventSrcNames;
+};
+
+#endif // _SELECTEVENT_H_
diff --git a/kttsd/kcmkttsmgr/selecteventwidget.ui b/kttsd/kcmkttsmgr/selecteventwidget.ui
new file mode 100644
index 0000000..13b91f1
--- /dev/null
+++ b/kttsd/kcmkttsmgr/selecteventwidget.ui
@@ -0,0 +1,62 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>SelectEventWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>SelectEventWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>472</width>
+ <height>326</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>eventSrcLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Event source:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>eventSrcComboBox</cstring>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="0" column="1">
+ <property name="name">
+ <cstring>eventSrcComboBox</cstring>
+ </property>
+ </widget>
+ <widget class="KListView" row="1" column="0" rowspan="1" colspan="2">
+ <column>
+ <property name="text">
+ <string>Events</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>eventsListView</cstring>
+ </property>
+ <property name="fullWidth">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klistview.h</includehint>
+</includehints>
+</UI>