1 /***************************************************** vim:set ts=4 sw=4 sts=4:
2 KControl module for KTTSD configuration and Job Management
4 Copyright : (C) 2002-2003 by José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
5 Copyright : (C) 2004-2005 by Gary Cramblitt <garycramblitt@comcast.net>
7 Original author: José Pablo Ezequiel "Pupeno" Fernández <pupeno@kde.org>
8 Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
9 ******************************************************************************/
11 /***************************************************************************
13 * This program is free software; you can redistribute it and/or modify *
14 * it under the terms of the GNU General Public License as published by *
15 * the Free Software Foundation; version 2 of the License. *
17 ***************************************************************************/
19 // Note to programmers. There is a subtle difference between a plugIn name and a
20 // synthesizer name. The latter is a translated name, for example, "Festival Interactivo",
21 // while the former is alway an English name, example "Festival Interactive".
23 // KCMKttsMgr includes.
24 #include "kcmkttsmgr.h"
25 #include "kcmkttsmgr.moc"
31 #include <QtGui/QWidget>
32 #include <QtGui/QTabWidget>
33 #include <QtGui/QCheckBox>
34 #include <QtGui/QLayout>
35 #include <QtGui/QRadioButton>
36 #include <QtGui/QSlider>
37 #include <QtGui/QLabel>
38 #include <QtGui/QTreeWidget>
39 #include <QtGui/QHeaderView>
40 #include <QtCore/QTextStream>
41 #include <QtGui/QMenu>
44 #include <kparts/componentfactory.h>
45 #include <klineedit.h>
46 #include <kurlrequester.h>
48 #include <kstandarddirs.h>
49 #include <kaboutdata.h>
51 #include <knuminput.h>
52 #include <kcombobox.h>
53 #include <kinputdialog.h>
54 #include <kmessagebox.h>
55 #include <kfiledialog.h>
56 #include <ktoolinvocation.h>
59 #include <kpluginfactory.h>
60 #include <kpluginloader.h>
64 #include "talkercode.h"
65 #include "pluginconf.h"
66 #include "filterconf.h"
67 #include "testplayer.h"
69 #include "selecttalkerdlg.h"
70 #include "selectlanguagedlg.h"
74 // Defaults set when clicking Defaults button.
75 const bool autostartMgrCheckBoxValue
= true;
76 const bool autoexitMgrCheckBoxValue
= true;
79 const bool textPreMsgCheckValue
= true;
80 const QString textPreMsgValue
= i18n("Text interrupted. Message.");
82 const bool textPreSndCheckValue
= false;
83 const QString textPreSndValue
= "";
85 const bool textPostMsgCheckValue
= true;
86 const QString textPostMsgValue
= i18n("Resuming text.");
88 const bool textPostSndCheckValue
= false;
89 const QString textPostSndValue
= "";
91 const int timeBoxValue
= 100;
93 const bool keepAudioCheckBoxValue
= false;
95 // Make this a plug in.
96 K_PLUGIN_FACTORY(KCMKttsMgrFactory
, registerPlugin
<KCMKttsMgr
>();)
97 K_EXPORT_PLUGIN(KCMKttsMgrFactory("kttsd"))
100 // ----------------------------------------------------------------------------
102 FilterListModel::FilterListModel(FilterList filters
, QObject
*parent
)
103 : QAbstractListModel(parent
), m_filters(filters
)
107 int FilterListModel::rowCount(const QModelIndex
&parent
) const
109 if (!parent
.isValid())
110 return m_filters
.count();
115 int FilterListModel::columnCount(const QModelIndex
&parent
) const
121 QModelIndex
FilterListModel::index(int row
, int column
, const QModelIndex
&parent
) const
123 if (!parent
.isValid())
124 return createIndex(row
, column
, 0);
126 return QModelIndex();
129 QModelIndex
FilterListModel::parent(const QModelIndex
&index
) const
132 return QModelIndex();
135 QVariant
FilterListModel::data(const QModelIndex
&index
, int role
) const
137 if (!index
.isValid())
140 if (index
.row() < 0 || index
.row() >= m_filters
.count())
143 if (index
.column() < 0 || index
.column() >= 2)
146 if (role
== Qt::DisplayRole
|| role
== Qt::EditRole
)
147 switch (index
.column()) {
148 case 0: return QVariant(); break;
149 case 1: return m_filters
.at(index
.row()).userFilterName
; break;
152 if (role
== Qt::CheckStateRole
)
153 switch (index
.column()) {
154 case 0: if (m_filters
.at(index
.row()).enabled
)
157 return Qt::Unchecked
;
159 case 1: return QVariant(); break;
165 Qt::ItemFlags
FilterListModel::flags(const QModelIndex
&index
) const
167 if (!index
.isValid())
168 return Qt::ItemIsEnabled
;
170 switch (index
.column()) {
171 case 0: return QAbstractItemModel::flags(index
) | Qt::ItemIsEnabled
|
172 Qt::ItemIsSelectable
| Qt::ItemIsUserCheckable
; break;
173 case 1: return QAbstractItemModel::flags(index
) | Qt::ItemIsEnabled
| Qt::ItemIsSelectable
; break;
175 return QAbstractItemModel::flags(index
) | Qt::ItemIsEnabled
;
178 QVariant
FilterListModel::headerData(int section
, Qt::Orientation orientation
, int role
) const
180 if (orientation
== Qt::Horizontal
&& role
== Qt::DisplayRole
)
183 case 1: return i18n("Filter");
188 bool FilterListModel::removeRow(int row
, const QModelIndex
& parent
)
190 beginRemoveRows(parent
, row
, row
);
191 m_filters
.removeAt(row
);
196 FilterItem
FilterListModel::getRow(int row
) const
198 if (row
< 0 || row
>= rowCount()) return FilterItem();
199 return m_filters
[row
];
202 bool FilterListModel::appendRow(FilterItem
& filter
)
204 beginInsertRows(QModelIndex(), m_filters
.count(), m_filters
.count());
205 m_filters
.append(filter
);
210 bool FilterListModel::updateRow(int row
, FilterItem
& filter
)
212 m_filters
.replace(row
, filter
);
213 emit
dataChanged(index(row
, 0, QModelIndex()), index(row
, columnCount()-1, QModelIndex()));
217 bool FilterListModel::swap(int i
, int j
)
219 m_filters
.swap(i
, j
);
220 emit
dataChanged(index(i
, 0, QModelIndex()), index(j
, columnCount()-1, QModelIndex()));
224 void FilterListModel::clear()
230 // ----------------------------------------------------------------------------
232 SbdFilterListModel::SbdFilterListModel(FilterList filters
, QObject
*parent
)
233 : FilterListModel(filters
, parent
)
237 int SbdFilterListModel::columnCount(const QModelIndex
&parent
) const
243 QVariant
SbdFilterListModel::data(const QModelIndex
&index
, int role
) const
245 if (!index
.isValid())
248 if (index
.row() < 0 || index
.row() >= m_filters
.count())
251 if (index
.column() != 0)
254 if (role
== Qt::DisplayRole
)
255 return m_filters
.at(index
.row()).userFilterName
;
260 Qt::ItemFlags
SbdFilterListModel::flags(const QModelIndex
&index
) const
262 if (!index
.isValid())
263 return Qt::ItemIsEnabled
;
265 return Qt::ItemIsEnabled
| Qt::ItemIsSelectable
;
268 QVariant
SbdFilterListModel::headerData(int section
, Qt::Orientation orientation
, int role
) const
270 if (orientation
== Qt::Horizontal
&& role
== Qt::DisplayRole
)
272 case 0: return i18n("Sentence Boundary Detector");
277 // ----------------------------------------------------------------------------
282 KCMKttsMgr::KCMKttsMgr(QWidget
*parent
, const QVariantList
&) :
283 KCModule(KCMKttsMgrFactory::componentData(), parent
/*, name*/),
287 // kDebug() << "KCMKttsMgr constructor running.";
289 // Initialize some variables.
294 m_suppressConfigChanged
= false;
296 // Add the KTTS Manager widget
299 // Connect Views to Models and set row selection mode.
300 talkersView
->setModel(&m_talkerListModel
);
301 filtersView
->setModel(&m_filterListModel
);
302 sbdsView
->setModel(&m_sbdFilterListModel
);
303 talkersView
->setSelectionBehavior(QAbstractItemView::SelectRows
);
304 filtersView
->setSelectionBehavior(QAbstractItemView::SelectRows
);
305 sbdsView
->setSelectionBehavior(QAbstractItemView::SelectRows
);
306 talkersView
->setRootIsDecorated(false);
307 filtersView
->setRootIsDecorated(false);
308 sbdsView
->setRootIsDecorated(false);
309 talkersView
->setItemsExpandable(false);
310 filtersView
->setItemsExpandable(false);
311 sbdsView
->setItemsExpandable(false);
313 // Give buttons icons.
315 higherTalkerPriorityButton
->setIcon(KIcon("go-up"));
316 lowerTalkerPriorityButton
->setIcon(KIcon("go-down"));
317 removeTalkerButton
->setIcon(KIcon("user-trash"));
318 configureTalkerButton
->setIcon(KIcon("configure"));
321 higherFilterPriorityButton
->setIcon(KIcon("go-up"));
322 lowerFilterPriorityButton
->setIcon(KIcon("go-down"));
323 removeFilterButton
->setIcon(KIcon("user-trash"));
324 configureFilterButton
->setIcon(KIcon("configure"));
326 // Construct a popup menu for the Sentence Boundary Detector buttons on Filter tab.
327 QMenu
* sbdPopmenu
= new QMenu( this );
328 sbdPopmenu
->setObjectName( "SbdPopupMenu" );
329 m_sbdBtnEdit
= sbdPopmenu
->addAction(
330 i18n("&Edit..."), this, SLOT(slotConfigureSbdFilterButton_clicked()), 0 );
331 m_sbdBtnUp
= sbdPopmenu
->addAction( KIcon("go-up"),
332 i18n("U&p"), this, SLOT(slotHigherSbdFilterPriorityButton_clicked()), 0 );
333 m_sbdBtnDown
= sbdPopmenu
->addAction( KIcon("go-down"),
334 i18n("Do&wn"), this, SLOT(slotLowerSbdFilterPriorityButton_clicked()), 0 );
335 m_sbdBtnAdd
= sbdPopmenu
->addAction(
336 i18n("&Add..."), this, SLOT(slotAddSbdFilterButton_clicked()), 0 );
337 m_sbdBtnRemove
= sbdPopmenu
->addAction(
338 i18n("&Remove"), this, SLOT(slotRemoveSbdFilterButton_clicked()), 0 );
339 sbdButton
->setMenu( sbdPopmenu
);
341 TestPlayer
* testPlayer
;
344 // If Phonon is available, enable its radio button.
345 // Determine if available by loading its plugin. If it fails, not available.
346 testPlayer
= new TestPlayer();
347 player
= testPlayer
->createPlayerObject(0);
350 phononRadioButton
->setEnabled(true);
355 // If ALSA is available, enable its radio button.
356 // Determine if available by loading its plugin. If it fails, not available.
357 testPlayer
= new TestPlayer();
358 player
= testPlayer
->createPlayerObject(2);
361 alsaRadioButton
->setEnabled(true);
362 pcmLabel
->setEnabled(true);
363 pcmComboBox
->setEnabled(true);
364 pcmCustom
->setEnabled(pcmComboBox
->currentText() == "custom");
365 QStringList pcmList
= player
->getPluginList("");
366 pcmList
.append("custom");
367 kDebug() << "KCMKttsMgr::KCMKttsMgr: ALSA pcmList = " << pcmList
;
368 pcmComboBox
->clear();
369 pcmComboBox
->addItems(pcmList
);
374 // Set up Keep Audio Path KURLRequestor.
375 keepAudioPath
->setMode(KFile::Directory
);
376 keepAudioPath
->setUrl(KUrl::fromPath(
377 KStandardDirs::locateLocal("data", "kttsd/audio/")));
379 // Object for the KTTSD configuration.
380 m_config
= new KConfig("kttsdrc");
382 // Load configuration.
385 // Connect the signals from the KCMKtssMgrWidget to this class.
388 connect(enableKttsdCheckBox
, SIGNAL(toggled(bool)),
389 SLOT(slotEnableKttsd_toggled(bool)));
390 connect(autostartMgrCheckBox
, SIGNAL(toggled(bool)),
391 SLOT(slotAutoStartMgrCheckBox_toggled(bool)));
392 connect(autoexitMgrCheckBox
, SIGNAL(toggled(bool)),
393 SLOT(configChanged()));
396 connect(addTalkerButton
, SIGNAL(clicked()),
397 this, SLOT(slotAddTalkerButton_clicked()));
398 connect(higherTalkerPriorityButton
, SIGNAL(clicked()),
399 this, SLOT(slotHigherTalkerPriorityButton_clicked()));
400 connect(lowerTalkerPriorityButton
, SIGNAL(clicked()),
401 this, SLOT(slotLowerTalkerPriorityButton_clicked()));
402 connect(removeTalkerButton
, SIGNAL(clicked()),
403 this, SLOT(slotRemoveTalkerButton_clicked()));
404 connect(configureTalkerButton
, SIGNAL(clicked()),
405 this, SLOT(slotConfigureTalkerButton_clicked()));
406 connect(talkersView
, SIGNAL(clicked(const QModelIndex
&)),
407 this, SLOT(updateTalkerButtons()));
410 connect(addFilterButton
, SIGNAL(clicked()),
411 this, SLOT(slotAddNormalFilterButton_clicked()));
412 connect(higherFilterPriorityButton
, SIGNAL(clicked()),
413 this, SLOT(slotHigherNormalFilterPriorityButton_clicked()));
414 connect(lowerFilterPriorityButton
, SIGNAL(clicked()),
415 this, SLOT(slotLowerNormalFilterPriorityButton_clicked()));
416 connect(removeFilterButton
, SIGNAL(clicked()),
417 this, SLOT(slotRemoveNormalFilterButton_clicked()));
418 connect(configureFilterButton
, SIGNAL(clicked()),
419 this, SLOT(slotConfigureNormalFilterButton_clicked()));
420 connect(filtersView
, SIGNAL(clicked(const QModelIndex
&)),
421 this, SLOT(updateFilterButtons()));
422 connect(sbdsView
, SIGNAL(clicked(const QModelIndex
&)),
423 this, SLOT(updateSbdButtons()));
424 connect(filtersView
, SIGNAL(clicked(const QModelIndex
&)),
425 this, SLOT(slotFilterListView_clicked(const QModelIndex
&)));
429 connect(textPreMsgCheck
, SIGNAL(toggled(bool)),
430 this, SLOT(slotTextPreMsgCheck_toggled(bool)));
431 connect(textPreMsg
, SIGNAL(textChanged(const QString
&)),
432 this, SLOT(configChanged()));
433 connect(textPreSndCheck
, SIGNAL(toggled(bool)),
434 this, SLOT(slotTextPreSndCheck_toggled(bool)));
435 connect(textPreSnd
, SIGNAL(textChanged(const QString
&)),
436 this, SLOT(configChanged()));
437 connect(textPostMsgCheck
, SIGNAL(toggled(bool)),
438 this, SLOT(slotTextPostMsgCheck_toggled(bool)));
439 connect(textPostMsg
, SIGNAL(textChanged(const QString
&)),
440 this, SLOT(configChanged()));
441 connect(textPostSndCheck
, SIGNAL(toggled(bool)),
442 this, SLOT(slotTextPostSndCheck_toggled(bool)));
443 connect(textPostSnd
, SIGNAL(textChanged(const QString
&)),
444 this, SLOT(configChanged()));
447 connect(phononRadioButton
, SIGNAL(toggled(bool)),
448 this, SLOT(slotPhononRadioButton_toggled(bool)));
449 connect(alsaRadioButton
, SIGNAL(toggled(bool)),
450 this, SLOT(slotAlsaRadioButton_toggled(bool)));
451 connect(pcmComboBox
, SIGNAL(activated(int)),
452 this, SLOT(slotPcmComboBox_activated()));
453 connect(pcmComboBox
, SIGNAL(activated(int)),
454 this, SLOT(configChanged()));
455 connect(timeBox
, SIGNAL(valueChanged(int)),
456 this, SLOT(timeBox_valueChanged(int)));
457 connect(timeSlider
, SIGNAL(valueChanged(int)),
458 this, SLOT(timeSlider_valueChanged(int)));
459 connect(timeBox
, SIGNAL(valueChanged(int)),
460 this, SLOT(configChanged()));
461 connect(timeSlider
, SIGNAL(valueChanged(int)),
462 this, SLOT(configChanged()));
463 connect(keepAudioCheckBox
, SIGNAL(toggled(bool)),
464 this, SLOT(keepAudioCheckBox_toggled(bool)));
465 connect(keepAudioPath
, SIGNAL(textChanged(const QString
&)),
466 this, SLOT(configChanged()));
469 connect(mainTab
, SIGNAL(currentChanged(int)),
470 this, SLOT(slotTabChanged()));
472 // See if KTTSD is already running, and if so, create jobs tab.
473 if (QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kttsd"))
476 // Start KTTSD if check box is checked.
477 slotEnableKttsd_toggled(enableKttsdCheckBox
->isChecked());
479 // Adjust view column sizes.
480 // TODO: To work properly, this needs to be done after the widgets are shown.
481 // Possibly in Resize event?
482 for (int i
= 0; i
< m_filterListModel
.columnCount(); ++i
)
483 filtersView
->resizeColumnToContents(i
);
484 for (int i
= 0; i
< m_talkerListModel
.columnCount(); ++i
)
485 talkersView
->resizeColumnToContents(i
);
487 // Switch to Talkers tab if none configured,
488 // otherwise switch to Jobs tab if it is active.
489 if (m_talkerListModel
.rowCount() == 0)
490 mainTab
->setCurrentIndex(wpTalkers
);
491 else if (enableKttsdCheckBox
->isChecked())
492 mainTab
->setCurrentIndex(wpJobs
);
498 KCMKttsMgr::~KCMKttsMgr(){
499 // kDebug() << "KCMKttsMgr::~KCMKttsMgr: Running";
504 * This method is invoked whenever the module should read its
505 * configuration (most of the times from a config file) and update the
506 * user interface. This happens when the user clicks the "Reset" button in
507 * the control center, to undo all of his changes and restore the currently
508 * valid settings. NOTE that this is not called after the modules is loaded,
509 * so you probably want to call this method in the constructor.
511 void KCMKttsMgr::load()
513 // kDebug() << "KCMKttsMgr::load: Running";
516 // Don't emit changed() signal while loading.
517 m_suppressConfigChanged
= true;
519 // Set the group general for the configuration of kttsd itself (no plug ins)
520 KConfigGroup
generalConfig(m_config
, "General");
522 // Load the configuration of the text interruption messages and sound
523 textPreMsgCheck
->setChecked(generalConfig
.readEntry("TextPreMsgEnabled", textPreMsgCheckValue
));
524 textPreMsg
->setText(generalConfig
.readEntry("TextPreMsg", textPreMsgValue
));
525 textPreMsg
->setEnabled(textPreMsgCheck
->isChecked());
527 textPreSndCheck
->setChecked(generalConfig
.readEntry("TextPreSndEnabled", textPreSndCheckValue
));
528 textPreSnd
->setUrl(KUrl::fromPath(generalConfig
.readEntry("TextPreSnd", textPreSndValue
)));
529 textPreSnd
->setEnabled(textPreSndCheck
->isChecked());
531 textPostMsgCheck
->setChecked(generalConfig
.readEntry("TextPostMsgEnabled", textPostMsgCheckValue
));
532 textPostMsg
->setText(generalConfig
.readEntry("TextPostMsg", textPostMsgValue
));
533 textPostMsg
->setEnabled(textPostMsgCheck
->isChecked());
535 textPostSndCheck
->setChecked(generalConfig
.readEntry("TextPostSndEnabled", textPostSndCheckValue
));
536 textPostSnd
->setUrl(KUrl::fromPath(generalConfig
.readEntry("TextPostSnd", textPostSndValue
)));
537 textPostSnd
->setEnabled(textPostSndCheck
->isChecked());
540 enableKttsdCheckBox
->setChecked(generalConfig
.readEntry("EnableKttsd",
541 enableKttsdCheckBox
->isChecked()));
543 autostartMgrCheckBox
->setChecked(generalConfig
.readEntry("AutoStartManager", true));
544 autoexitMgrCheckBox
->setChecked(generalConfig
.readEntry("AutoExitManager", true));
548 // Default to Phonon.
549 int audioOutputMethod
= 0;
550 // if (gstreamerRadioButton->isChecked()) audioOutputMethod = 1;
551 if (alsaRadioButton
->isChecked()) audioOutputMethod
= 2;
552 audioOutputMethod
= generalConfig
.readEntry("AudioOutputMethod", audioOutputMethod
);
553 switch (audioOutputMethod
)
556 phononRadioButton
->setChecked(true);
559 alsaRadioButton
->setChecked(true);
562 phononRadioButton
->setChecked(true);
564 timeBox
->setValue(generalConfig
.readEntry("AudioStretchFactor", timeBoxValue
));
565 timeBox_valueChanged(timeBox
->value());
566 keepAudioCheckBox
->setChecked(
567 generalConfig
.readEntry("KeepAudio", keepAudioCheckBox
->isChecked()));
568 keepAudioPath
->setUrl(KUrl::fromPath(
569 generalConfig
.readEntry("KeepAudioPath",
570 keepAudioPath
->url().path())));
571 keepAudioPath
->setEnabled(keepAudioCheckBox
->isChecked());
573 // Last filter ID. Used to generate a new ID for an added filter.
576 // Load existing Talkers into Talker List.
577 m_talkerListModel
.loadTalkerCodesFromConfig(m_config
);
579 // Last talker ID. Used to generate a new ID for an added talker.
580 m_lastTalkerID
= m_talkerListModel
.highestTalkerId();
582 // Dictionary mapping languages to language codes.
583 m_languagesToCodes
.clear();
584 for (int i
= 0; i
< m_talkerListModel
.rowCount(); ++i
) {
585 QString fullLanguageCode
= m_talkerListModel
.getRow(i
).fullLanguageCode();
586 QString language
= TalkerCode::languageCodeToLanguage(fullLanguageCode
);
587 m_languagesToCodes
[language
] = fullLanguageCode
;
590 // Query for all the KCMKTTSD SynthPlugins and store the list in offers.
591 KService::List offers
= KServiceTypeTrader::self()->query("KTTSD/SynthPlugin");
593 // Iterate thru the possible plug ins getting their language support codes.
594 for(int i
=0; i
< offers
.count() ; ++i
)
596 QString synthName
= offers
[i
]->name();
597 QStringList languageCodes
= offers
[i
]->property("X-KDE-Languages").toStringList();
598 // Add language codes to the language-to-language code map.
599 QStringList::ConstIterator
endLanguages(languageCodes
.constEnd());
600 for( QStringList::ConstIterator it
= languageCodes
.constBegin(); it
!= endLanguages
; ++it
)
602 QString language
= TalkerCode::languageCodeToLanguage(*it
);
603 m_languagesToCodes
[language
] = *it
;
606 // All plugins support "Other".
607 // TODO: Eventually, this should not be necessary, since all plugins will know
608 // the languages they support and report them in call to getSupportedLanguages().
609 if (!languageCodes
.contains("other")) languageCodes
.append("other");
611 // Add supported language codes to synthesizer-to-language map.
612 m_synthToLangMap
[synthName
] = languageCodes
;
615 // Add "Other" language.
616 m_languagesToCodes
[i18n("Other")] = "other";
619 m_filterListModel
.clear();
620 m_sbdFilterListModel
.clear();
621 QStringList filterIDsList
= generalConfig
.readEntry("FilterIDs", QStringList());
622 // kDebug() << "KCMKttsMgr::load: FilterIDs = " << filterIDsList;
623 if (!filterIDsList
.isEmpty())
625 QStringList::ConstIterator itEnd
= filterIDsList
.constEnd();
626 for (QStringList::ConstIterator it
= filterIDsList
.constBegin(); it
!= itEnd
; ++it
)
628 QString filterID
= *it
;
629 // kDebug() << "KCMKttsMgr::load: filterID = " << filterID;
630 KConfigGroup
filterConfig(m_config
, "Filter_" + filterID
);
631 QString desktopEntryName
= filterConfig
.readEntry("DesktopEntryName", QString());
632 // If a DesktopEntryName is not in the config file, it was configured before
633 // we started using them, when we stored translated plugin names instead.
634 // Try to convert the translated plugin name to a DesktopEntryName.
635 // DesktopEntryNames are better because user can change their desktop language
636 // and DesktopEntryName won't change.
637 QString filterPlugInName
;
638 filterPlugInName
= FilterDesktopEntryNameToName(desktopEntryName
);
639 if (!filterPlugInName
.isEmpty())
643 fi
.plugInName
= filterPlugInName
;
644 fi
.desktopEntryName
= desktopEntryName
;
645 fi
.userFilterName
= filterConfig
.readEntry("UserFilterName", filterPlugInName
);
646 fi
.multiInstance
= filterConfig
.readEntry("MultiInstance", false);
647 fi
.enabled
= filterConfig
.readEntry("Enabled", false);
648 // Determine if this filter is a Sentence Boundary Detector (SBD).
649 bool isSbd
= filterConfig
.readEntry("IsSBD", false);
651 m_sbdFilterListModel
.appendRow(fi
);
653 m_filterListModel
.appendRow(fi
);
654 if (filterID
.toInt() > m_lastFilterID
) m_lastFilterID
= filterID
.toInt();
659 // Add at least one unchecked instance of each available filter plugin if there is
660 // not already at least one instance and the filter can autoconfig itself.
661 offers
= KServiceTypeTrader::self()->query("KTTSD/FilterPlugin");
662 for (int i
=0; i
< offers
.count() ; ++i
)
664 QString filterPlugInName
= offers
[i
]->name();
665 QString desktopEntryName
= FilterNameToDesktopEntryName(filterPlugInName
);
666 if (!desktopEntryName
.isEmpty() && (countFilterPlugins(filterPlugInName
) == 0))
668 // Must load plugin to determine if it supports multiple instances
669 // and to see if it can autoconfigure itself.
670 KttsFilterConf
* filterPlugIn
= loadFilterPlugin(desktopEntryName
);
674 QString filterID
= QString::number(m_lastFilterID
);
675 QString groupName
= "Filter_" + filterID
;
676 filterPlugIn
->load(m_config
, groupName
);
677 QString userFilterName
= filterPlugIn
->userPlugInName();
678 if (!userFilterName
.isEmpty())
680 kDebug() << "KCMKttsMgr::load: auto-configuring filter " << userFilterName
;
681 bool multiInstance
= filterPlugIn
->supportsMultiInstance();
684 fi
.userFilterName
= userFilterName
;
685 fi
.plugInName
= filterPlugInName
;
686 fi
.desktopEntryName
= desktopEntryName
;
688 fi
.multiInstance
= multiInstance
;
689 // Determine if plugin is an SBD filter.
690 bool isSbd
= filterPlugIn
->isSBD();
692 m_sbdFilterListModel
.appendRow(fi
);
694 m_filterListModel
.appendRow(fi
);
695 KConfigGroup
filterConfig(m_config
, groupName
);
696 filterPlugIn
->save(m_config
, groupName
);
697 filterConfig
.writeEntry("DesktopEntryName", desktopEntryName
);
698 filterConfig
.writeEntry("UserFilterName", userFilterName
);
699 filterConfig
.writeEntry("Enabled", isSbd
);
700 filterConfig
.writeEntry("MultiInstance", multiInstance
);
701 filterConfig
.writeEntry("IsSBD", isSbd
);
702 filterIDsList
.append(filterID
);
703 } else m_lastFilterID
--;
705 kDebug() << "KCMKttsMgr::load: Unable to load filter plugin " << filterPlugInName
706 << " DesktopEntryName " << desktopEntryName
<< endl
;
710 // Rewrite list of FilterIDs in case we added any.
711 QString filterIDs
= filterIDsList
.join(",");
712 generalConfig
.writeEntry("FilterIDs", filterIDs
);
715 // Uncheck and disable KTTSD checkbox if no Talkers are configured.
716 if (m_talkerListModel
.rowCount() == 0)
718 enableKttsdCheckBox
->setChecked(false);
719 enableKttsdCheckBox
->setEnabled(false);
720 slotEnableKttsd_toggled(false);
727 KConfigGroup
alsaConfig(m_config
, "ALSAPlayer");
728 KttsUtils::setCbItemFromText(pcmComboBox
, alsaConfig
.readEntry("PcmName", "default"));
729 pcmCustom
->setText(alsaConfig
.readEntry("CustomPcmName", ""));
731 // Update controls based on new states.
732 updateTalkerButtons();
733 updateFilterButtons();
735 slotPhononRadioButton_toggled(phononRadioButton
->isChecked());
736 slotAlsaRadioButton_toggled(alsaRadioButton
->isChecked());
739 m_suppressConfigChanged
= false;
743 * This function gets called when the user wants to save the settings in
744 * the user interface, updating the config files or wherever the
745 * configuration is stored. The method is called when the user clicks "Apply"
748 void KCMKttsMgr::save()
750 // kDebug() << "KCMKttsMgr::save: Running";
754 m_config
->deleteGroup("General", 0);
756 // Set the group general for the configuration of kttsd itself (no plug ins)
757 KConfigGroup
generalConfig(m_config
, "General");
759 // Set text interrumption messages and paths
760 generalConfig
.writeEntry("TextPreMsgEnabled", textPreMsgCheck
->isChecked());
761 generalConfig
.writeEntry("TextPreMsg", textPreMsg
->text());
763 generalConfig
.writeEntry("TextPreSndEnabled", textPreSndCheck
->isChecked());
764 generalConfig
.writeEntry("TextPreSnd", PlugInConf::realFilePath(textPreSnd
->url().path()));
766 generalConfig
.writeEntry("TextPostMsgEnabled", textPostMsgCheck
->isChecked());
767 generalConfig
.writeEntry("TextPostMsg", textPostMsg
->text());
769 generalConfig
.writeEntry("TextPostSndEnabled", textPostSndCheck
->isChecked());
770 generalConfig
.writeEntry("TextPostSnd", PlugInConf::realFilePath(textPostSnd
->url().path()));
773 generalConfig
.writeEntry("AutoStartManager", autostartMgrCheckBox
->isChecked());
774 generalConfig
.writeEntry("AutoExitManager", autoexitMgrCheckBox
->isChecked());
776 // Uncheck and disable KTTSD checkbox if no Talkers are configured.
777 // Enable checkbox if at least one Talker is configured.
778 bool enableKttsdWasToggled
= false;
779 if (m_talkerListModel
.rowCount() == 0)
781 enableKttsdWasToggled
= enableKttsdCheckBox
->isChecked();
782 enableKttsdCheckBox
->setChecked(false);
783 enableKttsdCheckBox
->setEnabled(false);
784 // Might as well zero LastTalkerID as well.
788 enableKttsdCheckBox
->setEnabled(true);
790 generalConfig
.writeEntry("EnableKttsd", enableKttsdCheckBox
->isChecked());
794 int audioOutputMethod
= 0;
795 // if (gstreamerRadioButton->isChecked()) audioOutputMethod = 1;
796 if (alsaRadioButton
->isChecked()) audioOutputMethod
= 2;
797 generalConfig
.writeEntry("AudioOutputMethod", audioOutputMethod
);
798 generalConfig
.writeEntry("AudioStretchFactor", timeBox
->value());
799 generalConfig
.writeEntry("KeepAudio", keepAudioCheckBox
->isChecked());
800 generalConfig
.writeEntry("KeepAudioPath", keepAudioPath
->url().path());
802 // Get ordered list of all talker IDs.
803 QStringList talkerIDsList
;
804 for (int i
= 0; i
< m_talkerListModel
.rowCount(); ++i
)
805 talkerIDsList
.append(m_talkerListModel
.getRow(i
).id());
806 QString talkerIDs
= talkerIDsList
.join(",");
807 generalConfig
.writeEntry("TalkerIDs", talkerIDs
);
809 // Erase obsolete Talker_nn sections.
810 QStringList groupList
= m_config
->groupList();
811 int groupListCount
= groupList
.count();
812 for (int groupNdx
= 0; groupNdx
< groupListCount
; ++groupNdx
)
814 QString groupName
= groupList
[groupNdx
];
815 if (groupName
.left(7) == "Talker_")
817 QString groupTalkerID
= groupName
.mid(7);
818 if (!talkerIDsList
.contains(groupTalkerID
))
819 m_config
->deleteGroup(groupName
, 0);
823 // Get ordered list of all filter IDs. Record enabled state of each filter.
824 QStringList filterIDsList
;
825 for (int i
= 0; i
< m_filterListModel
.rowCount(); ++i
) {
826 FilterItem fi
= m_filterListModel
.getRow(i
);
827 filterIDsList
.append(fi
.id
);
828 KConfigGroup
filterConfig(m_config
, "Filter_" + fi
.id
);
829 filterConfig
.writeEntry("Enabled", fi
.enabled
);
830 filterConfig
.writeEntry("IsSBD", false);
832 for (int i
= 0; i
< m_sbdFilterListModel
.rowCount(); ++i
) {
833 FilterItem fi
= m_sbdFilterListModel
.getRow(i
);
834 filterIDsList
.append(fi
.id
);
835 KConfigGroup
filterConfig(m_config
, "Filter_" + fi
.id
);
836 filterConfig
.writeEntry("Enabled", fi
.enabled
);
837 filterConfig
.writeEntry("IsSBD", true);
839 QString filterIDs
= filterIDsList
.join(",");
840 generalConfig
.writeEntry("FilterIDs", filterIDs
);
842 // Erase obsolete Filter_nn sections.
843 for (int groupNdx
= 0; groupNdx
< groupListCount
; ++groupNdx
)
845 QString groupName
= groupList
[groupNdx
];
846 if (groupName
.left(7) == "Filter_")
848 QString groupFilterID
= groupName
.mid(7);
849 if (!filterIDsList
.contains(groupFilterID
))
850 m_config
->deleteGroup(groupName
, 0);
855 KConfigGroup
alsaConfig(m_config
, "ALSAPlayer");
856 alsaConfig
.writeEntry("PcmName", pcmComboBox
->currentText());
857 alsaConfig
.writeEntry("CustomPcmName", pcmCustom
->text());
861 // If we automatically unchecked the Enable KTTSD checkbox, stop KTTSD.
862 if (enableKttsdWasToggled
)
863 slotEnableKttsd_toggled(false);
866 // If KTTSD is running, reinitialize it.
869 kDebug() << "Restarting KTTSD";
875 void KCMKttsMgr::slotTabChanged()
877 // TODO: Commentting this out to avoid a crash. It seems there is a bug in
878 // KDialog. The workaround is to call setDefaultButton(), but that method
879 // is not available to a KCModule. Uncomment this when bug is fixed.
880 // setButtons(buttons());
881 int currentPageIndex
= mainTab
->currentIndex();
882 if (currentPageIndex
== wpJobs
)
886 KMessageBox::information(this,
887 i18n("You have made changes to the configuration but have not saved them yet. "
888 "Click Apply to save the changes or Cancel to abandon the changes."));
894 * This function is called to set the settings in the module to sensible
895 * default values. It gets called when hitting the "Default" button. The
896 * default values should probably be the same as the ones the application
897 * uses when started without a config file.
899 void KCMKttsMgr::defaults() {
900 // kDebug() << "Running: KCMKttsMgr::defaults: Running";
902 int currentPageIndex
= mainTab
->currentIndex();
903 bool changed
= false;
904 switch (currentPageIndex
)
907 if (autostartMgrCheckBox
->isChecked() != autostartMgrCheckBoxValue
)
910 autostartMgrCheckBox
->setChecked(
911 autostartMgrCheckBoxValue
);
913 if (autoexitMgrCheckBox
->isChecked() != autoexitMgrCheckBoxValue
)
916 autoexitMgrCheckBox
->setChecked(
917 autoexitMgrCheckBoxValue
);
922 if (textPreMsgCheck
->isChecked() != textPreMsgCheckValue
)
925 textPreMsgCheck
->setChecked(textPreMsgCheckValue
);
927 if (textPreMsg
->text() != i18n(textPreMsgValue
.toUtf8()))
930 textPreMsg
->setText(i18n(textPreMsgValue
.toUtf8()));
932 if (textPreSndCheck
->isChecked() != textPreSndCheckValue
)
935 textPreSndCheck
->setChecked(textPreSndCheckValue
);
937 if (textPreSnd
->url().path() != textPreSndValue
)
940 textPreSnd
->setUrl(KUrl::fromPath(textPreSndValue
));
942 if (textPostMsgCheck
->isChecked() != textPostMsgCheckValue
)
945 textPostMsgCheck
->setChecked(textPostMsgCheckValue
);
947 if (textPostMsg
->text() != i18n(textPostMsgValue
.toUtf8()))
950 textPostMsg
->setText(i18n(textPostMsgValue
.toUtf8()));
952 if (textPostSndCheck
->isChecked() != textPostSndCheckValue
)
955 textPostSndCheck
->setChecked(textPostSndCheckValue
);
957 if (textPostSnd
->url().path() != textPostSndValue
)
960 textPostSnd
->setUrl(KUrl::fromPath(textPostSndValue
));
965 // Default to Phonon.
966 if (!phononRadioButton
->isChecked())
969 phononRadioButton
->setChecked(true);
971 if (timeBox
->value() != timeBoxValue
)
974 timeBox
->setValue(timeBoxValue
);
976 if (keepAudioCheckBox
->isChecked() !=
977 keepAudioCheckBoxValue
)
980 keepAudioCheckBox
->setChecked(keepAudioCheckBoxValue
);
982 if (keepAudioPath
->url().path() != KStandardDirs::locateLocal("data", "kttsd/audio/"))
985 keepAudioPath
->setUrl(KUrl::fromPath(
986 KStandardDirs::locateLocal("data", "kttsd/audio/")));
988 keepAudioPath
->setEnabled(keepAudioCheckBox
->isEnabled());
990 if (changed
) configChanged();
994 * This is a static method which gets called to realize the modules settings
995 * during the startup of KDE. NOTE that most modules do not implement this
996 * method, but modules like the keyboard and mouse modules, which directly
997 * interact with the X-server, need this method. As this method is static,
998 * it can avoid to create an instance of the user interface, which is often
999 * not needed in this case.
1001 void KCMKttsMgr::init(){
1002 // kDebug() << "KCMKttsMgr::init: Running";
1006 * This function returns the small quickhelp.
1007 * That is displayed in the sidebar in the KControl
1009 QString
KCMKttsMgr::quickHelp() const{
1010 // kDebug() << "KCMKttsMgr::quickHelp: Running";
1012 "<h1>Text-to-Speech</h1>"
1013 "<p>This is the configuration for the text-to-speech dcop service</p>"
1014 "<p>This allows other applications to access text-to-speech resources</p>"
1015 "<p>Be sure to configure a default language for the language you are using as this will be the language used by most of the applications</p>");
1018 const KAboutData
* KCMKttsMgr::aboutData() const{
1020 new KAboutData(I18N_NOOP("kttsd"), 0, ki18n("KCMKttsMgr"),
1021 0, KLocalizedString(), KAboutData::License_GPL
,
1022 ki18n("(c) 2002, José Pablo Ezequiel Fernández"));
1024 about
->addAuthor(ki18n("José Pablo Ezequiel Fernández"), ki18n("Author") , "pupeno@kde.org");
1025 about
->addAuthor(ki18n("Gary Cramblitt"), ki18n("Maintainer") , "garycramblitt@comcast.net");
1026 about
->addAuthor(ki18n("Olaf Schmidt"), ki18n("Contributor"), "ojschmidt@kde.org");
1027 about
->addAuthor(ki18n("Paul Giannaros"), ki18n("Contributor"), "ceruleanblaze@gmail.com");
1033 * Loads the configuration plug in for a named talker plug in and type.
1034 * @param name DesktopEntryName of the Synthesizer.
1035 * @return Pointer to the configuration plugin for the Talker.
1037 PlugInConf
* KCMKttsMgr::loadTalkerPlugin(const QString
& name
)
1039 // kDebug() << "KCMKttsMgr::loadPlugin: Running";
1042 KService::List offers
= KServiceTypeTrader::self()->query("KTTSD/SynthPlugin",
1043 QString("DesktopEntryName == '%1'").arg(name
));
1045 if (offers
.count() == 1)
1047 // When the entry is found, load the plug in
1048 // First create a factory for the library
1049 KLibFactory
*factory
= KLibLoader::self()->factory(offers
[0]->library().toLatin1());
1051 // If the factory is created successfully, instantiate the PlugInConf class for the
1052 // specific plug in to get the plug in configuration object.
1053 PlugInConf
*plugIn
= KLibLoader::createInstance
<PlugInConf
>(
1054 offers
[0]->library().toLatin1(), NULL
, QStringList(offers
[0]->library().toLatin1()));
1056 // If everything went ok, return the plug in pointer.
1059 // Something went wrong, returning null.
1060 kDebug() << "KCMKttsMgr::loadTalkerPlugin: Unable to instantiate PlugInConf class for plugin " << name
;
1064 // Something went wrong, returning null.
1065 kDebug() << "KCMKttsMgr::loadTalkerPlugin: Unable to create Factory object for plugin "
1070 // The plug in was not found (unexpected behaviour, returns null).
1071 kDebug() << "KCMKttsMgr::loadTalkerPlugin: KTrader did not return an offer for plugin "
1077 * Loads the configuration plug in for a named filter plug in.
1078 * @param plugInName DesktopEntryName of the plugin.
1079 * @return Pointer to the configuration plugin for the Filter.
1081 KttsFilterConf
* KCMKttsMgr::loadFilterPlugin(const QString
& plugInName
)
1083 // kDebug() << "KCMKttsMgr::loadPlugin: Running";
1086 KService::List offers
= KServiceTypeTrader::self()->query("KTTSD/FilterPlugin",
1087 QString("DesktopEntryName == '%1'").arg(plugInName
));
1089 if (offers
.count() == 1)
1091 // When the entry is found, load the plug in
1092 // First create a factory for the library
1093 KLibFactory
*factory
= KLibLoader::self()->factory(offers
[0]->library().toLatin1());
1095 // If the factory is created successfully, instantiate the KttsFilterConf class for the
1096 // specific plug in to get the plug in configuration object.
1098 KttsFilterConf
*plugIn
=
1099 KLibLoader::createInstance
<KttsFilterConf
>(
1100 offers
[0]->library().toLatin1(), NULL
, QStringList(offers
[0]->library().toLatin1()),
1103 // If everything went ok, return the plug in pointer.
1106 // Something went wrong, returning null.
1107 kDebug() << "KCMKttsMgr::loadFilterPlugin: Unable to instantiate KttsFilterConf class for plugin " << plugInName
<< " error: " << errorNo
;
1111 // Something went wrong, returning null.
1112 kDebug() << "KCMKttsMgr::loadFilterPlugin: Unable to create Factory object for plugin " << plugInName
;
1116 // The plug in was not found (unexpected behaviour, returns null).
1117 kDebug() << "KCMKttsMgr::loadFilterPlugin: KTrader did not return an offer for plugin " << plugInName
;
1124 void KCMKttsMgr::slotAddTalkerButton_clicked()
1126 KDialog
* dlg
= new KDialog(this);
1127 dlg
->setCaption(i18n("Add Talker"));
1128 dlg
->setButtons(KDialog::Help
|KDialog::Ok
|KDialog::Cancel
);
1129 dlg
->setDefaultButton(KDialog::Cancel
);
1130 AddTalker
* addTalkerWidget
= new AddTalker(m_synthToLangMap
, dlg
, "AddTalker_widget");
1131 dlg
->setMainWidget(addTalkerWidget
);
1132 dlg
->setHelp("select-plugin", "kttsd");
1133 int dlgResult
= dlg
->exec();
1134 QString languageCode
= addTalkerWidget
->getLanguageCode();
1135 QString synthName
= addTalkerWidget
->getSynthesizer();
1137 // TODO: Also delete addTalkerWidget?
1138 if (dlgResult
!= QDialog::Accepted
) return;
1140 // If user chose "Other", must now get a language from him.
1141 if(languageCode
== "other")
1143 SelectLanguageDlg
* dlg
= new SelectLanguageDlg(
1145 i18n("Select Language"),
1147 SelectLanguageDlg::SingleSelect
,
1148 SelectLanguageDlg::BlankNotAllowed
);
1149 int dlgResult
= dlg
->exec();
1150 languageCode
= dlg
->selectedLanguageCode();
1152 // TODO: Also delete QTableWidget and hBox?
1153 if (dlgResult
!= QDialog::Accepted
) return;
1156 if (languageCode
.isEmpty()) return;
1157 QString language
= TalkerCode::languageCodeToLanguage(languageCode
);
1158 if (language
.isEmpty()) return;
1160 m_languagesToCodes
[language
] = languageCode
;
1162 // Assign a new Talker ID for the talker. Wraps around to 1.
1163 QString talkerID
= QString::number(m_lastTalkerID
+ 1);
1165 // Erase extraneous Talker configuration entries that might be there.
1166 m_config
->deleteGroup(QString("Talker_")+talkerID
, 0);
1169 // Convert translated plugin name to DesktopEntryName.
1170 QString desktopEntryName
= TalkerCode::TalkerNameToDesktopEntryName(synthName
);
1171 // This shouldn't happen, but just in case.
1172 if (desktopEntryName
.isEmpty()) return;
1175 m_loadedTalkerPlugIn
= loadTalkerPlugin(desktopEntryName
);
1176 if (!m_loadedTalkerPlugIn
) return;
1178 // Give plugin the user's language code and permit plugin to autoconfigure itself.
1179 m_loadedTalkerPlugIn
->setDesiredLanguage(languageCode
);
1180 m_loadedTalkerPlugIn
->load(m_config
, QString("Talker_")+talkerID
);
1182 // If plugin was able to configure itself, it returns a full talker code.
1183 // If not, display configuration dialog for user to configure the plugin.
1184 QString talkerCode
= m_loadedTalkerPlugIn
->getTalkerCode();
1185 if (talkerCode
.isEmpty())
1187 // Display configuration dialog.
1190 if (!m_loadedTalkerPlugIn
)
1196 talkerCode
= m_loadedTalkerPlugIn
->getTalkerCode();
1199 // If still no Talker Code, abandon.
1200 if (!talkerCode
.isEmpty())
1202 // Let plugin save its configuration.
1203 m_loadedTalkerPlugIn
->save(m_config
, QString("Talker_"+talkerID
));
1205 // Record last Talker ID used for next add.
1206 m_lastTalkerID
= talkerID
.toInt();
1208 // Record configuration data. Note, might as well do this now.
1209 KConfigGroup
talkerConfig(m_config
, QString("Talker_")+talkerID
);
1210 talkerConfig
.writeEntry("DesktopEntryName", desktopEntryName
);
1211 talkerCode
= TalkerCode::normalizeTalkerCode(talkerCode
, languageCode
);
1212 talkerConfig
.writeEntry("TalkerCode", talkerCode
);
1215 // Add to list of Talkers.
1216 TalkerCode tc
= TalkerCode(talkerCode
);
1218 tc
.setDesktopEntryName(desktopEntryName
);
1219 m_talkerListModel
.appendRow(tc
);
1221 // Make sure visible.
1222 const QModelIndex modelIndex
= m_talkerListModel
.index(m_talkerListModel
.rowCount(),
1224 talkersView
->scrollTo(modelIndex
);
1226 // Select the new item, update buttons.
1227 talkersView
->setCurrentIndex(modelIndex
);
1228 updateTalkerButtons();
1230 // Inform Control Center that change has been made.
1234 // Don't need plugin in memory anymore.
1235 delete m_loadedTalkerPlugIn
;
1236 m_loadedTalkerPlugIn
= 0;
1243 // kDebug() << "KCMKttsMgr::addTalker: done.";
1246 void KCMKttsMgr::slotAddNormalFilterButton_clicked()
1251 void KCMKttsMgr:: slotAddSbdFilterButton_clicked()
1259 void KCMKttsMgr::addFilter( bool sbd
)
1261 QTreeView
* lView
= filtersView
;
1262 if (sbd
) lView
= sbdsView
;
1263 FilterListModel
* model
= qobject_cast
<FilterListModel
*>(lView
->model());
1265 // Build a list of filters that support multiple instances and let user choose.
1266 QStringList filterPlugInNames
;
1267 for (int i
= 0; i
< model
->rowCount(); ++i
) {
1268 FilterItem fi
= model
->getRow(i
);
1269 if (fi
.multiInstance
)
1271 if (!filterPlugInNames
.contains(fi
.plugInName
))
1272 filterPlugInNames
.append(fi
.plugInName
);
1275 // Append those available plugins not yet in the list at all.
1276 KService::List offers
= KServiceTypeTrader::self()->query("KTTSD/FilterPlugin");
1277 for (int i
=0; i
< offers
.count() ; ++i
)
1279 QString filterPlugInName
= offers
[i
]->name();
1280 if (countFilterPlugins(filterPlugInName
) == 0)
1282 QString desktopEntryName
= FilterNameToDesktopEntryName(filterPlugInName
);
1283 KttsFilterConf
* filterConf
= loadFilterPlugin( desktopEntryName
);
1286 if (filterConf
->isSBD() == sbd
)
1287 filterPlugInNames
.append(filterPlugInName
);
1293 // If no choice (shouldn't happen), bail out.
1294 // kDebug() << "KCMKttsMgr::addFilter: filterPluginNames = " << filterPlugInNames;
1295 if (filterPlugInNames
.count() == 0) return;
1297 // If exactly one choice, skip selection dialog, otherwise display list to user to select from.
1298 bool okChosen
= false;
1299 QString filterPlugInName
;
1300 if (filterPlugInNames
.count() > 1)
1302 filterPlugInName
= KInputDialog::getItem(
1303 i18n("Select Filter"),
1310 if (!okChosen
) return;
1312 filterPlugInName
= filterPlugInNames
[0];
1314 // kDebug() << "KCMKttsMgr::addFilter: filterPlugInName = " << filterPlugInName;
1316 // Assign a new Filter ID for the filter. Wraps around to 1.
1317 QString filterID
= QString::number(m_lastFilterID
+ 1);
1319 // Erase extraneous Filter configuration entries that might be there.
1320 m_config
->deleteGroup(QString("Filter_")+filterID
, 0);
1323 // Get DesktopEntryName from the translated name.
1324 QString desktopEntryName
= FilterNameToDesktopEntryName(filterPlugInName
);
1325 // This shouldn't happen, but just in case.
1326 if (desktopEntryName
.isEmpty()) return;
1329 m_loadedFilterPlugIn
= loadFilterPlugin(desktopEntryName
);
1330 if (!m_loadedFilterPlugIn
) return;
1332 // Permit plugin to autoconfigure itself.
1333 m_loadedFilterPlugIn
->load(m_config
, QString("Filter_")+filterID
);
1335 // Display configuration dialog for user to configure the plugin.
1339 if (!m_loadedFilterPlugIn
)
1346 // Get user's name for Filter.
1347 QString userFilterName
= m_loadedFilterPlugIn
->userPlugInName();
1349 // If user properly configured the plugin, save its configuration.
1350 if ( !userFilterName
.isEmpty() )
1352 // Let plugin save its configuration.
1353 m_loadedFilterPlugIn
->save(m_config
, QString("Filter_"+filterID
));
1355 // Record last Filter ID used for next add.
1356 m_lastFilterID
= filterID
.toInt();
1358 // Determine if filter supports multiple instances.
1359 bool multiInstance
= m_loadedFilterPlugIn
->supportsMultiInstance();
1361 // Record configuration data. Note, might as well do this now.
1362 KConfigGroup
filterConfig(m_config
, QString("Filter_"+filterID
));
1363 filterConfig
.writeEntry("DesktopEntryName", desktopEntryName
);
1364 filterConfig
.writeEntry("UserFilterName", userFilterName
);
1365 filterConfig
.writeEntry("MultiInstance", multiInstance
);
1366 filterConfig
.writeEntry("Enabled", true);
1367 filterConfig
.writeEntry("IsSBD", sbd
);
1370 // Add listview item.
1373 fi
.plugInName
= filterPlugInName
;
1374 fi
.userFilterName
= userFilterName
;
1375 fi
.desktopEntryName
= desktopEntryName
;
1376 fi
.multiInstance
= multiInstance
;
1378 model
->appendRow(fi
);
1380 // Make sure visible.
1381 QModelIndex modelIndex
= model
->index(model
->rowCount() - 1, 0, QModelIndex());
1382 lView
->scrollTo(modelIndex
);
1384 // Select the new item, update buttons.
1385 lView
->setCurrentIndex(modelIndex
);
1389 updateFilterButtons();
1391 // Inform Control Center that change has been made.
1395 // Don't need plugin in memory anymore.
1396 delete m_loadedFilterPlugIn
;
1397 m_loadedFilterPlugIn
= 0;
1401 // kDebug() << "KCMKttsMgr::addFilter: done.";
1407 void KCMKttsMgr::slotRemoveTalkerButton_clicked(){
1408 // kDebug() << "KCMKttsMgr::removeTalker: Running";
1410 // Get the selected talker.
1411 QModelIndex modelIndex
= talkersView
->currentIndex();
1412 if (!modelIndex
.isValid()) return;
1414 // Delete the talker from configuration file?
1415 QString talkerID
= m_talkerListModel
.getRow(modelIndex
.row()).id();
1416 m_config
->deleteGroup(QString("Talker_")+talkerID
, 0);
1418 // Delete the talker from the list of Talkers.
1419 m_talkerListModel
.removeRow(modelIndex
.row());
1421 updateTalkerButtons();
1423 // Emit configuration changed.
1427 void KCMKttsMgr::slotRemoveNormalFilterButton_clicked()
1429 removeFilter( false );
1432 void KCMKttsMgr::slotRemoveSbdFilterButton_clicked()
1434 removeFilter( true );
1440 void KCMKttsMgr::removeFilter( bool sbd
)
1442 // kDebug() << "KCMKttsMgr::removeFilter: Running";
1444 FilterListModel
* model
;
1449 lView
= filtersView
;
1450 model
= qobject_cast
<FilterListModel
*>(lView
->model());
1451 QModelIndex modelIndex
= lView
->currentIndex();
1452 if (!modelIndex
.isValid()) return;
1453 QString filterID
= model
->getRow(modelIndex
.row()).id
;
1454 // Delete the filter from list view.
1455 model
->removeRow(modelIndex
.row());
1459 updateFilterButtons();
1461 // Delete the filter from the configuration file?
1462 kDebug() << "KCMKttsMgr::removeFilter: removing FilterID = " << filterID
<< " from config file.";
1463 m_config
->deleteGroup(QString("Filter_")+filterID
, 0);
1465 // Emit configuration changed.
1469 void KCMKttsMgr::slotHigherTalkerPriorityButton_clicked()
1471 QModelIndex modelIndex
= talkersView
->currentIndex();
1472 if (!modelIndex
.isValid()) return;
1473 m_talkerListModel
.swap(modelIndex
.row(), modelIndex
.row() - 1);
1474 modelIndex
= m_talkerListModel
.index(modelIndex
.row() - 1, 0, QModelIndex());
1475 talkersView
->scrollTo(modelIndex
);
1476 talkersView
->setCurrentIndex(modelIndex
);
1477 updateTalkerButtons();
1481 void KCMKttsMgr::slotHigherNormalFilterPriorityButton_clicked()
1483 QModelIndex modelIndex
= filtersView
->currentIndex();
1484 if (!modelIndex
.isValid()) return;
1485 m_filterListModel
.swap(modelIndex
.row(), modelIndex
.row() - 1);
1486 modelIndex
= m_filterListModel
.index(modelIndex
.row() - 1, 0, QModelIndex());
1487 filtersView
->scrollTo(modelIndex
);
1488 filtersView
->setCurrentIndex(modelIndex
);
1489 updateFilterButtons();
1493 void KCMKttsMgr::slotHigherSbdFilterPriorityButton_clicked()
1495 QModelIndex modelIndex
= sbdsView
->currentIndex();
1496 if (!modelIndex
.isValid()) return;
1497 m_sbdFilterListModel
.swap(modelIndex
.row(), modelIndex
.row() - 1);
1498 modelIndex
= m_sbdFilterListModel
.index(modelIndex
.row() - 1, 0, QModelIndex());
1499 sbdsView
->scrollTo(modelIndex
);
1500 sbdsView
->setCurrentIndex(modelIndex
);
1505 void KCMKttsMgr::slotLowerTalkerPriorityButton_clicked()
1507 QModelIndex modelIndex
= talkersView
->currentIndex();
1508 if (!modelIndex
.isValid()) return;
1509 m_talkerListModel
.swap(modelIndex
.row(), modelIndex
.row() + 1);
1510 modelIndex
= m_talkerListModel
.index(modelIndex
.row() + 1, 0, QModelIndex());
1511 talkersView
->scrollTo(modelIndex
);
1512 talkersView
->setCurrentIndex(modelIndex
);
1513 updateTalkerButtons();
1517 void KCMKttsMgr::slotLowerNormalFilterPriorityButton_clicked()
1519 QModelIndex modelIndex
= filtersView
->currentIndex();
1520 if (!modelIndex
.isValid()) return;
1521 m_filterListModel
.swap(modelIndex
.row(), modelIndex
.row() + 1);
1522 modelIndex
= m_filterListModel
.index(modelIndex
.row() + 1, 0, QModelIndex());
1523 filtersView
->scrollTo(modelIndex
);
1524 filtersView
->setCurrentIndex(modelIndex
);
1525 updateFilterButtons();
1529 void KCMKttsMgr::slotLowerSbdFilterPriorityButton_clicked()
1531 QModelIndex modelIndex
= sbdsView
->currentIndex();
1532 if (!modelIndex
.isValid()) return;
1533 m_sbdFilterListModel
.swap(modelIndex
.row(), modelIndex
.row() + 1);
1534 modelIndex
= m_sbdFilterListModel
.index(modelIndex
.row() + 1, 0, QModelIndex());
1535 sbdsView
->scrollTo(modelIndex
);
1536 sbdsView
->setCurrentIndex(modelIndex
);
1542 * Update the status of the Talker buttons.
1544 void KCMKttsMgr::updateTalkerButtons(){
1545 // kDebug() << "KCMKttsMgr::updateTalkerButtons: Running";
1546 QModelIndex modelIndex
= talkersView
->currentIndex();
1547 if (modelIndex
.isValid()) {
1548 removeTalkerButton
->setEnabled(true);
1549 configureTalkerButton
->setEnabled(true);
1550 higherTalkerPriorityButton
->setEnabled(modelIndex
.row() != 0);
1551 lowerTalkerPriorityButton
->setEnabled(modelIndex
.row() < (m_talkerListModel
.rowCount() - 1));
1553 removeTalkerButton
->setEnabled(false);
1554 configureTalkerButton
->setEnabled(false);
1555 higherTalkerPriorityButton
->setEnabled(false);
1556 lowerTalkerPriorityButton
->setEnabled(false);
1558 // kDebug() << "KCMKttsMgr::updateTalkerButtons: Exiting";
1562 * Update the status of the normal Filter buttons.
1564 void KCMKttsMgr::updateFilterButtons(){
1565 // kDebug() << "KCMKttsMgr::updateFilterButtons: Running";
1566 QModelIndex modelIndex
= filtersView
->currentIndex();
1567 if (modelIndex
.isValid()) {
1568 removeFilterButton
->setEnabled(true);
1569 configureFilterButton
->setEnabled(true);
1570 higherFilterPriorityButton
->setEnabled(modelIndex
.row() != 0);
1571 lowerFilterPriorityButton
->setEnabled(modelIndex
.row() < (m_filterListModel
.rowCount() - 1));
1573 removeFilterButton
->setEnabled(false);
1574 configureFilterButton
->setEnabled(false);
1575 higherFilterPriorityButton
->setEnabled(false);
1576 lowerFilterPriorityButton
->setEnabled(false);
1578 // kDebug() << "KCMKttsMgr::updateFilterButtons: Exiting";
1582 * Update the status of the SBD buttons.
1584 void KCMKttsMgr::updateSbdButtons(){
1585 // kDebug() << "KCMKttsMgr::updateSbdButtons: Running";
1586 QModelIndex modelIndex
= sbdsView
->currentIndex();
1587 if (modelIndex
.isValid()) {
1588 m_sbdBtnEdit
->setEnabled( true );
1589 m_sbdBtnUp
->setEnabled( modelIndex
.row() != 0 );
1590 m_sbdBtnDown
->setEnabled( modelIndex
.row() < (m_sbdFilterListModel
.rowCount() -1));
1591 m_sbdBtnRemove
->setEnabled( true );
1593 m_sbdBtnEdit
->setEnabled( false );
1594 m_sbdBtnUp
->setEnabled( false );
1595 m_sbdBtnDown
->setEnabled( false );
1596 m_sbdBtnRemove
->setEnabled( false );
1598 // kDebug() << "KCMKttsMgr::updateSbdButtons: Exiting";
1602 * This signal is emitted whenever user checks/unchecks the Enable TTS System check box.
1604 void KCMKttsMgr::slotEnableKttsd_toggled(bool)
1606 // Prevent re-entrancy.
1607 static bool reenter
;
1608 if (reenter
) return;
1610 // See if KTTSD is running.
1611 bool kttsdRunning
= (QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.kttsd"));
1613 // kDebug() << "KCMKttsMgr::slotEnableKttsd_toggled: kttsdRunning = " << kttsdRunning;
1614 // If Enable KTTSD check box is checked and it is not running, then start KTTSD.
1615 if (enableKttsdCheckBox
->isChecked())
1619 // kDebug() << "KCMKttsMgr::slotEnableKttsd_toggled:: Starting KTTSD";
1621 if (KToolInvocation::startServiceByDesktopName("kttsd", QStringList(), &error
))
1623 kDebug() << "Starting KTTSD failed with message " << error
;
1624 enableKttsdCheckBox
->setChecked(false);
1633 // If check box is not checked and it is running, then stop KTTSD.
1637 // kDebug() << "KCMKttsMgr::slotEnableKttsd_toggled:: Stopping KTTSD";
1638 m_kspeech
->kttsdExit();
1645 void KCMKttsMgr::slotAutoStartMgrCheckBox_toggled(bool checked
)
1647 autoexitMgrCheckBox
->setEnabled(checked
);
1651 void KCMKttsMgr::slotTextPreMsgCheck_toggled(bool checked
)
1653 textPreMsg
->setEnabled(checked
);
1657 void KCMKttsMgr::slotTextPreSndCheck_toggled(bool checked
)
1659 textPreSnd
->setEnabled(checked
);
1663 void KCMKttsMgr::slotTextPostMsgCheck_toggled(bool checked
)
1665 textPostMsg
->setEnabled(checked
);
1669 void KCMKttsMgr::slotTextPostSndCheck_toggled(bool checked
)
1671 textPostSnd
->setEnabled(checked
);
1676 * This signal is emitted whenever user checks/unchecks the Phonon radio button.
1678 void KCMKttsMgr::slotPhononRadioButton_toggled(bool state
)
1685 * This signal is emitted whenever user checks/unchecks the ALSA radio button.
1687 void KCMKttsMgr::slotAlsaRadioButton_toggled(bool state
)
1689 pcmLabel
->setEnabled(state
);
1690 pcmComboBox
->setEnabled(state
);
1691 pcmCustom
->setEnabled(state
&& pcmComboBox
->currentText() == "custom");
1696 * This is emitted whenever user activates the ALSA pcm combobox.
1698 void KCMKttsMgr::slotPcmComboBox_activated()
1700 pcmCustom
->setEnabled(pcmComboBox
->currentText() == "custom");
1704 * This slot is called whenever KTTSD starts or restarts.
1706 void KCMKttsMgr::kttsdStarted()
1708 // kDebug() << "KCMKttsMgr::kttsdStarted: Running";
1709 bool kttsdLoaded
= (m_jobMgrPart
!= 0);
1710 // Load Job Manager Part library.
1713 m_jobMgrPart
= KParts::ComponentFactory::createPartInstanceFromLibrary
<KParts::ReadOnlyPart
>(
1714 "libkttsjobmgrpart", mainTab
, this);
1717 // Add the Job Manager part as a new tab.
1718 mainTab
->addTab(m_jobMgrPart
->widget(), i18n("Jobs"));
1722 kDebug() << "KCMKttsMgr::kttsdStarted: Could not create kttsjobmgr part.";
1724 // Check/Uncheck the Enable KTTSD check box.
1727 enableKttsdCheckBox
->setChecked(true);
1728 m_kspeech
= new OrgKdeKSpeechInterface("org.kde.kttsd", "/KSpeech", QDBusConnection::sessionBus());
1729 m_kspeech
->setParent(this);
1730 m_kspeech
->setApplicationName("KCMKttsMgr");
1731 m_kspeech
->setIsSystemManager(true);
1732 // Connect KTTSD DBUS signals to our slots.
1733 connect(m_kspeech
, SIGNAL(kttsdStarted()),
1734 this, SLOT(kttsdStarted()));
1735 connect(m_kspeech
, SIGNAL(kttsdExiting()),
1736 this, SLOT(kttsdExiting()));
1737 kttsdVersion
->setText(i18n("KTTSD Version: %1", m_kspeech
->version()));
1740 enableKttsdCheckBox
->setChecked(false);
1747 * This slot is called whenever KTTSD is about to exit.
1749 void KCMKttsMgr::kttsdExiting()
1751 // kDebug() << "KCMKttsMgr::kttsdExiting: Running";
1754 mainTab
->removeTab(wpJobs
);
1755 delete m_jobMgrPart
;
1758 enableKttsdCheckBox
->setChecked(false);
1761 kttsdVersion
->setText(i18n("KTTSD not running"));
1765 * User has requested display of talker configuration dialog.
1767 void KCMKttsMgr::slotConfigureTalkerButton_clicked()
1769 // Get highlighted plugin from Talker ListView and load into memory.
1770 QModelIndex modelIndex
= talkersView
->currentIndex();
1771 if (!modelIndex
.isValid()) return;
1772 TalkerCode tc
= m_talkerListModel
.getRow(modelIndex
.row());
1773 QString talkerID
= tc
.id();
1774 QString synthName
= tc
.plugInName();
1775 QString desktopEntryName
= tc
.desktopEntryName();
1776 QString languageCode
= tc
.fullLanguageCode();
1777 m_loadedTalkerPlugIn
= loadTalkerPlugin(desktopEntryName
);
1778 if (!m_loadedTalkerPlugIn
) return;
1779 // kDebug() << "KCMKttsMgr::slotConfigureTalkerButton_clicked: plugin for " << synthName << " loaded successfully.";
1781 // Tell plugin to load its configuration.
1782 m_loadedTalkerPlugIn
->setDesiredLanguage(languageCode
);
1783 // kDebug() << "KCMKttsMgr::slotConfigureTalkerButton_clicked: about to call plugin load() method with Talker ID = " << talkerID;
1784 m_loadedTalkerPlugIn
->load(m_config
, QString("Talker_")+talkerID
);
1786 // Display configuration dialog.
1790 if (!m_loadedTalkerPlugIn
)
1797 // Get Talker Code. Note that plugin may return a code different from before.
1798 QString talkerCode
= m_loadedTalkerPlugIn
->getTalkerCode();
1800 // If plugin was successfully configured, save its configuration.
1801 if (!talkerCode
.isEmpty())
1803 m_loadedTalkerPlugIn
->save(m_config
, QString("Talker_")+talkerID
);
1804 talkerCode
= TalkerCode::normalizeTalkerCode(talkerCode
, languageCode
);
1805 KConfigGroup
talkerConfig(m_config
, QString("Talker_")+talkerID
);
1806 talkerConfig
.writeEntry("TalkerCode", talkerCode
);
1810 tc
.setTalkerCode(talkerCode
);
1811 m_talkerListModel
.updateRow(modelIndex
.row(), tc
);
1812 // Inform Control Center that configuration has changed.
1816 delete m_loadedTalkerPlugIn
;
1817 m_loadedTalkerPlugIn
= 0;
1822 void KCMKttsMgr::slotConfigureNormalFilterButton_clicked()
1824 configureFilterItem( false );
1827 void KCMKttsMgr::slotConfigureSbdFilterButton_clicked()
1829 configureFilterItem( true );
1833 * User has requested display of filter configuration dialog.
1835 void KCMKttsMgr::configureFilterItem( bool sbd
)
1837 // Get highlighted plugin from Filter ListView and load into memory.
1839 FilterListModel
* model
;
1842 model
= &m_sbdFilterListModel
;
1844 lView
= filtersView
;
1845 model
= &m_filterListModel
;
1847 QModelIndex modelIndex
= lView
->currentIndex();
1848 if (!modelIndex
.isValid()) return;
1849 FilterItem fi
= model
->getRow(modelIndex
.row());
1850 QString filterID
= fi
.id
;
1851 QString filterPlugInName
= fi
.plugInName
;
1852 QString desktopEntryName
= fi
.desktopEntryName
;
1853 if (desktopEntryName
.isEmpty()) return;
1854 m_loadedFilterPlugIn
= loadFilterPlugin(desktopEntryName
);
1855 if (!m_loadedFilterPlugIn
) return;
1856 // kDebug() << "KCMKttsMgr::slot_configureFilter: plugin for " << filterPlugInName << " loaded successfully.";
1858 // Tell plugin to load its configuration.
1859 // kDebug() << "KCMKttsMgr::slot_configureFilter: about to call plugin load() method with Filter ID = " << filterID;
1860 m_loadedFilterPlugIn
->load(m_config
, QString("Filter_")+filterID
);
1862 // Display configuration dialog.
1866 if (!m_loadedFilterPlugIn
)
1873 // Get user's name for the plugin.
1874 QString userFilterName
= m_loadedFilterPlugIn
->userPlugInName();
1876 // If user properly configured the plugin, save the configuration.
1877 if ( !userFilterName
.isEmpty() )
1879 // Let plugin save its configuration.
1880 m_loadedFilterPlugIn
->save(m_config
, QString("Filter_")+filterID
);
1882 // Save configuration.
1883 KConfigGroup
filterConfig(m_config
, QString("Filter_")+filterID
);
1884 filterConfig
.writeEntry("DesktopEntryName", desktopEntryName
);
1885 filterConfig
.writeEntry("UserFilterName", userFilterName
);
1886 filterConfig
.writeEntry("Enabled", true);
1887 filterConfig
.writeEntry("MultiInstance", m_loadedFilterPlugIn
->supportsMultiInstance());
1888 filterConfig
.writeEntry("IsSBD", sbd
);
1895 fi
.desktopEntryName
= desktopEntryName
;
1896 fi
.userFilterName
= userFilterName
;
1898 fi
.multiInstance
= m_loadedFilterPlugIn
->supportsMultiInstance();
1899 model
->updateRow(modelIndex
.row(), fi
);
1900 // Inform Control Center that configuration has changed.
1904 delete m_loadedFilterPlugIn
;
1905 m_loadedFilterPlugIn
= 0;
1911 * Display talker configuration dialog. The plugin is assumed already loaded into
1912 * memory referenced by m_loadedTalkerPlugIn.
1914 void KCMKttsMgr::configureTalker()
1916 if (!m_loadedTalkerPlugIn
) return;
1917 m_configDlg
= new KDialog(this);
1918 m_configDlg
->setCaption(i18n("Talker Configuration"));
1919 m_configDlg
->setButtons(KDialog::Help
|KDialog::Default
|KDialog::Ok
|KDialog::Cancel
);
1920 m_configDlg
->setDefaultButton(KDialog::Cancel
);
1921 m_configDlg
->setMainWidget(m_loadedTalkerPlugIn
);
1922 m_configDlg
->setHelp("configure-plugin", "kttsd");
1923 m_configDlg
->enableButtonOk(false);
1924 connect(m_loadedTalkerPlugIn
, SIGNAL( changed(bool) ), this, SLOT( slotConfigTalkerDlg_ConfigChanged() ));
1925 connect(m_configDlg
, SIGNAL( defaultClicked() ), this, SLOT( slotConfigTalkerDlg_DefaultClicked() ));
1926 connect(m_configDlg
, SIGNAL( cancelClicked() ), this, SLOT (slotConfigTalkerDlg_CancelClicked() ));
1927 // Create a Player object for the plugin to use for testing.
1928 int playerOption
= 0;
1930 if (phononRadioButton
->isChecked()) {
1933 if (alsaRadioButton
->isChecked()) {
1935 sinkName
= pcmComboBox
->currentText();
1937 float audioStretchFactor
= 1.0/(float(timeBox
->value())/100.0);
1938 // kDebug() << "KCMKttsMgr::configureTalker: playerOption = " << playerOption << " audioStretchFactor = " << audioStretchFactor << " sink name = " << sinkName;
1939 TestPlayer
* testPlayer
= new TestPlayer(this, "ktts_testplayer",
1940 playerOption
, audioStretchFactor
, sinkName
);
1941 m_loadedTalkerPlugIn
->setPlayer(testPlayer
);
1942 // Display the dialog.
1943 m_configDlg
->exec();
1944 // Done with Player object.
1945 if (m_loadedTalkerPlugIn
)
1948 m_loadedTalkerPlugIn
->setPlayer(0);
1953 * Display filter configuration dialog. The plugin is assumed already loaded into
1954 * memory referenced by m_loadedFilterPlugIn.
1956 void KCMKttsMgr::configureFilter()
1958 if (!m_loadedFilterPlugIn
) return;
1959 m_configDlg
= new KDialog(this);
1960 m_configDlg
->setCaption(i18n("Filter Configuration"));
1961 m_configDlg
->setButtons(KDialog::Help
|KDialog::Default
|KDialog::Ok
|KDialog::Cancel
);
1962 m_configDlg
->setDefaultButton(KDialog::Cancel
);
1963 m_loadedFilterPlugIn
->setMinimumSize(m_loadedFilterPlugIn
->minimumSizeHint());
1964 m_loadedFilterPlugIn
->show();
1965 m_configDlg
->setMainWidget(m_loadedFilterPlugIn
);
1966 m_configDlg
->setHelp("configure-filter", "kttsd");
1967 m_configDlg
->enableButtonOk(false);
1968 connect(m_loadedFilterPlugIn
, SIGNAL( changed(bool) ), this, SLOT( slotConfigFilterDlg_ConfigChanged() ));
1969 connect(m_configDlg
, SIGNAL( defaultClicked() ), this, SLOT( slotConfigFilterDlg_DefaultClicked() ));
1970 connect(m_configDlg
, SIGNAL( cancelClicked() ), this, SLOT (slotConfigFilterDlg_CancelClicked() ));
1971 // Display the dialog.
1972 m_configDlg
->exec();
1976 * Count number of configured Filters with the specified plugin name.
1978 int KCMKttsMgr::countFilterPlugins(const QString
& filterPlugInName
)
1981 for (int i
= 0; i
< m_filterListModel
.rowCount(); ++i
) {
1982 FilterItem fi
= m_filterListModel
.getRow(i
);
1983 if (fi
.plugInName
== filterPlugInName
) ++cnt
;
1985 for (int i
= 0; i
< m_sbdFilterListModel
.rowCount(); ++i
) {
1986 FilterItem fi
= m_sbdFilterListModel
.getRow(i
);
1987 if (fi
.plugInName
== filterPlugInName
) ++cnt
;
1992 void KCMKttsMgr::keepAudioCheckBox_toggled(bool checked
)
1994 keepAudioPath
->setEnabled(checked
);
1998 // Basically the slider values are logarithmic (0,...,1000) whereas percent
1999 // values are linear (50%,...,200%).
2001 // slider = alpha * (log(percent)-log(50))
2002 // with alpha = 1000/(log(200)-log(50))
2004 int KCMKttsMgr::percentToSlider(int percentValue
) {
2005 double alpha
= 1000 / (log(200.0) - log(50.0));
2006 return (int)floor (0.5 + alpha
* (log((float)percentValue
)-log(50.0)));
2009 int KCMKttsMgr::sliderToPercent(int sliderValue
) {
2010 double alpha
= 1000 / (log(200.0) - log(50.0));
2011 return (int)floor(0.5 + exp (sliderValue
/alpha
+ log(50.0)));
2014 void KCMKttsMgr::timeBox_valueChanged(int percentValue
) {
2015 timeSlider
->setValue (percentToSlider (percentValue
));
2018 void KCMKttsMgr::timeSlider_valueChanged(int sliderValue
) {
2019 timeBox
->setValue (sliderToPercent (sliderValue
));
2022 void KCMKttsMgr::slotConfigTalkerDlg_ConfigChanged()
2024 m_configDlg
->enableButtonOk(!m_loadedTalkerPlugIn
->getTalkerCode().isEmpty());
2027 void KCMKttsMgr::slotConfigFilterDlg_ConfigChanged()
2029 m_configDlg
->enableButtonOk( !m_loadedFilterPlugIn
->userPlugInName().isEmpty() );
2032 void KCMKttsMgr::slotConfigTalkerDlg_DefaultClicked()
2034 m_loadedTalkerPlugIn
->defaults();
2037 void KCMKttsMgr::slotConfigFilterDlg_DefaultClicked()
2039 m_loadedFilterPlugIn
->defaults();
2042 void KCMKttsMgr::slotConfigTalkerDlg_CancelClicked()
2044 delete m_loadedTalkerPlugIn
;
2045 m_loadedTalkerPlugIn
= 0;
2048 void KCMKttsMgr::slotConfigFilterDlg_CancelClicked()
2050 delete m_loadedFilterPlugIn
;
2051 m_loadedFilterPlugIn
= 0;
2055 * Uses KTrader to convert a translated Filter Plugin Name to DesktopEntryName.
2056 * @param name The translated plugin name. From Name= line in .desktop file.
2057 * @return DesktopEntryName. The name of the .desktop file (less .desktop).
2058 * QString() if not found.
2060 QString
KCMKttsMgr::FilterNameToDesktopEntryName(const QString
& name
)
2062 if (name
.isEmpty()) return QString();
2063 KService::List offers
= KServiceTypeTrader::self()->query("KTTSD/FilterPlugin");
2064 for (int ndx
= 0; ndx
< offers
.count(); ++ndx
)
2065 if (offers
[ndx
]->name() == name
) return offers
[ndx
]->desktopEntryName();
2070 * Uses KTrader to convert a DesktopEntryName into a translated Filter Plugin Name.
2071 * @param desktopEntryName The DesktopEntryName.
2072 * @return The translated Name of the plugin, from Name= line in .desktop file.
2074 QString
KCMKttsMgr::FilterDesktopEntryNameToName(const QString
& desktopEntryName
)
2076 if (desktopEntryName
.isEmpty()) return QString();
2077 KService::List offers
= KServiceTypeTrader::self()->query("KTTSD/FilterPlugin",
2078 QString("DesktopEntryName == '%1'").arg(desktopEntryName
));
2080 if (offers
.count() == 1)
2081 return offers
[0]->name();
2087 void KCMKttsMgr::slotFilterListView_clicked(const QModelIndex
& index
)
2089 if (!index
.isValid()) return;
2090 if (index
.column() != 0) return;
2091 if (index
.row() < 0 || index
.row() >= m_filterListModel
.rowCount()) return;
2092 FilterItem fi
= m_filterListModel
.getRow(index
.row());
2093 fi
.enabled
= !fi
.enabled
;
2094 m_filterListModel
.updateRow(index
.row(), fi
);