1 /***************************************************** vim:set ts=4 sw=4 sts=4:
2 A KPart to display running jobs in KTTSD and permit user to stop, rewind,
3 advance, change Talker, etc.
5 Copyright : (C) 2004,2005 by Gary Cramblitt <garycramblitt@comcast.net>
7 Current Maintainer: Gary Cramblitt <garycramblitt@comcast.net>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 ******************************************************************************/
29 #include <QPushButton>
36 #include <kinstance.h>
38 #include <kaboutdata.h>
41 #include <kencodingfiledialog.h>
42 #include <kapplication.h>
43 #include <kinputdialog.h>
44 #include <ktextedit.h>
46 #include <kdemacros.h>
47 #include <kparts/genericfactory.h>
51 #include "talkercode.h"
52 #include "selecttalkerdlg.h"
53 #include "jobinfolistmodel.h"
55 // KttsJobMgr includes.
56 #include "kttsjobmgr.h"
57 #include "kttsjobmgr.moc"
59 typedef KParts::GenericFactory
<KttsJobMgrPart
> KttsJobMgrPartFactory
;
60 K_EXPORT_COMPONENT_FACTORY( libkttsjobmgrpart
, KttsJobMgrPartFactory
)
62 KAboutData
* KttsJobMgrPart::createAboutData()
64 KAboutData
*about
= new KAboutData("kttsjobmgr", I18N_NOOP("KttsJobMgr"), "1.99");
68 KttsJobMgrPart::KttsJobMgrPart(QWidget
*parentWidget
, QObject
*parent
, const QStringList
& args
) :
69 KParts::ReadOnlyPart(parent
)
70 // m_kspeech(QDBus::sessionBus().findInterface<org::kde::KSpeech>("org.kde.kttsd", "/KSpeech"))
72 //DBusAbstractInterfacePrivate
74 m_kspeech
= new OrgKdeKSpeechInterface("org.kde.kttsd", "/KSpeech", QDBusConnection::sessionBus());
75 m_kspeech
->setParent(this);
77 // Establish ourself as a System Manager.
78 m_kspeech
->setApplicationName("KCMKttsMgr");
79 m_kspeech
->setIsSystemManager(true);
81 // Initialize some variables.
82 m_selectOnTextSet
= false;
85 // All the ktts components use the same catalog.
86 KGlobal::locale()->insertCatalog("kttsd");
88 // Create a QVBox to host everything.
89 KVBox
* vBox
= new KVBox(parentWidget
);
92 // Create a splitter to contain the Job List View and the current sentence.
93 QSplitter
* splitter
= new QSplitter(vBox
);
94 splitter
->setOrientation(Qt::Vertical
);
96 // Create Job List View widget and model.
97 m_jobListView
= new QTreeView( splitter
);
98 m_jobListModel
= new JobInfoListModel();
99 m_jobListView
->setModel(m_jobListModel
);
102 m_jobListView
->setSelectionMode(QAbstractItemView::SingleSelection
);
103 m_jobListView
->setSelectionBehavior(QAbstractItemView::SelectRows
);
106 m_jobListView
->setRootIsDecorated(false);
108 // TODO: Do not sort the list.
109 // m_jobListView->setSorting(-1);
111 QString jobListViewWT
= i18n(
112 "<p>These are all the text jobs. The <b>State</b> column "
115 "<li><b>Queued</b> - the job is waiting and will not be spoken until its state "
116 "is changed to <b>Waiting</b> by clicking the <b>Resume</b> or <b>Restart</b> buttons.</li>"
117 "<li><b>Waiting</b> - the job is ready to be spoken. It will be spoken when the jobs "
118 "preceding it in the list have finished.</li>"
119 "<li><b>Speaking</b> - the job is speaking. The <b>Position</b> column shows the current "
120 "sentence of the job being spoken. You may pause a speaking job by clicking the "
121 "<b>Hold</b> button.</li>"
122 "<li><b>Paused</b> - the job is currently paused. Paused jobs prevent jobs below them "
123 "from speaking. Use the <b>Resume</b> or <b>Restart</b> buttons to resume speaking the "
124 "job, or click <b>Later</b> to move the job down in the list.</li>"
125 "<li><b>Finished</b> - the job has finished speaking. When a second job finishes, "
126 "this one will be deleted. You may click <b>Restart</b> to repeat the job.</li>"
128 "<em>Note</em>: Messages, Warnings, and Screen Reader Output do not appear in this list. "
129 "See the Handbook for more information."
131 m_jobListView
->setWhatsThis( jobListViewWT
);
133 // splitter->setResizeMode(m_jobListView, QSplitter::Stretch);
135 // Create a VBox to hold buttons and current sentence.
136 KVBox
* bottomBox
= new KVBox(splitter
);
138 // Create a box to hold buttons.
139 m_buttonBox
= new KVBox(bottomBox
);
140 m_buttonBox
->setSpacing(6);
142 // Create 3 HBoxes to host buttons.
143 KHBox
* hbox1
= new KHBox(m_buttonBox
);
144 hbox1
->setSpacing(6);
145 KHBox
* hbox2
= new KHBox(m_buttonBox
);
146 hbox2
->setSpacing(6);
147 KHBox
* hbox3
= new KHBox(m_buttonBox
);
148 hbox3
->setSpacing(6);
150 // Do not let button box stretch vertically.
151 m_buttonBox
->setSizePolicy(QSizePolicy(QSizePolicy::Expanding
, QSizePolicy::Fixed
));
153 // All the buttons with "job_" at start of their names will be enabled/disabled when a job is
154 // selected in the Job List View.
158 btn
= new QPushButton(KIcon("stop"), i18n("Hold"), hbox1
);
159 btn
->setObjectName("job_hold");
161 "<p>Changes a job to Paused state. If currently speaking, the job stops speaking. "
162 "Paused jobs prevent jobs that follow them from speaking, so either click "
163 "<b>Resume</b> to make the job speakable, or click <b>Later</b> to move it "
164 "down in the list.</p>");
165 btn
->setWhatsThis(wt
);
166 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_job_hold()));
167 btn
= new QPushButton(KIcon("exec"), i18n("Resume"), hbox1
);
168 btn
->setObjectName("job_resume");
170 "<p>Resumes a paused job or changes a Queued job to Waiting. If the job is the "
171 "top speakable job in the list, it begins speaking.</p>");
172 btn
->setWhatsThis(wt
);
173 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_job_resume()));
174 btn
= new QPushButton(KIcon("redo"), i18n("R&estart"), hbox1
);
175 btn
->setObjectName("job_restart");
177 "<p>Rewinds a job to the beginning and changes its state to Waiting. If the job "
178 "is the top speakable job in the list, it begins speaking.</p>");
179 btn
->setWhatsThis(wt
);
180 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_job_restart()));
181 btn
= new QPushButton(KIcon("edittrash"), i18n("Re&move"), hbox1
);
182 btn
->setObjectName("job_remove");
184 "<p>Deletes the job. If it is currently speaking, it stops speaking. The next "
185 "speakable job in the list begins speaking.</p>");
186 btn
->setWhatsThis(wt
);
187 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_job_remove()));
188 btn
= new QPushButton(KIcon("down"), i18n("&Later"), hbox1
);
189 btn
->setObjectName("job_later");
191 "<p>Moves a job downward in the list so that it will be spoken later. If the job "
192 "is currently speaking, its state changes to Paused.</p>");
193 btn
->setWhatsThis(wt
);
194 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_job_move()));
196 btn
= new QPushButton(KIcon("1leftarrow"), i18n("&Previous Sentence"), hbox2
);
197 btn
->setObjectName("job_prevsentence");
199 "<p>Rewinds a job to the previous sentence.</p>");
200 btn
->setWhatsThis(wt
);
201 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_job_prev_sen()));
202 btn
= new QPushButton(KIcon("1rightarrow"), i18n("&Next Sentence"), hbox2
);
203 btn
->setObjectName("job_nextsentence");
205 "<p>Advances a job to the next sentence.</p>");
206 btn
->setWhatsThis(wt
);
207 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_job_next_sen()));
209 btn
= new QPushButton(KIcon("klipper"), i18n("&Speak Clipboard"), hbox3
);
210 btn
->setObjectName("speak_clipboard");
212 "<p>Queues the current contents of the clipboard for speaking and sets its state "
213 "to Waiting. If the job is the topmost in the list, it begins speaking. "
214 "The job will be spoken by the topmost Talker in the <b>Talkers</b> tab.</p>");
215 btn
->setWhatsThis(wt
);
216 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_speak_clipboard()));
217 btn
= new QPushButton(KIcon("fileopen"), i18n("Spea&k File"), hbox3
);
218 btn
->setObjectName("speak_file");
220 "<p>Prompts you for a file name and queues the contents of the file for speaking. "
221 "You must click the <b>Resume</b> button before the job will be speakable. "
222 "The job will be spoken by the topmost Talker in the <b>Talkers</b> tab.</p>");
223 btn
->setWhatsThis(wt
);
224 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_speak_file()));
225 btn
= new QPushButton(KIcon("translate"), i18n("Change Talker"), hbox3
);
226 btn
->setObjectName("job_changetalker");
228 "<p>Prompts you with a list of your configured Talkers from the <b>Talkers</b> tab. "
229 "The job will be spoken using the selected Talker.</p>");
230 btn
->setWhatsThis(wt
);
231 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_job_change_talker()));
232 btn
= new QPushButton(KIcon("reload_page"), i18n("&Refresh"), hbox3
);
233 btn
->setObjectName("refresh");
235 "<p>Refresh the list of jobs.</p>");
236 btn
->setWhatsThis(wt
);
237 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_refresh()));
239 // Disable job buttons until a job is selected.
240 enableJobActions(false);
242 // Create a VBox for the current sentence and sentence label.
243 KVBox
* sentenceVBox
= new KVBox(bottomBox
);
245 // Create a label for current sentence.
246 QLabel
* currentSentenceLabel
= new QLabel(sentenceVBox
);
247 currentSentenceLabel
->setSizePolicy(QSizePolicy(QSizePolicy::Preferred
, QSizePolicy::Fixed
));
248 currentSentenceLabel
->setText(i18n("Current Sentence"));
250 // Create a box to contain the current sentence.
251 m_currentSentence
= new KTextEdit(sentenceVBox
);
252 m_currentSentence
->setReadOnly(true);
253 m_currentSentence
->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere
);
254 m_currentSentence
->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
255 m_currentSentence
->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded
);
257 "<p>The text of the sentence currently speaking.</p>");
258 m_currentSentence
->setWhatsThis(wt
);
260 // Set the main widget for the part.
263 connect(m_jobListView
, SIGNAL(clicked(const QModelIndex
&)),
264 this, SLOT(slot_jobListView_clicked()));
266 // Fill the Job List.
269 // Select first item (if any).
270 autoSelectInJobListView();
272 // Connect DBUS Signals emitted by KTTSD to our own slots.
273 connect(m_kspeech
, SIGNAL(kttsdStarted()),
274 this, SLOT(kttsdStarted()));
275 connect(m_kspeech
, SIGNAL(jobStateChanged(const QString
&, int, int)),
276 this, SLOT(jobStateChanged(const QString
&, int, int)));
277 connect(m_kspeech
, SIGNAL(marker(const QString
&, int, int, const QString
&)),
278 this, SLOT(marker(const QString
&, int, int, const QString
&)));
280 m_extension
= new KttsJobMgrBrowserExtension(this);
282 // Divide splitter in half. ListView gets half. Buttons and Current Sentence get half.
283 int halfSplitterSize
= splitter
->height()/2;
284 QList
<int> splitterSizes
;
285 splitterSizes
.append(halfSplitterSize
);
286 splitterSizes
.append(halfSplitterSize
);
287 splitter
->setSizes(splitterSizes
);
290 KttsJobMgrPart::~KttsJobMgrPart()
292 KGlobal::locale()->removeCatalog("kttsd");
294 delete m_jobListModel
;
297 bool KttsJobMgrPart::openFile()
302 bool KttsJobMgrPart::closeUrl()
308 * This slot is connected to the Job List View clicked signal.
310 void KttsJobMgrPart::slot_jobListView_clicked()
312 // Enable job buttons.
313 enableJobActions(true);
317 * Slots connected to buttons.
319 void KttsJobMgrPart::slot_job_hold()
324 void KttsJobMgrPart::slot_job_resume()
329 void KttsJobMgrPart::slot_job_restart()
331 int jobNum
= getCurrentJobNum();
332 // kDebug() << "KttsJobMgrPart::slot_job_restart: jobNum = " << jobNum << endl;
335 int seq
= m_kspeech
->moveRelSentence(jobNum
, 0);
336 m_kspeech
->moveRelSentence(jobNum
, -seq
);
341 void KttsJobMgrPart::slot_job_prev_sen()
343 int jobNum
= getCurrentJobNum();
346 m_kspeech
->moveRelSentence(jobNum
, -1);
351 void KttsJobMgrPart::slot_job_next_sen()
353 int jobNum
= getCurrentJobNum();
356 m_kspeech
->moveRelSentence(jobNum
, 1);
361 void KttsJobMgrPart::slot_job_remove()
363 int jobNum
= getCurrentJobNum();
366 m_kspeech
->removeJob(jobNum
);
367 m_currentSentence
->clear();
371 void KttsJobMgrPart::slot_job_move()
373 int jobNum
= getCurrentJobNum();
376 m_kspeech
->moveJobLater(jobNum
);
378 // Select the job we just moved.
379 QModelIndex index
= m_jobListModel
->jobNumToIndex(jobNum
);
382 m_jobListView
->setCurrentIndex(index
);
383 slot_jobListView_clicked();
388 void KttsJobMgrPart::slot_job_change_talker()
390 QModelIndex index
= m_jobListView
->currentIndex();
393 JobInfo job
= m_jobListModel
->getRow(index
.row());
394 QString talkerID
= job
.talkerID
;
395 QStringList talkerIDs
= m_talkerCodesToTalkerIDs
.values();
396 int ndx
= talkerIDs
.indexOf(talkerID
);
398 if (ndx
>= 0) talkerCode
= m_talkerCodesToTalkerIDs
.keys()[ndx
];
399 SelectTalkerDlg
dlg(widget(), "selecttalkerdialog", i18n("Select Talker"), talkerCode
, true);
400 int dlgResult
= dlg
.exec();
401 if (dlgResult
!= KDialog::Accepted
) return;
402 talkerCode
= dlg
.getSelectedTalkerCode();
403 int jobNum
= job
.jobNum
;
404 m_kspeech
->changeJobTalker(jobNum
, talkerCode
);
409 void KttsJobMgrPart::slot_speak_clipboard()
411 // kDebug() << "KttsJobMgrPart::slot_speak_clipboard: running" << endl;
413 // Get the clipboard object.
414 QClipboard
*cb
= kapp
->clipboard();
416 // Copy text from the clipboard.
418 KSpeech::SayOptions sayOptions
= KSpeech::soNone
;
419 const QMimeData
* data
= cb
->mimeData();
422 if (data
->hasFormat("text/html"))
424 // if (m_kspeech->supportsMarkup(NULL, KSpeech::mtHtml))
426 sayOptions
= KSpeech::soHtml
;
428 if (data
->hasFormat("text/ssml"))
430 // if (m_kspeech->supportsMarkup(NULL, KSpeech::mtSsml))
432 QByteArray d
= data
->data("text/ssml");
434 sayOptions
= KSpeech::soSsml
;
438 if (text
.isEmpty()) {
440 sayOptions
= KSpeech::soPlainText
;
444 if ( !text
.isEmpty() )
446 m_kspeech
->say(text
, sayOptions
);
447 // int jobNum = m_kspeech->say(text, sayOptions);
448 // kDebug() << "KttsJobMgrPart::slot_speak_clipboard: started jobNum " << jobNum << endl;
449 // Set flag so that the job we just created will be selected when textSet signal is received.
450 m_selectOnTextSet
= true;
454 void KttsJobMgrPart::slot_speak_file()
456 KEncodingFileDialog dlg
;
457 KEncodingFileDialog::Result result
= dlg
.getOpenFileNameAndEncoding();
458 if (result
.fileNames
.count() == 1)
460 // kDebug() << "KttsJobMgr::slot_speak_file: calling setFile with filename " <<
461 // result.fileNames[0] << " and encoding " << result.encoding << endl;
462 m_kspeech
->sayFile(result
.fileNames
[0], result
.encoding
);
466 void KttsJobMgrPart::slot_refresh()
468 // Clear TalkerID cache.
469 m_talkerCodesToTalkerIDs
.clear();
470 // Get current job number.
471 int jobNum
= getCurrentJobNum();
473 // Select the previously-selected job.
476 QModelIndex index
= m_jobListModel
->jobNumToIndex(jobNum
);
479 m_jobListView
->setCurrentIndex(index
);
480 slot_jobListView_clicked();
487 * Get the Job Number of the currently-selected job in the Job List View.
488 * @return Job Number of currently-selected job.
489 * 0 if no currently-selected job.
491 int KttsJobMgrPart::getCurrentJobNum()
494 QModelIndex index
= m_jobListView
->currentIndex();
496 jobNum
= m_jobListModel
->getRow(index
.row()).jobNum
;
501 * Retrieves JobInfo from KTTSD, creates and fills JobInfo object.
502 * @param jobNum Job Number.
504 JobInfo
* KttsJobMgrPart::retrieveJobInfo(int jobNum
)
506 QByteArray jobInfo
= m_kspeech
->getJobInfo(jobNum
);
507 if (jobInfo
!= QByteArray()) {
508 JobInfo
* job
= new JobInfo();
509 QDataStream
stream(&jobInfo
, QIODevice::ReadOnly
);
514 qint32 sentenceCount
;
517 stream
>> job
->appId
;
518 stream
>> talkerCode
;
519 stream
>> sentenceNum
;
520 stream
>> sentenceCount
;
521 stream
>> job
->applicationName
;
522 job
->jobNum
= jobNum
;
523 job
->priority
= priority
;
525 job
->sentenceNum
= sentenceNum
;
526 job
->sentenceCount
= sentenceCount
;
527 job
->talkerID
= cachedTalkerCodeToTalkerID(talkerCode
);
534 * Refresh display of a single job in the JobListView.
535 * @param jobNum Job Number.
537 void KttsJobMgrPart::refreshJob(int jobNum
)
539 QModelIndex index
= m_jobListModel
->jobNumToIndex(jobNum
);
540 if (index
.isValid()) {
541 JobInfo
* job
= retrieveJobInfo(jobNum
);
543 m_jobListModel
->updateRow(index
.row(), *job
);
545 m_jobListModel
->removeRow(index
.row());
550 * Fill the Job List View.
552 void KttsJobMgrPart::refreshJobList()
554 // kDebug() << "KttsJobMgrPart::refreshJobList: Running" << endl;
555 m_jobListModel
->clear();
556 JobInfoList jobInfoList
;
557 enableJobActions(false);
558 QStringList jobNums
= m_kspeech
->getJobNumbers(KSpeech::jpAll
);
559 for (int ndx
= 0; ndx
< jobNums
.count(); ++ndx
)
561 QString jobNumStr
= jobNums
[ndx
];
562 kDebug() << "jobNumStr = " << jobNumStr
<< endl
;
563 int jobNum
= jobNumStr
.toInt(0, 10);
564 kDebug() << "jobNum = " << jobNum
<< endl
;
565 JobInfo
* job
= retrieveJobInfo(jobNum
);
567 jobInfoList
.append(*job
);
569 m_jobListModel
->setDatastore(jobInfoList
);
573 * If nothing selected in Job List View and list not empty, select top item.
574 * If nothing selected and list is empty, disable job buttons.
576 void KttsJobMgrPart::autoSelectInJobListView()
578 // If something selected, nothing to do.
579 if (m_jobListView
->currentIndex().isValid()) return;
580 // If empty, disable job buttons.
582 if (m_jobListModel
->rowCount() == 0)
583 enableJobActions(false);
586 // Select first item.
587 m_jobListView
->setCurrentIndex(m_jobListModel
->index(0, 0));
588 slot_jobListView_clicked();
593 * Return the Talker ID corresponding to a Talker Code, retrieving from cached list if present.
594 * @param talkerCode Talker Code.
597 QString
KttsJobMgrPart::cachedTalkerCodeToTalkerID(const QString
& talkerCode
)
599 // If in the cache, return that.
600 if (m_talkerCodesToTalkerIDs
.contains(talkerCode
))
601 return m_talkerCodesToTalkerIDs
[talkerCode
];
604 // Otherwise, retrieve Talker ID from KTTSD and cache it.
605 QString talkerID
= m_kspeech
->talkerToTalkerId(talkerCode
);
606 m_talkerCodesToTalkerIDs
[talkerCode
] = talkerID
;
607 // kdDebug() << "KttsJobMgrPart::cachedTalkerCodeToTalkerID: talkerCode = " << talkerCode << " talkerID = " << talkerID << endl;
613 * Enables or disables all the job-related buttons.
614 * @param enable True to enable the job-related butons. False to disable.
616 void KttsJobMgrPart::enableJobActions(bool enable
)
618 if (!m_buttonBox
) return;
620 #if defined Q_CC_MSVC && _MSC_VER < 1300
621 QList
<QPushButton
*> l
= qfindChildren
<QPushButton
*>( m_buttonBox
, QRegExp("job_*") );
623 QList
<QPushButton
*> l
= m_buttonBox
->findChildren
<QPushButton
*>( QRegExp("job_*") );
625 QListIterator
<QPushButton
*> i(l
);
628 (i
.next())->setEnabled( enable
);
632 // Later button only enables if currently selected list item is not bottom of list.
633 QModelIndex index
= m_jobListView
->currentIndex();
636 bool enableLater
= (index
.row() < m_jobListModel
->rowCount());
638 #if defined Q_CC_MSVC && _MSC_VER < 1300
639 l
= qfindChildren
<QPushButton
*>( m_buttonBox
, "job_later" );
641 l
= m_buttonBox
->findChildren
<QPushButton
*>( "job_later" );
643 QListIterator
<QPushButton
*> it(l
); // iterate over the buttons
645 // for each found object...
646 (it
.next())->setEnabled( enableLater
);
651 /** Slots connected to DBUS Signals emitted by KTTSD. */
654 * This signal is emitted when KTTSD starts or restarts after a call to reinit.
656 Q_SCRIPTABLE
void KttsJobMgrPart::kttsdStarted() { slot_refresh(); }
660 * This signal is emitted each time the state of a job changes.
661 * @param appId The DBUS sender ID of the application that
663 * @param jobNum Job Number.
664 * @param state Job state. @see KSpeech::JobState.
666 Q_SCRIPTABLE
void KttsJobMgrPart::jobStateChanged(const QString
&appId
, int jobNum
, int state
)
671 case KSpeech::jsQueued
:
673 QModelIndex index
= m_jobListModel
->jobNumToIndex(jobNum
);
678 JobInfo
* job
= retrieveJobInfo(jobNum
);
680 m_jobListModel
->appendRow(*job
);
681 // Should we select this job?
682 if (m_selectOnTextSet
)
684 m_jobListView
->setCurrentIndex(m_jobListModel
->jobNumToIndex(jobNum
));
685 m_selectOnTextSet
= false;
686 slot_jobListView_clicked();
690 // If a job not already selected, select this one.
691 autoSelectInJobListView();
694 case KSpeech::jsSpeakable
:
696 QModelIndex index
= m_jobListModel
->jobNumToIndex(jobNum
);
697 if (index
.isValid()) {
698 JobInfo
* job
= retrieveJobInfo(jobNum
);
700 m_jobListModel
->updateRow(index
.row(), *job
);
702 m_jobListModel
->removeRow(index
.row());
706 case KSpeech::jsFiltering
:
707 case KSpeech::jsSpeaking
:
708 case KSpeech::jsPaused
:
709 case KSpeech::jsInterrupted
:
710 case KSpeech::jsFinished
:
712 QModelIndex index
= m_jobListModel
->jobNumToIndex(jobNum
);
715 JobInfo job
= m_jobListModel
->getRow(index
.row());
717 m_jobListModel
->updateRow(index
.row(), job
);
719 m_currentSentence
->setPlainText(QString());
722 case KSpeech::jsDeleted
:
724 QModelIndex index
= m_jobListModel
->jobNumToIndex(jobNum
);
726 m_jobListModel
->removeRow(index
.row());
727 autoSelectInJobListView();
734 * This signal is emitted when a marker is processed.
735 * Currently only emits mtSentenceBegin and mtSentenceEnd.
736 * @param appId The DBUS sender ID of the application that submitted the job.
737 * @param jobNum Job Number of the job emitting the marker.
738 * @param markerType The type of marker.
739 * Currently either mtSentenceBegin or mtSentenceEnd.
740 * @param markerData Data for the marker.
741 * Currently, this is the sequence number of the sentence
742 * begun or ended. Sequence numbers begin at 1.
744 Q_SCRIPTABLE
void KttsJobMgrPart::marker(const QString
&appId
, int jobNum
, int markerType
, const QString
&markerData
)
747 if (KSpeech::mtSentenceBegin
== markerType
) {
748 QModelIndex index
= m_jobListModel
->jobNumToIndex(jobNum
);
751 JobInfo job
= m_jobListModel
->getRow(index
.row());
752 int seq
= markerData
.toInt();
753 job
.sentenceNum
= seq
;
754 m_jobListModel
->updateRow(index
.row(), job
);
755 m_currentSentence
->setPlainText(m_kspeech
->getJobSentence(jobNum
, seq
));
758 if (KSpeech::mtSentenceEnd
== markerType
) {
759 m_currentSentence
->setPlainText(QString());
764 KttsJobMgrBrowserExtension::KttsJobMgrBrowserExtension(KttsJobMgrPart
*parent
)
765 : KParts::BrowserExtension(parent
)
769 KttsJobMgrBrowserExtension::~KttsJobMgrBrowserExtension()