summaryrefslogtreecommitdiffstats
path: root/kttsd/filters/stringreplacer
diff options
context:
space:
mode:
Diffstat (limited to 'kttsd/filters/stringreplacer')
-rw-r--r--kttsd/filters/stringreplacer/Makefile.am34
-rw-r--r--kttsd/filters/stringreplacer/abbreviations.xml58
-rw-r--r--kttsd/filters/stringreplacer/chat-de.xml616
-rw-r--r--kttsd/filters/stringreplacer/chat.xml616
-rw-r--r--kttsd/filters/stringreplacer/editreplacementwidget.ui263
-rw-r--r--kttsd/filters/stringreplacer/emoticons.xml304
-rw-r--r--kttsd/filters/stringreplacer/festival_unspeakable_chars.xml94
-rw-r--r--kttsd/filters/stringreplacer/kmail.xml31
-rw-r--r--kttsd/filters/stringreplacer/kttsd_stringreplacerplugin.desktop92
-rw-r--r--kttsd/filters/stringreplacer/polish_festival_fixes.xml12
-rw-r--r--kttsd/filters/stringreplacer/polish_festival_unspeakables.xml78
-rw-r--r--kttsd/filters/stringreplacer/qt2plaintext.xml359
-rw-r--r--kttsd/filters/stringreplacer/stringreplacerconf.cpp725
-rw-r--r--kttsd/filters/stringreplacer/stringreplacerconf.h158
-rw-r--r--kttsd/filters/stringreplacer/stringreplacerconfwidget.ui474
-rw-r--r--kttsd/filters/stringreplacer/stringreplacerplugin.cpp32
-rw-r--r--kttsd/filters/stringreplacer/stringreplacerproc.cpp231
-rw-r--r--kttsd/filters/stringreplacer/stringreplacerproc.h97
18 files changed, 4274 insertions, 0 deletions
diff --git a/kttsd/filters/stringreplacer/Makefile.am b/kttsd/filters/stringreplacer/Makefile.am
new file mode 100644
index 0000000..b52085c
--- /dev/null
+++ b/kttsd/filters/stringreplacer/Makefile.am
@@ -0,0 +1,34 @@
+INCLUDES = \
+ -I$(top_srcdir)/kttsd/libkttsd -I$(top_builddir)/kttsd/libkttsd \
+ $(all_includes)
+
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = libkttsd_stringreplacerplugin.la
+
+libkttsd_stringreplacerplugin_la_SOURCES = \
+ stringreplacerconfwidget.ui \
+ editreplacementwidget.ui \
+ stringreplacerconf.cpp \
+ stringreplacerproc.cpp \
+ stringreplacerplugin.cpp
+libkttsd_stringreplacerplugin_la_LDFLAGS = $(KDE_PLUGIN) $(all_libraries)
+libkttsd_stringreplacerplugin_la_LIBADD = $(top_builddir)/kttsd/libkttsd/libkttsd.la
+
+services_DATA = kttsd_stringreplacerplugin.desktop
+servicesdir = $(kde_servicesdir)
+
+# Install data files.
+stringreplacerdatadir = $(kde_datadir)/kttsd/stringreplacer/
+stringreplacerdata_DATA = \
+ abbreviations.xml \
+ chat.xml \
+ chat-de.xml \
+ emoticons.xml \
+ polish_festival_fixes.xml \
+ polish_festival_unspeakables.xml \
+ kmail.xml \
+ festival_unspeakable_chars.xml \
+ qt2plaintext.xml
+
+noinst_HEADERS = stringreplacerconfwidget.h editreplacementwidget.h
diff --git a/kttsd/filters/stringreplacer/abbreviations.xml b/kttsd/filters/stringreplacer/abbreviations.xml
new file mode 100644
index 0000000..d04b7aa
--- /dev/null
+++ b/kttsd/filters/stringreplacer/abbreviations.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wordlist>
+ <name>Abbreviations</name>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[TODO]]></match>
+ <subst><![CDATA[To Do]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[CPU]]></match>
+ <subst><![CDATA[C P U]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[DCOP]]></match>
+ <subst><![CDATA[D Cop]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[IP]]></match>
+ <subst><![CDATA[I P]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[KDE]]></match>
+ <subst><![CDATA[K D E]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[KTTS]]></match>
+ <subst><![CDATA[K T T S]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[kttsd]]></match>
+ <subst><![CDATA[K T T S D]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[KTTSD]]></match>
+ <subst><![CDATA[K T T S D]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[TTS]]></match>
+ <subst><![CDATA[T T S]]></subst>
+ </word>
+</wordlist>
diff --git a/kttsd/filters/stringreplacer/chat-de.xml b/kttsd/filters/stringreplacer/chat-de.xml
new file mode 100644
index 0000000..801c144
--- /dev/null
+++ b/kttsd/filters/stringreplacer/chat-de.xml
@@ -0,0 +1,616 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wordlist>
+ <name>Internet Relay Chat and IM (Deutsch)</name>
+ <language-code>de</language-code>
+ <appid>knotify</appid>
+ <appid>kopete</appid>
+ <appid>kvirc</appid>
+ <appid>ksirc</appid>
+ <appid>konversation</appid>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<qt>]]></match>
+ <subst><![CDATA[ ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[&lt([^>]+)&gt]]></match>
+ <subst><![CDATA[ \1 meint ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<br>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</qt>]]></match>
+ <subst><![CDATA[ ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\;\)]]></match>
+ <subst><![CDATA[ winkt]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\<]]></match>
+ <subst><![CDATA[ traurig]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\/]]></match>
+ <subst><![CDATA[stirnrunzeln]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\>]]></match>
+ <subst><![CDATA[ grinst]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\|]]></match>
+ <subst><![CDATA[ernsthaft]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\-\|]]></match>
+ <subst><![CDATA[ernsthaft]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\-\)]]></match>
+ <subst><![CDATA[ laechelt]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\'\(]]></match>
+ <subst><![CDATA[weint]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\(]]></match>
+ <subst><![CDATA[ traurig]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\)]]></match>
+ <subst><![CDATA[ laechelt]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\@]]></match>
+ <subst><![CDATA[ boese]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\$]]></match>
+ <subst><![CDATA[ schaemt sich]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\@\)]]></match>
+ <subst><![CDATA[ katzengesicht]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(6\)]]></match>
+ <subst><![CDATA[ teufelsfratze]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(a\)]]></match>
+ <subst><![CDATA[ engelsgesicht]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:D]]></match>
+ <subst><![CDATA[ grins]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(h\)]]></match>
+ <subst><![CDATA[ kuhl]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\so\_O]]></match>
+ <subst><![CDATA[ winkt]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:p]]></match>
+ <subst><![CDATA[ baeh]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(s\)]]></match>
+ <subst><![CDATA[ gaehn]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ad]]></match>
+ <subst><![CDATA[fuege hinzu]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[afaik]]></match>
+ <subst><![CDATA[soviel ich weiss]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[afk]]></match>
+ <subst><![CDATA[nicht an tastatur]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[asap]]></match>
+ <subst><![CDATA[so schnell wie moeglich]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[atm]]></match>
+ <subst><![CDATA[momentan]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ayt]]></match>
+ <subst><![CDATA[bist du da]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[b4]]></match>
+ <subst><![CDATA[vorher]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[b4n]]></match>
+ <subst><![CDATA[tschuess]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[bak]]></match>
+ <subst><![CDATA[zurueck]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[bbl]]></match>
+ <subst><![CDATA[komme spaeter wieder]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[bf]]></match>
+ <subst><![CDATA[freund]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[b/f]]></match>
+ <subst><![CDATA[freund]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[brb]]></match>
+ <subst><![CDATA[bin gleich wieder da]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[btw]]></match>
+ <subst><![CDATA[nebenbei bemerkt]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[cu]]></match>
+ <subst><![CDATA[bis dann]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[cul]]></match>
+ <subst><![CDATA[bis spaeter]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[cul8r]]></match>
+ <subst><![CDATA[bis spaeter]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[cya]]></match>
+ <subst><![CDATA[bis spaeter]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[d/l]]></match>
+ <subst><![CDATA[daunlohd]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[dvd]]></match>
+ <subst><![CDATA[die wie die]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[f2f]]></match>
+ <subst><![CDATA[von angesicht zu angesicht]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[fubar]]></match>
+ <subst><![CDATA[leuft trotz reparatur nicht]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[fyi]]></match>
+ <subst><![CDATA[zu deiner information]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[gf]]></match>
+ <subst><![CDATA[freundin]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[g/f]]></match>
+ <subst><![CDATA[freundin]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[gtg]]></match>
+ <subst><![CDATA[ich muss weck]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[hmm]]></match>
+ <subst><![CDATA[aehm]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[hth]]></match>
+ <subst><![CDATA[hoffe es hilft]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ic]]></match>
+ <subst><![CDATA[verstehe]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[iirc]]></match>
+ <subst><![CDATA[wenn ich recht erinnere]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[imao]]></match>
+ <subst><![CDATA[meiner arroganten meinung nach]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[imco]]></match>
+ <subst><![CDATA[meiner wohlueberlegten meinung nach]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ime]]></match>
+ <subst><![CDATA[meiner erfahrung nach]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[imho]]></match>
+ <subst><![CDATA[meiner bescheidenen meinung nach]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[imnsho]]></match>
+ <subst><![CDATA[meiner unbescheidenen meinung nach]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[imo]]></match>
+ <subst><![CDATA[meiner meinung nach]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ip]]></match>
+ <subst><![CDATA[ei pie]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[isdn]]></match>
+ <subst><![CDATA[i es de en]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[k]]></match>
+ <subst><![CDATA[ho key]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[kde]]></match>
+ <subst><![CDATA[ka de eh]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[kbd]]></match>
+ <subst><![CDATA[tastatur]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[lshmba]]></match>
+ <subst><![CDATA[halte mir den bauch vor lachen]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[lthtt]]></match>
+ <subst><![CDATA[unbeschreibliches gelaechter]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ltns]]></match>
+ <subst><![CDATA[lange nicht gesehen]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[lol]]></match>
+ <subst><![CDATA[h h h]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[m8]]></match>
+ <subst><![CDATA[kumpel]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[msg]]></match>
+ <subst><![CDATA[nachricht]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[np]]></match>
+ <subst><![CDATA[kein problem]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[oic]]></match>
+ <subst><![CDATA[oh verstehe]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ok]]></match>
+ <subst><![CDATA[ho key]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ott]]></match>
+ <subst><![CDATA[übertreiben]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[pc]]></match>
+ <subst><![CDATA[pie cie]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ppc]]></match>
+ <subst><![CDATA[power pie cie]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ppl]]></match>
+ <subst><![CDATA[leute]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[rotfl]]></match>
+ <subst><![CDATA[kugelt sich vor lachen]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[rotflol]]></match>
+ <subst><![CDATA[bruellt vor lachen]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[rsvp]]></match>
+ <subst><![CDATA[antworte bitte]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[scsi]]></match>
+ <subst><![CDATA[skasi]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[suse]]></match>
+ <subst><![CDATA[suse]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[sec]]></match>
+ <subst><![CDATA[sekunde]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[secs]]></match>
+ <subst><![CDATA[sekunden]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[thx]]></match>
+ <subst><![CDATA[danke]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[tnx]]></match>
+ <subst><![CDATA[danke]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wo]]></match>
+ <subst><![CDATA[ohne]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wb]]></match>
+ <subst><![CDATA[willkommen urueck]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wtf]]></match>
+ <subst><![CDATA[was zum teufel]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wth]]></match>
+ <subst><![CDATA[was zum teufel]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wtg]]></match>
+ <subst><![CDATA[gut gemacht]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wtgp]]></match>
+ <subst><![CDATA[bitte um privatchett]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wth]]></match>
+ <subst><![CDATA[was zum teufel]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wygiswypf]]></match>
+ <subst><![CDATA[was du kriegst ist was du bezahlst]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[yw]]></match>
+ <subst><![CDATA[gruess diche]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\_]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\|]]></match>
+ <subst><![CDATA[ ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\\o\/]]></match>
+ <subst><![CDATA[tschuess]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\/o\\]]></match>
+ <subst><![CDATA[haelt sich die ohren zu]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\:\-\/]]></match>
+ <subst><![CDATA[stirnrunzeln]]></subst>
+ </word>
+</wordlist>
diff --git a/kttsd/filters/stringreplacer/chat.xml b/kttsd/filters/stringreplacer/chat.xml
new file mode 100644
index 0000000..2518824
--- /dev/null
+++ b/kttsd/filters/stringreplacer/chat.xml
@@ -0,0 +1,616 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wordlist>
+ <name>Internet Relay Chat and IM</name>
+ <language-code>en</language-code>
+ <appid>knotify</appid>
+ <appid>kopete</appid>
+ <appid>kvirc</appid>
+ <appid>ksirc</appid>
+ <appid>konversation</appid>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<qt>]]></match>
+ <subst><![CDATA[ ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[&lt([^>]+)&gt]]></match>
+ <subst><![CDATA[ \1 says ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<br>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</qt>]]></match>
+ <subst><![CDATA[ ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\;\)]]></match>
+ <subst><![CDATA[ winks]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\<]]></match>
+ <subst><![CDATA[ sad face]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\/]]></match>
+ <subst><![CDATA[ frowns ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\>]]></match>
+ <subst><![CDATA[ grins]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\|]]></match>
+ <subst><![CDATA[ straight faced]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\-\|]]></match>
+ <subst><![CDATA[ straight faced]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\-\)]]></match>
+ <subst><![CDATA[ smiles]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\'\(]]></match>
+ <subst><![CDATA[ cries]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\(]]></match>
+ <subst><![CDATA[ sad face]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\)]]></match>
+ <subst><![CDATA[ smiles]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\@]]></match>
+ <subst><![CDATA[ angry look]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\$]]></match>
+ <subst><![CDATA[ blushes]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\@\)]]></match>
+ <subst><![CDATA[ cat face]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(6\)]]></match>
+ <subst><![CDATA[ devil]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(a\)]]></match>
+ <subst><![CDATA[ angel]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:D]]></match>
+ <subst><![CDATA[ grins]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(h\)]]></match>
+ <subst><![CDATA[ cool shades]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\so\_O]]></match>
+ <subst><![CDATA[ winks]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:p]]></match>
+ <subst><![CDATA[ sticks out tung]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(s\)]]></match>
+ <subst><![CDATA[ sleepy]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ad]]></match>
+ <subst><![CDATA[add]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[afaik]]></match>
+ <subst><![CDATA[as far as I know]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[afk]]></match>
+ <subst><![CDATA[away from keyboard]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[asap]]></match>
+ <subst><![CDATA[as soon as possable]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[atm]]></match>
+ <subst><![CDATA[at the moment]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ayt]]></match>
+ <subst><![CDATA[are you there]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[b4]]></match>
+ <subst><![CDATA[before]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[b4n]]></match>
+ <subst><![CDATA[bye for now]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[bak]]></match>
+ <subst><![CDATA[back]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[bbl]]></match>
+ <subst><![CDATA[be back later]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[bf]]></match>
+ <subst><![CDATA[boy friend]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[b/f]]></match>
+ <subst><![CDATA[boy friend]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[brb]]></match>
+ <subst><![CDATA[be right back]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[btw]]></match>
+ <subst><![CDATA[by the way]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[cu]]></match>
+ <subst><![CDATA[see you]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[cul]]></match>
+ <subst><![CDATA[see you later]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[cul8r]]></match>
+ <subst><![CDATA[see you later]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[cya]]></match>
+ <subst><![CDATA[see you later]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[d/l]]></match>
+ <subst><![CDATA[down load]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[dvd]]></match>
+ <subst><![CDATA[de vee de]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[f2f]]></match>
+ <subst><![CDATA[face to face]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[fubar]]></match>
+ <subst><![CDATA[fecked up beyond all repair]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[fyi]]></match>
+ <subst><![CDATA[for your information]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[gf]]></match>
+ <subst><![CDATA[girl friend]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[g/f]]></match>
+ <subst><![CDATA[girl friend]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[gtg]]></match>
+ <subst><![CDATA[got to go]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[hmm]]></match>
+ <subst><![CDATA[hurrmmm]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[hth]]></match>
+ <subst><![CDATA[hope that helps]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ic]]></match>
+ <subst><![CDATA[i see]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[iirc]]></match>
+ <subst><![CDATA[if I recall correctly]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[imao]]></match>
+ <subst><![CDATA[in my arrogant opinion]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[imco]]></match>
+ <subst><![CDATA[in my considered opinion]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ime]]></match>
+ <subst><![CDATA[in my experience]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[imho]]></match>
+ <subst><![CDATA[in my humble opinion]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[imnsho]]></match>
+ <subst><![CDATA[in my not so humble opinion]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[imo]]></match>
+ <subst><![CDATA[in my opinion]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ip]]></match>
+ <subst><![CDATA[i p]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[isdn]]></match>
+ <subst><![CDATA[i s d n]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[k]]></match>
+ <subst><![CDATA[ho kay]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[kde]]></match>
+ <subst><![CDATA[k d e]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[kbd]]></match>
+ <subst><![CDATA[keyboard]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[lshmba]]></match>
+ <subst><![CDATA[laughing so hard my belly aches]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[lthtt]]></match>
+ <subst><![CDATA[laughing too hard to type]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ltns]]></match>
+ <subst><![CDATA[long time no see]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[lol]]></match>
+ <subst><![CDATA[lafes out loud]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[m8]]></match>
+ <subst><![CDATA[mate]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[msg]]></match>
+ <subst><![CDATA[message]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[np]]></match>
+ <subst><![CDATA[no problem]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[oic]]></match>
+ <subst><![CDATA[oh i see]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ok]]></match>
+ <subst><![CDATA[ho kay]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ott]]></match>
+ <subst><![CDATA[over the top]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[pc]]></match>
+ <subst><![CDATA[p c]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ppc]]></match>
+ <subst><![CDATA[power p c]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[ppl]]></match>
+ <subst><![CDATA[people]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[rotfl]]></match>
+ <subst><![CDATA[rolling on the floor laughing]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[rotflol]]></match>
+ <subst><![CDATA[rolling on the floor laughing out loud]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[rsvp]]></match>
+ <subst><![CDATA[please reply]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[scsi]]></match>
+ <subst><![CDATA[scuzy]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[suse]]></match>
+ <subst><![CDATA[sue see]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[sec]]></match>
+ <subst><![CDATA[second]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[secs]]></match>
+ <subst><![CDATA[seconds]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[thx]]></match>
+ <subst><![CDATA[thanks]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[tnx]]></match>
+ <subst><![CDATA[thanks]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wo]]></match>
+ <subst><![CDATA[without]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wb]]></match>
+ <subst><![CDATA[welcome back]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wtf]]></match>
+ <subst><![CDATA[what the heck]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wth]]></match>
+ <subst><![CDATA[what the heck]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wtg]]></match>
+ <subst><![CDATA[way to go]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wtgp]]></match>
+ <subst><![CDATA[want to go private]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wth]]></match>
+ <subst><![CDATA[what the heck]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[wygiswypf]]></match>
+ <subst><![CDATA[what you get is what you pay for]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[yw]]></match>
+ <subst><![CDATA[your welcome]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\_]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\|]]></match>
+ <subst><![CDATA[ ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\\o\/]]></match>
+ <subst><![CDATA[ cheers ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\/o\\]]></match>
+ <subst><![CDATA[ covers ears ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\:\-\/]]></match>
+ <subst><![CDATA[ frowns ]]></subst>
+ </word>
+</wordlist>
diff --git a/kttsd/filters/stringreplacer/editreplacementwidget.ui b/kttsd/filters/stringreplacer/editreplacementwidget.ui
new file mode 100644
index 0000000..917cdf8
--- /dev/null
+++ b/kttsd/filters/stringreplacer/editreplacementwidget.ui
@@ -0,0 +1,263 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>EditReplacementWidget</class>
+<author>Gary Cramblitt &lt;garycramblitt@comcast.net&gt;</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>EditReplacementWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>393</width>
+ <height>148</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>255</horstretch>
+ <verstretch>255</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>typeButtonGroup</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>&amp;Type</string>
+ </property>
+ <property name="exclusive">
+ <bool>true</bool>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>wordRadioButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Word</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>regexpRadioButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Regular &amp;expression</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>caseCheckBox</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Match &amp;case</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>substLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Replace with:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>matchLineEdit</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>matchLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Match:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>matchLineEdit</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>substLineEdit</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="KPushButton" row="0" column="1">
+ <property name="name">
+ <cstring>matchButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit" row="0" column="0">
+ <property name="name">
+ <cstring>matchLineEdit</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>wordRadioButton</tabstop>
+ <tabstop>regexpRadioButton</tabstop>
+ <tabstop>caseCheckBox</tabstop>
+ <tabstop>matchLineEdit</tabstop>
+ <tabstop>matchButton</tabstop>
+ <tabstop>substLineEdit</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klineedit.h</includehint>
+</includehints>
+</UI>
diff --git a/kttsd/filters/stringreplacer/emoticons.xml b/kttsd/filters/stringreplacer/emoticons.xml
new file mode 100644
index 0000000..f522358
--- /dev/null
+++ b/kttsd/filters/stringreplacer/emoticons.xml
@@ -0,0 +1,304 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wordlist>
+ <name>Emoticons (English)</name>
+ <language-code>en</language-code>
+ <appid>knotify</appid>
+ <appid>kopete</appid>
+ <appid>ksirc</appid>
+ <appid>kvirc</appid>
+ <appid>konversation</appid>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\)]]></match>
+ <subst><![CDATA[. smiles]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\-\)]]></match>
+ <subst><![CDATA[. smiles]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\p]]></match>
+ <subst><![CDATA[. sticks out tung]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:D]]></match>
+ <subst><![CDATA[. grins]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\>]]></match>
+ <subst><![CDATA[.grins]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\;\)]]></match>
+ <subst><![CDATA[. winks]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\o\_\0]]></match>
+ <subst><![CDATA[. winks]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\(]]></match>
+ <subst><![CDATA[. sad face]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\<]]></match>
+ <subst><![CDATA[. sad face]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\\:\|]]></match>
+ <subst><![CDATA[. straight faced]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\-\|]]></match>
+ <subst><![CDATA[. straight faced]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\$]]></match>
+ <subst><![CDATA[. blushes]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\\(h\)]]></match>
+ <subst><![CDATA[. cool shades]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\@]]></match>
+ <subst><![CDATA[. angry look]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\'\(]]></match>
+ <subst><![CDATA[. cries]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(a\)]]></match>
+ <subst><![CDATA[. angel]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(6\)]]></match>
+ <subst><![CDATA[. devil]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\%\)]]></match>
+ <subst><![CDATA[. hand cuffs]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\:\[\]]></match>
+ <subst><![CDATA[. bat]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\@\)]]></match>
+ <subst><![CDATA[. cat face]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\&\)]]></match>
+ <subst><![CDATA[. dog face]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\*\)]]></match>
+ <subst><![CDATA[. star]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(s\)]]></match>
+ <subst><![CDATA[. sleepy]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(Y\)]]></match>
+ <subst><![CDATA[. thumbs up]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(n\)]]></match>
+ <subst><![CDATA[. thumbs down]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\}\)]]></match>
+ <subst><![CDATA[. girl huggs]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\{\)]]></match>
+ <subst><![CDATA[. boy huggs]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(l\)]]></match>
+ <subst><![CDATA[. love]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(U\)]]></match>
+ <subst><![CDATA[. is hart brooken]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(k\)]]></match>
+ <subst><![CDATA[. kisses]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\^\)]]></match>
+ <subst><![CDATA[. birthday cake]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(g\)]]></match>
+ <subst><![CDATA[. a gift]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(f\)]]></match>
+ <subst><![CDATA[. flower]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(w\)]]></match>
+ <subst><![CDATA[. willted flower]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(t\)]]></match>
+ <subst><![CDATA[. telephone]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(e\)]]></match>
+ <subst><![CDATA[. e mail]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(m\)]]></match>
+ <subst><![CDATA[. messenger]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(o\)]]></match>
+ <subst><![CDATA[. time]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(x\)]]></match>
+ <subst><![CDATA[. girl]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(z\)]]></match>
+ <subst><![CDATA[. boy]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(p\)]]></match>
+ <subst><![CDATA[. picture]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\~\)]]></match>
+ <subst><![CDATA[. film]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(b\)]]></match>
+ <subst><![CDATA[. glass of beer]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(d\)]]></match>
+ <subst><![CDATA[. glass of wine]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(\#\)]]></match>
+ <subst><![CDATA[. sunny]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(r\)]]></match>
+ <subst><![CDATA[. rainbow]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(8\)]]></match>
+ <subst><![CDATA[. note]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(i\)]]></match>
+ <subst><![CDATA[. idea]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\s\(c\)]]></match>
+ <subst><![CDATA[. coffee cup]]></subst>
+ </word>
+</wordlist>
diff --git a/kttsd/filters/stringreplacer/festival_unspeakable_chars.xml b/kttsd/filters/stringreplacer/festival_unspeakable_chars.xml
new file mode 100644
index 0000000..5086d01
--- /dev/null
+++ b/kttsd/filters/stringreplacer/festival_unspeakable_chars.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wordlist>
+ <name>Fix Festival Unspeakable Characters</name>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\x80]]></match>
+ <subst><![CDATA[ Euro ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\x82]]></match>
+ <subst><![CDATA[']]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\x84]]></match>
+ <subst><![CDATA["]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\x85]]></match>
+ <subst><![CDATA[...]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\x89]]></match>
+ <subst><![CDATA[ per Mille ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\x8B]]></match>
+ <subst><![CDATA[<]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[[\x91-\x92]]]></match>
+ <subst><![CDATA[']]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[[\x93-\x94]]]></match>
+ <subst><![CDATA["]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[[\x96-\x97]]]></match>
+ <subst><![CDATA[-]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\x98]]></match>
+ <subst><![CDATA[~]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\x99]]></match>
+ <subst><![CDATA[ trademark ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\x9B]]></match>
+ <subst><![CDATA[>]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[[\x80-\x9F]]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\{]]></match>
+ <subst><![CDATA[ left curly brace ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\}]]></match>
+ <subst><![CDATA[ right curly brace ]]></subst>
+ </word>
+</wordlist>
diff --git a/kttsd/filters/stringreplacer/kmail.xml b/kttsd/filters/stringreplacer/kmail.xml
new file mode 100644
index 0000000..b0f33d6
--- /dev/null
+++ b/kttsd/filters/stringreplacer/kmail.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Filter by David Power achiestdragon@gmail.com -->
+<wordlist>
+ <name>kmail notify</name>
+ <appid>knotify</appid>
+ <appid>kmail</appid>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<br>]]></match>
+ <subst><![CDATA[,]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</b>]]></match>
+ <subst><![CDATA[,]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[in /local/inbox]]></match>
+ <subst><![CDATA[,]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<b>]]></match>
+ <subst><![CDATA[,]]></subst>
+ </word>
+</wordlist>
diff --git a/kttsd/filters/stringreplacer/kttsd_stringreplacerplugin.desktop b/kttsd/filters/stringreplacer/kttsd_stringreplacerplugin.desktop
new file mode 100644
index 0000000..df8214c
--- /dev/null
+++ b/kttsd/filters/stringreplacer/kttsd_stringreplacerplugin.desktop
@@ -0,0 +1,92 @@
+[Desktop Entry]
+Name=String Replacer
+Name[bg]=Замяна на низове
+Name[ca]=Reemplaçador de cadenes
+Name[cs]=Nahrazení řetězce
+Name[da]=Streng-erstatter
+Name[de]=Zeichenkettenersetzer
+Name[el]=Αντικαταστάτης συμβολοσειρών
+Name[es]=Reemplazador de cadenas
+Name[et]=Stringiasendaja
+Name[eu]=Kate-ordezkatzailea
+Name[fa]=جایگزین‌کنندۀ رشته
+Name[fi]=Tekstien korvaaja
+Name[fr]=Remplacement de chaînes
+Name[ga]=Ionadóir Teaghrán
+Name[gl]=Reemprazamento de Cadeas
+Name[he]=מחליף מחרוזות
+Name[hu]=Sztringcserélő
+Name[is]=Strengja útskiptir
+Name[it]=Sostitutore di stringhe
+Name[ja]=文字列置換
+Name[ka]=სტრიქონის ჩამნაცვლებელი
+Name[km]= ឧបករណ៍​ជំនួស​ខ្សែ​អក្សរ
+Name[lt]=Eilučių pakeitiklis
+Name[mk]=Менувач на низи знаци
+Name[ms]=Pengganti Rentetan
+Name[nb]=Strengerstatter
+Name[nds]=Tekenkeed-Tuscher
+Name[ne]=स्ट्रिङ प्रतिस्थापक
+Name[nl]=Tekstvervanger
+Name[pa]=ਸਤਰ ਤਬਦੀਲ
+Name[pl]=Zastępowanie tekstu
+Name[pt]=Substituição de Textos
+Name[pt_BR]=Substituidor de Strings
+Name[ru]=Автозамена
+Name[sk]=Náhrada reťazca
+Name[sl]=Zamenjevalnik nizov
+Name[sr]=Замењивач знаковних низова
+Name[sr@Latn]=Zamenjivač znakovnih nizova
+Name[sv]=Strängersättning
+Name[ta]=சர இடமாற்றி
+Name[tg]=Ҷойивазкунии автоматӣ
+Name[tr]=Metin Değiştirici
+Name[uk]=Заміна рядків
+Name[vi]=Trình thay Chuỗi
+Name[zh_TW]=字串置換器
+Comment=Generic String Replacement Filter Plugin for KTTS
+Comment[bg]=Приставка филтър за замяна на низове за KTTS
+Comment[ca]=Connector del filtre reemplaçador genèric de cadenes pel KTTS
+Comment[cs]=Modul filtru náhrady řetězce KTTS
+Comment[da]=Generisk strengerstatnings-filter-plugin for KTTS
+Comment[de]=Ein generisches Modul zur Zeichenkettenersetzung für KTTS
+Comment[el]=Γενικό φίλτρο πρόσθετο αντικατάστασης συμβολοσειρών για το KTTS
+Comment[es]=Complemento de filtro genérico de sustituición de cadenas para KTTS
+Comment[et]=KTTS-i üldine stringiasendusfiltri plugin
+Comment[eu]=KTTS-ren kateak ordezkatzeko iragazki-plugin generikoa
+Comment[fa]=وصلۀ پالایۀ جایگزینی رشتۀ عمومی برای KTTS
+Comment[fi]=Yleinen tekstien korvaussuodatinliitännäinen KTTS-ohjelmaan
+Comment[fr]=Module de filtrage de remplacement de chaînes générique pour KTTS
+Comment[gl]=Plugin de Filtro Xenérico de Substituición de Cadeas para KTTS
+Comment[hu]=Általános sztringcserélő modul a KTTS-hez
+Comment[is]=Almennt strengja útskiptinga íforrit fyrir KTTS
+Comment[it]=Plugin generico per il filtro di sostituzione di stringhe per KTTS
+Comment[ja]=KTTS 用汎用文字列置換フィルタプラグイン
+Comment[ka]=ზოგადი სტრიქონის ჩანაცვლების ფილტრის მოდული KTTS-სთვის
+Comment[km]=កម្មវិធី​ជំនួយ​តម្រង​ការ​ជំនួស​ខ្សែអក្សរ​ទូទៅ​សម្រាប់ KTTS
+Comment[lt]=Bendro pobūdžio eilučių pakeitimo filtro priedas, skirtas KTTS
+Comment[mk]=Филтер за KTTS за општа замена на низи знаци
+Comment[ms]=Plugin Penapis Penggantian Rentetan Generik bagi KTTS
+Comment[nb]=Filter-programtillegg til KTTS for streng-erstatning
+Comment[nds]=KTTS-Filtermoduul för dat Utwesseln vun Tekenkeden
+Comment[ne]=KTTS का लागि जेनेरीक स्ट्रिङ प्रतिस्थापन फिल्टर प्लगइन
+Comment[nl]=Generieke tekst-vervang-filter-plugin voor KTTS
+Comment[pl]=Wtyczka zastępowania tekstu dla KTTS
+Comment[pt]='Plugin' Genérico de Substituição de Textos para o KTTS
+Comment[pt_BR]=Plug-in de Filtro genérico de Substituição de Strings Para o KTTS
+Comment[ru]=Фильтр автозамены для KTTS
+Comment[sk]=Všeobecný modul filtra náhrady reťazca v KTTS
+Comment[sl]=Filtrni vstavek KTTS za generični zamenjevalnik nizov
+Comment[sr]=Генерички филтерски прикључак KTTS-а за замену знаковних низова
+Comment[sr@Latn]=Generički filterski priključak KTTS-a za zamenu znakovnih nizova
+Comment[sv]=Insticksprogram för KTTS med generellt strängersättningsfilter
+Comment[ta]=KTTSக்கான அலங்கார சொருகுபொருள் சர இடமாற்றி
+Comment[tg]=Филтри худивазкунӣ барои KTTS
+Comment[tr]=KTTS için Genel Metin Değiştirme Süzgeci Eklentisi
+Comment[uk]=Втулок загального фільтра заміни рядків для KTTS
+Comment[vi]=Trình bổ sung Lọc Thay Chuỗi Chung cho KTTS
+Comment[zh_TW]=KTTS 使用的字串置換外掛程式
+Type=Service
+ServiceTypes=KTTSD/FilterPlugin
+X-KDE-Library=libkttsd_stringreplacerplugin
+X-KDE-Languages=en,en_US,en_GB,en_CA,es,es_mx,cy,de,fi,cs,pl
diff --git a/kttsd/filters/stringreplacer/polish_festival_fixes.xml b/kttsd/filters/stringreplacer/polish_festival_fixes.xml
new file mode 100644
index 0000000..a6f2533
--- /dev/null
+++ b/kttsd/filters/stringreplacer/polish_festival_fixes.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Author of filter: Mikolaj Machowski ( mikmach AT wp DOT pl ) -->
+<wordlist>
+ <name>Filtr polski / Filter for Polish Festival voice</name>
+ <language-code>pl</language-code>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[[^a-zA-Z0-9ęóąśłżźćńĘÓĄŚŁŻŹĆŃ\,\"\'\\@#$%^*+=`~]]]></match>
+ <subst><![CDATA[ ]]></subst>
+ </word>
+</wordlist>
diff --git a/kttsd/filters/stringreplacer/polish_festival_unspeakables.xml b/kttsd/filters/stringreplacer/polish_festival_unspeakables.xml
new file mode 100644
index 0000000..8fbc18a
--- /dev/null
+++ b/kttsd/filters/stringreplacer/polish_festival_unspeakables.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Author of filter: Mikolaj Machowski ( mikmach AT wp DOT pl ) -->
+<wordlist>
+ <name>Polskie niewymawialne / Polish Festival unspeakables</name>
+ <language-code>pl</language-code>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\(]]></match>
+ <subst><![CDATA[ otwieram nawias ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\)]]></match>
+ <subst><![CDATA[ zamykam nawias ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\{]]></match>
+ <subst><![CDATA[ otwieram nawias klamrowy ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\}]]></match>
+ <subst><![CDATA[ zamykam nawias klamrowy ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\[]]></match>
+ <subst><![CDATA[ otwieram nawias kwadratowy ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\]]]></match>
+ <subst><![CDATA[ zamykam nawias kwadratowy ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\<]]></match>
+ <subst><![CDATA[ otwieram nawias trójkątny ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\>]]></match>
+ <subst><![CDATA[ zamykam nawias trójkątny ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\_]]></match>
+ <subst><![CDATA[ znak podkreślenia ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\&]]></match>
+ <subst><![CDATA[ i ]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[\/]]></match>
+ <subst><![CDATA[ slesz ]]></subst>
+ </word>
+ <word>
+ <type>Word</type>
+ <case>No</case>
+ <match><![CDATA[\\]]></match>
+ <subst><![CDATA[ bekslesz ]]></subst>
+ </word>
+</wordlist>
diff --git a/kttsd/filters/stringreplacer/qt2plaintext.xml b/kttsd/filters/stringreplacer/qt2plaintext.xml
new file mode 100644
index 0000000..8a194ec
--- /dev/null
+++ b/kttsd/filters/stringreplacer/qt2plaintext.xml
@@ -0,0 +1,359 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wordlist>
+ <name>Qt Rich Text to Plain Text</name>
+ <appid>knotify</appid>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<qt>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</qt>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<h1>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<h2>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<h3>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</h1>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</h2>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</h3>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<p>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</p>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<center>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</center>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<blockquote>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</blockquote>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<ul>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</ul>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<ol>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</ol>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<li>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</li>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<a>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</a>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<em>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</em>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<strong>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</strong>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<bold>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</bold>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<b>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</b>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<u>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</u>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<big>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</big>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<small>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</small>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<hr/>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<br/>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<nobr>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</nobr>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<table>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</table>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<tr>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</tr>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<td>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</td>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<th>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</th>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<img src\=]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<a href\=]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[/>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<img>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[">]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<pre>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</pre>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<tt>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</tt>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[<code>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+ <word>
+ <type>RegExp</type>
+ <case>No</case>
+ <match><![CDATA[</code>]]></match>
+ <subst><![CDATA[]]></subst>
+ </word>
+</wordlist>
diff --git a/kttsd/filters/stringreplacer/stringreplacerconf.cpp b/kttsd/filters/stringreplacer/stringreplacerconf.cpp
new file mode 100644
index 0000000..9afa2d5
--- /dev/null
+++ b/kttsd/filters/stringreplacer/stringreplacerconf.cpp
@@ -0,0 +1,725 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generic String Replacement Filter Configuration class.
+ -------------------
+ 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 <qfile.h>
+#include <qfileinfo.h>
+#include <qstring.h>
+#include <qhbox.h>
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qdom.h>
+#include <qfile.h>
+#include <qradiobutton.h>
+
+// KDE includes.
+#include <kglobal.h>
+#include <klocale.h>
+#include <klistview.h>
+#include <klineedit.h>
+#include <kdialog.h>
+#include <kdialogbase.h>
+#include <kpushbutton.h>
+#include <kconfig.h>
+#include <kstandarddirs.h>
+#include <kregexpeditorinterface.h>
+#include <ktrader.h>
+#include <kparts/componentfactory.h>
+#include <kfiledialog.h>
+#include <kmessagebox.h>
+
+// KTTS includes.
+#include "filterconf.h"
+
+// StringReplacer includes.
+#include "stringreplacerconf.h"
+#include "stringreplacerconf.moc"
+#include "editreplacementwidget.h"
+
+/**
+* Constructor
+*/
+StringReplacerConf::StringReplacerConf( QWidget *parent, const char *name, const QStringList& /*args*/) :
+ KttsFilterConf(parent, name),
+ m_editDlg(0),
+ m_editWidget(0)
+{
+ // kdDebug() << "StringReplacerConf::StringReplacerConf: Running" << endl;
+
+ // Create configuration widget.
+ QVBoxLayout *layout = new QVBoxLayout(this, KDialog::marginHint(),
+ KDialog::spacingHint(), "StringReplacerConfigWidgetLayout");
+ layout->setAlignment (Qt::AlignTop);
+ m_widget = new StringReplacerConfWidget(this, "StringReplacerConfigWidget");
+ layout->addWidget(m_widget);
+ m_widget->substLView->setSortColumn(-1);
+
+ connect(m_widget->nameLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()));
+ connect(m_widget->languageBrowseButton, SIGNAL(clicked()),
+ this, SLOT(slotLanguageBrowseButton_clicked()));
+ connect(m_widget->addButton, SIGNAL(clicked()),
+ this, SLOT(slotAddButton_clicked()));
+ connect(m_widget->upButton, SIGNAL(clicked()),
+ this, SLOT(slotUpButton_clicked()));
+ connect(m_widget->downButton, SIGNAL(clicked()),
+ this, SLOT(slotDownButton_clicked()));
+ connect(m_widget->editButton, SIGNAL(clicked()),
+ this, SLOT(slotEditButton_clicked()));
+ connect(m_widget->removeButton, SIGNAL(clicked()),
+ this, SLOT(slotRemoveButton_clicked()));
+ connect(m_widget->loadButton, SIGNAL(clicked()),
+ this, SLOT(slotLoadButton_clicked()));
+ connect(m_widget->saveButton, SIGNAL(clicked()),
+ this, SLOT(slotSaveButton_clicked()));
+ connect(m_widget->clearButton, SIGNAL(clicked()),
+ this, SLOT(slotClearButton_clicked()));
+ connect(m_widget->substLView, SIGNAL(selectionChanged()),
+ this, SLOT(enableDisableButtons()));
+ connect(m_widget->appIdLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(configChanged()));
+
+ // Determine if kdeutils Regular Expression Editor is installed.
+ m_reEditorInstalled = !KTrader::self()->query("KRegExpEditor/KRegExpEditor").isEmpty();
+
+ // Set up defaults.
+ defaults();
+}
+
+/**
+* Destructor.
+*/
+StringReplacerConf::~StringReplacerConf(){
+ // kdDebug() << "StringReplacerConf::~StringReplacerConf: Running" << endl;
+}
+
+/**
+* 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 kttsmgr calls this when the plugin is
+* loaded, so it not necessary to call it in your constructor.
+* The plugin should read its configuration from the specified group
+* in the specified config file.
+* @param config Pointer to a KConfig object.
+* @param configGroup Call config->setGroup with this argument before
+* loading your configuration.
+*/
+void StringReplacerConf::load(KConfig* config, const QString& configGroup){
+ // kdDebug() << "StringReplacerConf::load: Running" << endl;
+ // See if this filter previously save its word list.
+ config->setGroup( configGroup );
+ QString wordsFilename = config->readEntry( "WordListFile" );
+ if ( !wordsFilename.isEmpty() )
+ {
+ QString errMsg = loadFromFile( wordsFilename, true );
+ if ( !errMsg.isEmpty() )
+ kdDebug() << "StringReplacerConf::load: " << errMsg << endl;
+ enableDisableButtons();
+ }
+}
+
+// Loads word list and settings from a file. Clearing configuration if clear is True.
+QString StringReplacerConf::loadFromFile( const QString& filename, bool clear)
+{
+ // Open existing word 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_widget->substLView->clear();
+
+ // Name setting.
+ QDomNodeList nameList = doc.elementsByTagName( "name" );
+ QDomNode nameNode = nameList.item( 0 );
+ m_widget->nameLineEdit->setText( nameNode.toElement().text() );
+ // kdDebug() << "StringReplacerConf::load: name = " << nameNode.toElement().text() << endl;
+
+ // Language Codes setting. List may be single element of comma-separated values,
+ // or multiple elements.
+ QString languageCodes;
+ QDomNodeList languageList = doc.elementsByTagName( "language-code" );
+ for ( uint ndx=0; ndx < languageList.count(); ++ndx )
+ {
+ QDomNode languageNode = languageList.item( ndx );
+ if (!languageCodes.isEmpty()) languageCodes += ",";
+ languageCodes += languageNode.toElement().text();
+ }
+ if ( clear )
+ m_languageCodeList = QStringList::split(',', languageCodes, false);
+ else
+ m_languageCodeList += QStringList::split(',', languageCodes, false);
+ QString language;
+ m_languageCodeList.sort();
+ // Eliminate dups.
+ for ( int ndx = m_languageCodeList.count() - 2; ndx >= 0; --ndx )
+ {
+ if ( m_languageCodeList[ndx] == m_languageCodeList[ndx+1] )
+ m_languageCodeList.remove(m_languageCodeList.at(ndx+1));
+ }
+ for ( uint ndx=0; ndx < m_languageCodeList.count(); ++ndx )
+ {
+ if (!language.isEmpty()) language += ",";
+ language += KGlobal::locale()->twoAlphaToLanguageName(m_languageCodeList[ndx]);
+ }
+ m_widget->languageLineEdit->setText(language);
+
+ // AppId. Apply this filter only if DCOP appId of application that queued
+ // the text contains this string. List may be single element of comma-separated values,
+ // or multiple elements.
+ QDomNodeList appIdList = doc.elementsByTagName( "appid" );
+ QString appIds;
+ for ( uint ndx=0; ndx < appIdList.count(); ++ndx )
+ {
+ QDomNode appIdNode = appIdList.item( ndx );
+ if (!appIds.isEmpty()) appIds += ",";
+ appIds += appIdNode.toElement().text();
+ }
+ if ( !clear ) appIds = m_widget->appIdLineEdit->text() + appIds;
+ m_widget->appIdLineEdit->setText( appIds );
+
+ // Word list.
+ QListViewItem* item = 0;
+ if ( !clear ) item = m_widget->substLView->lastChild();
+ QDomNodeList wordList = doc.elementsByTagName("word");
+ const int wordListCount = wordList.count();
+ for (int wordIndex = 0; wordIndex < wordListCount; ++wordIndex)
+ {
+ // kdDebug() << "StringReplacerConf::load: start parsing of word " << wordIndex << endl;
+ QDomNode wordNode = wordList.item(wordIndex);
+ QDomNodeList propList = wordNode.childNodes();
+ QString wordType;
+ QString matchCase = "No"; // Default for old (v<=3.5.3) config files with no <case/>.
+ QString match;
+ QString subst;
+ const int propListCount = propList.count();
+ for (int propIndex = 0; propIndex < propListCount; ++propIndex)
+ {
+ QDomNode propNode = propList.item(propIndex);
+ QDomElement prop = propNode.toElement();
+ if (prop.tagName() == "type") wordType = prop.text();
+ if (prop.tagName() == "case") matchCase = prop.text();
+ if (prop.tagName() == "match") match = prop.text();
+ if (prop.tagName() == "subst") subst = prop.text();
+ }
+ QString wordTypeStr =
+ (wordType=="RegExp"?i18n("Abbreviation for 'Regular Expression'", "RegExp"):i18n("Word"));
+ QString matchCaseStr =
+ (matchCase=="Yes"?i18n("Yes"):i18n("No"));
+ if (!item)
+ item = new KListViewItem(m_widget->substLView, wordTypeStr, matchCaseStr, match, subst);
+ else
+ item = new KListViewItem(m_widget->substLView, item, wordTypeStr, matchCaseStr, match, subst);
+ }
+
+ return QString::null;
+}
+
+/**
+* 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". The plugin should save its configuration in the specified
+* group of the specified config file.
+* @param config Pointer to a KConfig object.
+* @param configGroup Call config->setGroup with this argument before
+* saving your configuration.
+*/
+void StringReplacerConf::save(KConfig* config, const QString& configGroup){
+ // kdDebug() << "StringReplacerConf::save: Running" << endl;
+ QString wordsFilename =
+ KGlobal::dirs()->saveLocation( "data" ,"kttsd/stringreplacer/", true );
+ if ( wordsFilename.isEmpty() )
+ {
+ kdDebug() << "StringReplacerConf::save: no save location" << endl;
+ return;
+ }
+ wordsFilename += configGroup;
+ QString errMsg = saveToFile( wordsFilename );
+ if ( errMsg.isEmpty() )
+ {
+ config->setGroup( configGroup );
+ config->writeEntry( "WordListFile", realFilePath(wordsFilename) );
+ }
+ else
+ kdDebug() << "StringReplacerConf::save: " << errMsg << endl;
+}
+
+// Saves word list and settings to a file.
+QString StringReplacerConf::saveToFile(const QString& filename)
+{
+ // kdDebug() << "StringReplacerConf::saveToFile: saving to file " << wordsFilename << endl;
+
+ QFile file( filename );
+ if ( !file.open( IO_WriteOnly ) )
+ return i18n("Unable to open file ") + filename;
+
+ // QDomDocument doc( "http://www.kde.org/share/apps/kttsd/stringreplacer/wordlist.dtd []" );
+ QDomDocument doc( "" );
+
+ QDomElement root = doc.createElement( "wordlist" );
+ doc.appendChild( root );
+
+ // Name.
+ QDomElement name = doc.createElement( "name" );
+ root.appendChild( name );
+ QDomText t = doc.createTextNode( m_widget->nameLineEdit->text() );
+ name.appendChild( t );
+
+ // Language code.
+ for ( uint ndx=0; ndx < m_languageCodeList.count(); ++ndx )
+ {
+ QDomElement languageCode = doc.createElement( "language-code" );
+ root.appendChild( languageCode );
+ t = doc.createTextNode( m_languageCodeList[ndx] );
+ languageCode.appendChild( t );
+ }
+
+ // Application ID
+ QString appId = m_widget->appIdLineEdit->text().replace(" ", "");
+ if ( !appId.isEmpty() )
+ {
+ QStringList appIdList = QStringList::split(",", appId);
+ for ( uint ndx=0; ndx < appIdList.count(); ++ndx )
+ {
+ QDomElement appIdElem = doc.createElement( "appid" );
+ root.appendChild( appIdElem );
+ t = doc.createTextNode( appIdList[ndx] );
+ appIdElem.appendChild( t );
+ }
+ }
+
+ // Words.
+ QListView* lView = m_widget->substLView;
+ QListViewItem* item = lView->firstChild();
+ while (item)
+ {
+ QDomElement wordTag = doc.createElement( "word" );
+ root.appendChild( wordTag );
+ QDomElement propTag = doc.createElement( "type" );
+ wordTag.appendChild( propTag);
+ QDomText t = doc.createTextNode( item->text(0)==i18n("Word")?"Word":"RegExp" );
+ propTag.appendChild( t );
+
+ propTag = doc.createElement( "case" );
+ wordTag.appendChild( propTag);
+ t = doc.createTextNode( item->text(1)==i18n("Yes")?"Yes":"No" );
+ propTag.appendChild( t );
+
+ propTag = doc.createElement( "match" );
+ wordTag.appendChild( propTag);
+ t = doc.createCDATASection( item->text(2) );
+ propTag.appendChild( t );
+
+ propTag = doc.createElement( "subst" );
+ wordTag.appendChild( propTag);
+ t = doc.createCDATASection( item->text(3) );
+ propTag.appendChild( t );
+
+ item = item->nextSibling();
+ }
+
+ // Write it all out.
+ QTextStream ts( &file );
+ ts.setEncoding( QTextStream::UnicodeUTF8 );
+ ts << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+ ts << doc.toString();
+ // kdDebug() << "StringReplacerConf::saveToFile: writing out " << doc.toString() << endl;
+ file.close();
+
+ return QString::null;
+}
+
+/**
+* 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. Note that defaults should
+* be applied to the on-screen widgets; not to the config file.
+*/
+void StringReplacerConf::defaults(){
+ // kdDebug() << "StringReplacerConf::defaults: Running" << endl;
+ // Default language is none.
+ m_languageCodeList.clear();
+ m_widget->languageLineEdit->setText( "" );
+ // Default name.
+ m_widget->nameLineEdit->setText( i18n("String Replacer") );
+ m_widget->substLView->clear();
+ // Default App ID is blank.
+ m_widget->appIdLineEdit->setText( "" );
+ enableDisableButtons();
+ // kdDebug() << "StringReplacerConf::defaults: Exiting" << endl;
+}
+
+/**
+ * Indicates whether the plugin supports multiple instances. Return
+ * False if only one instance of the plugin can be configured.
+ * @return True if multiple instances are possible.
+ */
+bool StringReplacerConf::supportsMultiInstance() { return true; }
+
+/**
+ * Returns the name of the plugin. Displayed in Filters tab of KTTSMgr.
+ * If there can be more than one instance of a filter, it should return
+ * a unique name for each instance. The name should be translated for
+ * the user if possible. If the plugin is not correctly configured,
+ * return an empty string.
+ * @return Filter instance name.
+ */
+QString StringReplacerConf::userPlugInName()
+{
+ if ( m_widget->substLView->childCount() == 0 ) return QString::null;
+ QString instName = m_widget->nameLineEdit->text();
+ if ( instName.isEmpty() )
+ {
+ QString language;
+ if (m_languageCodeList.count() == 1)
+ language = KGlobal::locale()->twoAlphaToLanguageName(m_languageCodeList[0]);
+ if (m_languageCodeList.count() > 1)
+ language = i18n("Multiple Languages");
+ if (!language.isEmpty())
+ instName = i18n("String Replacer") + " (" + language + ")";
+ }
+ return instName;
+}
+
+void StringReplacerConf::slotLanguageBrowseButton_clicked()
+{
+ // Create a QHBox to host KListView.
+ QHBox* hBox = new QHBox(m_widget, "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"));
+ langLView->setSelectionMode(QListView::Extended);
+ QStringList allLocales = KGlobal::locale()->allLanguagesTwoAlpha();
+ QString locale;
+ QString languageCode;
+ QString countryCode;
+ QString charSet;
+ QString language;
+ // Blank line so user can select no language.
+ QListViewItem* item = new KListViewItem(langLView, "", "");
+ if (m_languageCodeList.isEmpty()) item->setSelected(true);
+ const int allLocalesCount = allLocales.count();
+ for (int ndx=0; ndx < allLocalesCount; ++ndx)
+ {
+ locale = allLocales[ndx];
+ KGlobal::locale()->splitLocale(locale, languageCode, countryCode, charSet);
+ language = KGlobal::locale()->twoAlphaToLanguageName(languageCode);
+ if (!countryCode.isEmpty()) language +=
+ " (" + KGlobal::locale()->twoAlphaToCountryName(countryCode)+")";
+ item = new KListViewItem(langLView, language, locale);
+ if (m_languageCodeList.contains(locale)) item->setSelected(true);
+ }
+ // Sort by language.
+ langLView->setSorting(0);
+ langLView->sort();
+ // Display the box in a dialog.
+ KDialogBase* dlg = new KDialogBase(
+ KDialogBase::Swallow,
+ i18n("Select Languages"),
+ KDialogBase::Help|KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Cancel,
+ m_widget,
+ "SelectLanguage_dlg",
+ true,
+ true);
+ dlg->setMainWidget(hBox);
+ dlg->setHelp("", "kttsd");
+ dlg->setInitialSize(QSize(300, 500), false);
+ int dlgResult = dlg->exec();
+ languageCode = QString::null;
+ if (dlgResult == QDialog::Accepted)
+ {
+ m_languageCodeList.clear();
+ QListViewItem* item = langLView->firstChild();
+ while (item)
+ {
+ if (item->isSelected()) m_languageCodeList += item->text(1);
+ item = item->nextSibling();
+ }
+ }
+ delete dlg;
+ // TODO: Also delete KListView and QHBox?
+ if (dlgResult != QDialog::Accepted) return;
+ language = "";
+ for ( uint ndx=0; ndx < m_languageCodeList.count(); ++ndx)
+ {
+ if (!language.isEmpty()) language += ",";
+ language += KGlobal::locale()->twoAlphaToLanguageName(m_languageCodeList[ndx]);
+ }
+ QString s1 = m_widget->languageLineEdit->text();
+ m_widget->languageLineEdit->setText(language);
+ // Replace language in the user's filter name.
+ QString s2 = m_widget->nameLineEdit->text();
+ if (m_languageCodeList.count() > 1) language = i18n("Multiple Languages");
+ if ( !s1.isEmpty() )
+ {
+ s2.replace( s1, language );
+ s2.replace( i18n("Multiple Languages"), language );
+ }
+ s2.replace(" ()", "");
+ if ( !s2.contains("(") && !language.isEmpty() ) s2 += " (" + language + ")";
+ m_widget->nameLineEdit->setText(s2);
+ configChanged();
+}
+
+void StringReplacerConf::enableDisableButtons()
+{
+ bool enableBtn = (m_widget->substLView->selectedItem() != 0);
+ if (enableBtn)
+ {
+ m_widget->upButton->setEnabled(
+ m_widget->substLView->selectedItem()->itemAbove() != 0);
+ m_widget->downButton->setEnabled(
+ m_widget->substLView->selectedItem()->itemBelow() != 0);
+ } else {
+ m_widget->upButton->setEnabled(false);
+ m_widget->downButton->setEnabled(false);
+ }
+ m_widget->editButton->setEnabled(enableBtn);
+ m_widget->removeButton->setEnabled(enableBtn);
+ m_widget->clearButton->setEnabled(m_widget->substLView->firstChild());
+ m_widget->saveButton->setEnabled(m_widget->substLView->firstChild());
+}
+
+void StringReplacerConf::slotUpButton_clicked()
+{
+ QListViewItem* item = m_widget->substLView->selectedItem();
+ if (!item) return;
+ QListViewItem* prevItem = item->itemAbove();
+ if (!prevItem) return;
+ prevItem->moveItem(item);
+ m_widget->substLView->setSelected(item, true);
+ m_widget->substLView->ensureItemVisible(item);
+ enableDisableButtons();
+ configChanged();
+}
+
+void StringReplacerConf::slotDownButton_clicked()
+{
+ QListViewItem* item = m_widget->substLView->selectedItem();
+ if (!item) return;
+ QListViewItem* nextItem = item->itemBelow();
+ if (!nextItem) return;
+ item->moveItem(nextItem);
+ m_widget->substLView->setSelected(item, true);
+ m_widget->substLView->ensureItemVisible(item);
+ enableDisableButtons();
+ configChanged();
+}
+
+void StringReplacerConf::slotAddButton_clicked()
+{
+ addOrEditSubstitution( true );
+}
+
+void StringReplacerConf::slotEditButton_clicked()
+{
+ addOrEditSubstitution( false );
+}
+
+// Displays the add/edit string replacement dialog.
+void StringReplacerConf::addOrEditSubstitution(bool isAdd)
+{
+ QListViewItem* item = 0;
+ if (isAdd)
+ item = m_widget->substLView->lastChild();
+ else
+ {
+ item = m_widget->substLView->selectedItem();
+ if (!item) return;
+ }
+ // Create a QHBox to host widget.
+ QHBox* hBox = new QHBox(m_widget, "AddOrEditSubstitution_hbox" );
+ // Create widget.
+ m_editWidget = new EditReplacementWidget( hBox, "AddOrEditSubstitution_widget" );
+ // Set controls if editing existing.
+ m_editWidget->matchButton->setEnabled( false );
+ if (!isAdd)
+ {
+ if ( item->text(0) == i18n("Abbreviation for 'Regular Expression'", "RegExp") )
+ {
+ m_editWidget->regexpRadioButton->setChecked( true );
+ m_editWidget->matchButton->setEnabled( m_reEditorInstalled );
+ }
+ m_editWidget->caseCheckBox->setChecked( (item->text(1))==i18n("Yes") );
+ m_editWidget->matchLineEdit->setText( item->text(2) );
+ m_editWidget->substLineEdit->setText( item->text(3) );
+ }
+ // The match box may not be blank.
+ connect( m_editWidget->matchLineEdit, SIGNAL(textChanged(const QString&)),
+ this, SLOT(slotMatchLineEdit_textChanged(const QString&)) );
+ connect( m_editWidget->regexpRadioButton, SIGNAL(clicked()),
+ this, SLOT(slotTypeButtonGroup_clicked()) );
+ connect( m_editWidget->wordRadioButton, SIGNAL(clicked()),
+ this, SLOT(slotTypeButtonGroup_clicked()) );
+ connect( m_editWidget->matchButton, SIGNAL(clicked()),
+ this, SLOT(slotMatchButton_clicked()) );
+ // Display the box in a dialog.
+ m_editDlg = new KDialogBase(
+ KDialogBase::Swallow,
+ i18n("Edit String Replacement"),
+ KDialogBase::Help|KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Cancel,
+ m_widget,
+ "AddOrEditSubstitution_dlg",
+ true,
+ true);
+ // Disable OK button if match field blank.
+ m_editDlg->setMainWidget( hBox );
+ m_editDlg->setHelp( "", "kttsd" );
+ m_editDlg->enableButton( KDialogBase::Ok, !m_editWidget->matchLineEdit->text().isEmpty() );
+ int dlgResult = m_editDlg->exec();
+ QString substType = i18n( "Word" );
+ if ( m_editWidget->regexpRadioButton->isChecked() )
+ substType = i18n("Abbreviation for 'Regular Expression'", "RegExp");
+ QString matchCase = i18n("No");
+ if ( m_editWidget->caseCheckBox->isChecked() ) matchCase = i18n("Yes");
+ QString match = m_editWidget->matchLineEdit->text();
+ QString subst = m_editWidget->substLineEdit->text();
+ delete m_editDlg;
+ m_editDlg = 0;
+ m_editWidget = 0;
+ if (dlgResult != QDialog::Accepted) return;
+ // TODO: Also delete hBox and w?
+ if ( match.isEmpty() ) return;
+ if ( isAdd )
+ {
+ if ( item )
+ item = new KListViewItem( m_widget->substLView, item, substType, matchCase, match, subst );
+ else
+ item = new KListViewItem( m_widget->substLView, substType, matchCase, match, subst );
+ m_widget->substLView->setSelected( item, true );
+ }
+ else
+ {
+ item->setText( 0, substType );
+ item->setText( 1, matchCase );
+ item->setText( 2, match );
+ item->setText( 3, subst );
+ }
+ m_widget->substLView->ensureItemVisible( item );
+ enableDisableButtons();
+ configChanged();
+}
+
+void StringReplacerConf::slotMatchLineEdit_textChanged(const QString& text)
+{
+ // Disable OK button if match field blank.
+ if ( !m_editDlg ) return;
+ m_editDlg->enableButton( KDialogBase::Ok, !text.isEmpty() );
+}
+
+void StringReplacerConf::slotRemoveButton_clicked()
+{
+ QListViewItem* item = m_widget->substLView->selectedItem();
+ if (!item) return;
+ delete item;
+ enableDisableButtons();
+ configChanged();
+}
+
+void StringReplacerConf::slotTypeButtonGroup_clicked()
+{
+ // Enable Regular Expression Editor button if editor is installed (requires kdeutils).
+ if ( !m_editWidget ) return;
+ m_editWidget->matchButton->setEnabled( m_editWidget->regexpRadioButton->isOn() && m_reEditorInstalled );
+}
+
+void StringReplacerConf::slotMatchButton_clicked()
+{
+ // Show Regular Expression Editor dialog if it is installed.
+ if ( !m_editWidget ) return;
+ if ( !m_editDlg ) return;
+ if ( !m_reEditorInstalled ) return;
+ QDialog *editorDialog =
+ KParts::ComponentFactory::createInstanceFromQuery<QDialog>( "KRegExpEditor/KRegExpEditor" );
+ if ( editorDialog )
+ {
+ // kdeutils was installed, so the dialog was found. Fetch the editor interface.
+ KRegExpEditorInterface *reEditor =
+ static_cast<KRegExpEditorInterface *>(editorDialog->qt_cast( "KRegExpEditorInterface" ) );
+ Q_ASSERT( reEditor ); // This should not fail!// now use the editor.
+ reEditor->setRegExp( m_editWidget->matchLineEdit->text() );
+ int dlgResult = editorDialog->exec();
+ if ( dlgResult == QDialog::Accepted )
+ {
+ QString re = reEditor->regExp();
+ m_editWidget->matchLineEdit->setText( re );
+ m_editDlg->enableButton( KDialogBase::Ok, !re.isEmpty() );
+ }
+ delete editorDialog;
+ } else return;
+}
+
+void StringReplacerConf::slotLoadButton_clicked()
+{
+ // QString dataDir = KGlobal::dirs()->resourceDirs("data").last() + "/kttsd/stringreplacer/";
+ QString dataDir = KGlobal::dirs()->findAllResources("data", "kttsd/stringreplacer/").last();
+ QString filename = KFileDialog::getOpenFileName(
+ dataDir,
+ "*.xml|String Replacer Word List (*.xml)",
+ m_widget,
+ "stringreplacer_loadfile");
+ if ( filename.isEmpty() ) return;
+ QString errMsg = loadFromFile( filename, false );
+ enableDisableButtons();
+ if ( !errMsg.isEmpty() )
+ KMessageBox::sorry( m_widget, errMsg, i18n("Error Opening File") );
+ else
+ configChanged();
+}
+
+void StringReplacerConf::slotSaveButton_clicked()
+{
+ QString filename = KFileDialog::getSaveFileName(
+ KGlobal::dirs()->saveLocation( "data" ,"kttsd/stringreplacer/", false ),
+ "*.xml|String Replacer Word List (*.xml)",
+ m_widget,
+ "stringreplacer_savefile");
+ if ( filename.isEmpty() ) return;
+ QString errMsg = saveToFile( filename );
+ enableDisableButtons();
+ if ( !errMsg.isEmpty() )
+ KMessageBox::sorry( m_widget, errMsg, i18n("Error Opening File") );
+}
+
+void StringReplacerConf::slotClearButton_clicked()
+{
+ m_widget->substLView->clear();
+ enableDisableButtons();
+}
diff --git a/kttsd/filters/stringreplacer/stringreplacerconf.h b/kttsd/filters/stringreplacer/stringreplacerconf.h
new file mode 100644
index 0000000..f0312a6
--- /dev/null
+++ b/kttsd/filters/stringreplacer/stringreplacerconf.h
@@ -0,0 +1,158 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generic String Replacement Filter Configuration class.
+ -------------------
+ 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 _STRINGREPLACERCONF_H_
+#define _STRINGREPLACERCONF_H_
+
+// Qt includes.
+#include <qwidget.h>
+
+// KDE includes.
+#include <kconfig.h>
+#include <kdebug.h>
+
+// KTTS includes.
+#include "filterconf.h"
+
+// StringReplacer includes.
+#include "stringreplacerconfwidget.h"
+
+class KDialogBase;
+class EditReplacementWidget;
+
+class StringReplacerConf : public KttsFilterConf
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Constructor
+ */
+ StringReplacerConf( QWidget *parent, const char *name, const QStringList &args = QStringList() );
+
+ /**
+ * Destructor
+ */
+ virtual ~StringReplacerConf();
+
+ enum SubstitutionType {
+ stWord, // Word
+ stRegExp // Regular Expression
+ };
+
+ /**
+ * 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 KTTSMGR calls this when the plugin is
+ * loaded, so it not necessary to call it in your constructor.
+ * The plugin should read its configuration from the specified group
+ * in the specified config file.
+ * @param config Pointer to a KConfig object.
+ * @param configGroup Call config->setGroup with this argument before
+ * loading your configuration.
+ *
+ * When a plugin is first added to KTTSMGR, @e load will be called with
+ * a Null @e configGroup. In this case, the plugin will not have
+ * any instance-specific parameters to load, but it may still wish
+ * to load parameters that apply to all instances of the plugin.
+ */
+ virtual void load(KConfig *config, const QString &configGroup);
+
+ /**
+ * 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". The plugin should save its configuration in the specified
+ * group of the specified config file.
+ * @param config Pointer to a KConfig object.
+ * @param configGroup Call config->setGroup with this argument before
+ * saving your configuration.
+ */
+ virtual void save(KConfig *config, const QString &configGroup);
+
+ /**
+ * 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. Note that defaults should
+ * be applied to the on-screen widgets; not to the config file.
+ */
+ virtual void defaults();
+
+ /**
+ * Indicates whether the plugin supports multiple instances. Return
+ * False if only one instance of the plugin can be configured.
+ * @return True if multiple instances are possible.
+ */
+ virtual bool supportsMultiInstance();
+
+ /**
+ * Returns the name of the plugin. Displayed in Filters tab of KTTSMgr.
+ * If there can be more than one instance of a filter, it should return
+ * a unique name for each instance. The name should be translated for
+ * the user if possible. If the plugin is not correctly configured,
+ * return an empty string.
+ * @return Filter instance name.
+ */
+ virtual QString userPlugInName();
+
+ private slots:
+ void slotLanguageBrowseButton_clicked();
+ void slotAddButton_clicked();
+ void slotUpButton_clicked();
+ void slotDownButton_clicked();
+ void slotEditButton_clicked();
+ void slotRemoveButton_clicked();
+ void slotMatchLineEdit_textChanged(const QString& text);
+ void slotTypeButtonGroup_clicked();
+ void slotMatchButton_clicked();
+ void slotLoadButton_clicked();
+ void slotSaveButton_clicked();
+ void slotClearButton_clicked();
+
+ // EnablesDisables buttons depending upon current item in list view.
+ void enableDisableButtons();
+
+ private:
+ // Displays the add/edit string replacement dialog.
+ void addOrEditSubstitution(bool isAdd);
+ // Loads word list and settings from a file. Clearing configuration if clear is True.
+ QString loadFromFile( const QString& filename, bool clear);
+ // Saves word list and settings to a file.
+ QString saveToFile( const QString& filename );
+
+
+ // Configuration Widget.
+ StringReplacerConfWidget* m_widget;
+ // Edit Dialog and widget.
+ KDialogBase* m_editDlg;
+ EditReplacementWidget* m_editWidget;
+ // True if kdeutils Regular Expression Editor is installed.
+ bool m_reEditorInstalled;
+ // Language Codes.
+ QStringList m_languageCodeList;
+};
+
+#endif //_STRINGREPLACERCONF_H_
diff --git a/kttsd/filters/stringreplacer/stringreplacerconfwidget.ui b/kttsd/filters/stringreplacer/stringreplacerconfwidget.ui
new file mode 100644
index 0000000..e88307f
--- /dev/null
+++ b/kttsd/filters/stringreplacer/stringreplacerconfwidget.ui
@@ -0,0 +1,474 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>StringReplacerConfWidget</class>
+<comment>Widget for configuring String Replacer Filter for KTTSD.</comment>
+<author>Gary Cramblitt &lt;garycramblitt@comcast.net&gt;</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>StringReplacerConfWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>548</width>
+ <height>421</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Configure String Replacer</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>nameLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Name:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>nameLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter any name you like for this filter.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>nameLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter any name you like for this filter.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox" row="3" column="0">
+ <property name="name">
+ <cstring>applyGroupBox</cstring>
+ </property>
+ <property name="title">
+ <string>Apply This &amp;Filter When</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>These settings determines when the filter is applied to text.</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout11</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>languageLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Lan&amp;guage is:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>languageLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This filter is applied to text jobs of the specified language. You may select more than one language by clicking the browse button and Ctrl-clicking on more than one in the list. If blank the filter applies to all text jobs of any language.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>appIdLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Application &amp;ID contains:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>appIdLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter a DCOP Application ID. This filter will only apply to text jobs queued by that application. You may enter more than one ID separated by commas. If blank, this filter applies to text jobs queued by all applications. Tip: Use kdcop from the command line to get the Application IDs of running applications. Example: "konversation, kvirc,ksirc,kopete"</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout13</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout12</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>languageLineEdit</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This filter is applied to text jobs of the specified language. You may select more than one language by clicking the browse button and Ctrl-clicking on more than one in the list. If blank the filter applies to all text jobs of any language.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>languageBrowseButton</cstring>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to select one or more languages. This filter will be applied to text jobs of those languages.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>appIdLineEdit</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter a DCOP Application ID. This filter will only apply to text jobs queued by that application. You may enter more than one ID separated by commas. Use &lt;b&gt;knotify&lt;/b&gt; to match all messages sent as KDE notifications. If blank, this filter applies to text jobs queued by all applications. Tip: Use kdcop from the command line to get the Application IDs of running applications. Example: "konversation, kvirc,ksirc,kopete"&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="0">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>loadButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Load...</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to load a word list from a file.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>saveButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Save...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to save word list to a file.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>clearButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>C&amp;lear</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to empty the word list.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>layout24</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KListView" row="0" column="0">
+ <column>
+ <property name="text">
+ <string>Type</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Match Case</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Match</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Replace With</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>substLView</cstring>
+ </property>
+ <property name="fullWidth">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="1">
+ <property name="name">
+ <cstring>layout23</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>addButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Add...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to add another word or regular expression to the list.</string>
+ <comment>What's this text</comment>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>upButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Up</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Click to move selected word up in the list. Words higher in the list are applied first.</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>downButton</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 word down in the list. Words lower in the list are applied last.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>editButton</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 modify an existing word or regular expression in the list.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>removeButton</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 a word or regular expression from the list.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer13</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>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<tabstops>
+ <tabstop>nameLineEdit</tabstop>
+ <tabstop>substLView</tabstop>
+ <tabstop>addButton</tabstop>
+ <tabstop>upButton</tabstop>
+ <tabstop>downButton</tabstop>
+ <tabstop>editButton</tabstop>
+ <tabstop>removeButton</tabstop>
+ <tabstop>loadButton</tabstop>
+ <tabstop>saveButton</tabstop>
+ <tabstop>clearButton</tabstop>
+ <tabstop>languageLineEdit</tabstop>
+ <tabstop>languageBrowseButton</tabstop>
+ <tabstop>appIdLineEdit</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klistview.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kttsd/filters/stringreplacer/stringreplacerplugin.cpp b/kttsd/filters/stringreplacer/stringreplacerplugin.cpp
new file mode 100644
index 0000000..c3f9678
--- /dev/null
+++ b/kttsd/filters/stringreplacer/stringreplacerplugin.cpp
@@ -0,0 +1,32 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generating the factories so String Replacer Filter can be used as plug in.
+ -------------------
+ 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.
+ ******************************************************************************/
+
+#include <kgenericfactory.h>
+
+#include "stringreplacerconf.h"
+#include "stringreplacerproc.h"
+
+typedef K_TYPELIST_2( StringReplacerProc, StringReplacerConf ) StringReplacerPlugin;
+K_EXPORT_COMPONENT_FACTORY( libkttsd_stringreplacerplugin,
+ KGenericFactory<StringReplacerPlugin>("kttsd_stringreplacer") )
+
diff --git a/kttsd/filters/stringreplacer/stringreplacerproc.cpp b/kttsd/filters/stringreplacer/stringreplacerproc.cpp
new file mode 100644
index 0000000..1b03810
--- /dev/null
+++ b/kttsd/filters/stringreplacer/stringreplacerproc.cpp
@@ -0,0 +1,231 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generic String Replacement Filter Processing class.
+ -------------------
+ 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 <qdom.h>
+#include <qfile.h>
+#include <qlistview.h>
+
+// KDE includes.
+#include <kdebug.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+
+// KTTS includes.
+#include "filterproc.h"
+#include "talkercode.h"
+
+// StringReplacer includes.
+#include "stringreplacerproc.h"
+#include "stringreplacerproc.moc"
+
+/**
+ * Constructor.
+ */
+StringReplacerProc::StringReplacerProc( QObject *parent, const char *name, const QStringList& ) :
+ KttsFilterProc(parent, name)
+{
+}
+
+/**
+ * Destructor.
+ */
+/*virtual*/ StringReplacerProc::~StringReplacerProc()
+{
+ m_matchList.clear();
+ m_caseList.clear();
+ m_substList.clear();
+}
+
+/**
+ * Initialize the filter.
+ * @param config Settings object.
+ * @param configGroup Settings Group.
+ * @return False if filter is not ready to filter.
+ *
+ * Note: The parameters are for reading from kttsdrc file. Plugins may wish to maintain
+ * separate configuration files of their own.
+ */
+bool StringReplacerProc::init(KConfig* config, const QString& configGroup){
+ // kdDebug() << "StringReplacerProc::init: Running" << endl;
+ QString wordsFilename =
+ KGlobal::dirs()->saveLocation( "data" ,"kttsd/stringreplacer/", false );
+ if ( wordsFilename.isEmpty() ) return false;
+ wordsFilename += configGroup;
+ config->setGroup( configGroup );
+ wordsFilename = config->readEntry( "WordListFile", wordsFilename );
+
+ // Open existing word list.
+ QFile file( wordsFilename );
+ if ( !file.open( IO_ReadOnly ) )
+ return false;
+ QDomDocument doc( "" );
+ if ( !doc.setContent( &file ) ) {
+ file.close();
+ return false;
+ }
+ file.close();
+
+ // Clear list.
+ m_matchList.clear();
+ m_caseList.clear();
+ m_substList.clear();
+
+ // Name setting.
+ // QDomNodeList nameList = doc.elementsByTagName( "name" );
+ // QDomNode nameNode = nameList.item( 0 );
+ // m_widget->nameLineEdit->setText( nameNode.toElement().text() );
+
+ // Language Codes setting. List may be single element of comma-separated values,
+ // or multiple elements.
+ m_languageCodeList.clear();
+ QDomNodeList languageList = doc.elementsByTagName( "language-code" );
+ for ( uint ndx=0; ndx < languageList.count(); ++ndx )
+ {
+ QDomNode languageNode = languageList.item( ndx );
+ m_languageCodeList += QStringList::split(',', languageNode.toElement().text(), false);
+ }
+
+ // AppId. Apply this filter only if DCOP appId of application that queued
+ // the text contains this string. List may be single element of comma-separated values,
+ // or multiple elements.
+ m_appIdList.clear();
+ QDomNodeList appIdList = doc.elementsByTagName( "appid" );
+ for ( uint ndx=0; ndx < appIdList.count(); ++ndx )
+ {
+ QDomNode appIdNode = appIdList.item( ndx );
+ m_appIdList += QStringList::split(',', appIdNode.toElement().text(), false);
+ }
+
+ // Word list.
+ QDomNodeList wordList = doc.elementsByTagName("word");
+ const int wordListCount = wordList.count();
+ for (int wordIndex = 0; wordIndex < wordListCount; ++wordIndex)
+ {
+ QDomNode wordNode = wordList.item(wordIndex);
+ QDomNodeList propList = wordNode.childNodes();
+ QString wordType;
+ QString matchCase = "No"; // Default for old (v<=3.5.3) config files with no <case/>.
+ QString match;
+ QString subst;
+ const int propListCount = propList.count();
+ for (int propIndex = 0; propIndex < propListCount; ++propIndex)
+ {
+ QDomNode propNode = propList.item(propIndex);
+ QDomElement prop = propNode.toElement();
+ if (prop.tagName() == "type") wordType = prop.text();
+ if (prop.tagName() == "case") matchCase = prop.text();
+ if (prop.tagName() == "match") match = prop.text();
+ if (prop.tagName() == "subst") subst = prop.text();
+ }
+ // Build Regular Expression for each word's match string.
+ QRegExp rx;
+ rx.setCaseSensitive(matchCase == "Yes");
+ if ( wordType == "Word" )
+ {
+ // TODO: Does \b honor strange non-Latin1 encodings?
+ rx.setPattern( "\\b" + match + "\\b" );
+ }
+ else
+ {
+ rx.setPattern( match );
+ }
+ // Add Regular Expression to list (if valid).
+ if ( rx.isValid() )
+ {
+ m_matchList.append( rx );
+ m_substList.append( subst );
+ }
+ }
+ return true;
+}
+
+/**
+ * Convert input, returning output.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ */
+/*virtual*/ QString StringReplacerProc::convert(const QString& inputText, TalkerCode* talkerCode, const QCString& appId)
+{
+ m_wasModified = false;
+ // If language doesn't match, return input unmolested.
+ if ( !m_languageCodeList.isEmpty() )
+ {
+ QString languageCode = talkerCode->languageCode();
+ // kdDebug() << "StringReplacerProc::convert: converting " << inputText <<
+ // " if language code " << languageCode << " matches " << m_languageCodeList << endl;
+ if ( !m_languageCodeList.contains( languageCode ) )
+ {
+ if ( !talkerCode->countryCode().isEmpty() )
+ {
+ languageCode += '_' + talkerCode->countryCode();
+ // kdDebug() << "StringReplacerProc::convert: converting " << inputText <<
+ // " if language code " << languageCode << " matches " << m_languageCodeList << endl;
+ if ( !m_languageCodeList.contains( languageCode ) ) return inputText;
+ } else return inputText;
+ }
+ }
+ // If appId doesn't match, return input unmolested.
+ if ( !m_appIdList.isEmpty() )
+ {
+ // kdDebug() << "StringReplacerProc::convert: converting " << inputText << " if appId "
+ // << appId << " matches " << m_appIdList << endl;
+ bool found = false;
+ QString appIdStr = appId;
+ for ( uint ndx=0; ndx < m_appIdList.count(); ++ndx )
+ {
+ if ( appIdStr.contains(m_appIdList[ndx]) )
+ {
+ found = true;
+ break;
+ }
+ }
+ if ( !found )
+ {
+ // kdDebug() << "StringReplacerProc::convert: appId not found" << endl;
+ return inputText;
+ }
+ }
+ QString newText = inputText;
+ const int listCount = m_matchList.count();
+ for ( int index = 0; index < listCount; ++index )
+ {
+ //kdDebug() << "newtext = " << newText << " matching " << m_matchList[index].pattern() << " replacing with " << m_substList[index] << endl;
+ newText.replace( m_matchList[index], m_substList[index] );
+ }
+ m_wasModified = true;
+ return newText;
+}
+
+/**
+ * Did this filter do anything? If the filter returns the input as output
+ * unmolested, it should return False when this method is called.
+ */
+/*virtual*/ bool StringReplacerProc::wasModified() { return m_wasModified; }
+
diff --git a/kttsd/filters/stringreplacer/stringreplacerproc.h b/kttsd/filters/stringreplacer/stringreplacerproc.h
new file mode 100644
index 0000000..114ebaf
--- /dev/null
+++ b/kttsd/filters/stringreplacer/stringreplacerproc.h
@@ -0,0 +1,97 @@
+/***************************************************** vim:set ts=4 sw=4 sts=4:
+ Generic String Replacement Filter Processing class.
+ This is the interface definition for text filters.
+ -------------------
+ 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 _STRINGREPLACERPROC_H_
+#define _STRINGREPLACERPROC_H_
+
+// Qt includes.
+#include <qobject.h>
+#include <qtextstream.h>
+#include <qvaluelist.h>
+#include <qregexp.h>
+#include <qstringlist.h>
+
+// KTTS includes.
+#include "filterproc.h"
+
+class StringReplacerProc : virtual public KttsFilterProc
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Constructor.
+ */
+ StringReplacerProc( QObject *parent, const char *name, const QStringList &args = QStringList() );
+
+ /**
+ * Destructor.
+ */
+ virtual ~StringReplacerProc();
+
+ /**
+ * Initialize the filter.
+ * @param config Settings object.
+ * @param configGroup Settings Group.
+ * @return False if filter is not ready to filter.
+ *
+ * Note: The parameters are for reading from kttsdrc file. Plugins may wish to maintain
+ * separate configuration files of their own.
+ */
+ virtual bool init(KConfig *config, const QString &configGroup);
+
+ /**
+ * Convert input, returning output.
+ * @param inputText Input text.
+ * @param talkerCode TalkerCode structure for the talker that KTTSD intends to
+ * use for synthing the text. Useful for extracting hints about
+ * how to filter the text. For example, languageCode.
+ * @param appId The DCOP appId of the application that queued the text.
+ * Also useful for hints about how to do the filtering.
+ */
+ virtual QString convert(const QString& inputText, TalkerCode* talkerCode, const QCString& appId);
+
+ /**
+ * Did this filter do anything? If the filter returns the input as output
+ * unmolested, it should return False when this method is called.
+ */
+ virtual bool wasModified();
+
+private:
+ // Language codes supported by the filter.
+ QStringList m_languageCodeList;
+ // If not empty, apply filter only to apps containing one or more of these strings.
+ QStringList m_appIdList;
+
+ // List of regular expressions to match.
+ QValueList<QRegExp> m_matchList;
+ // List of match case flag
+ QValueList<QString> m_caseList;
+ // List of substitutions to replace matches.
+ QValueList<QString> m_substList;
+ // True if this filter did anything to the text.
+ bool m_wasModified;
+};
+
+#endif // _STRINGREPLACERPROC_H_