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>
8 ******************************************************************************/
10 /***************************************************************************
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; version 2 of the License. *
16 ***************************************************************************/
22 #include <qsplitter.h>
23 #include <qclipboard.h>
24 #include <qpushbutton.h>
32 #include <kinstance.h>
34 #include <kaboutdata.h>
35 #include <klistview.h>
36 #include <kiconloader.h>
38 #include <kencodingfiledialog.h>
39 #include <kapplication.h>
40 #include <kinputdialog.h>
41 #include <ktextedit.h>
46 #include "talkercode.h"
47 #include "selecttalkerdlg.h"
48 #include "kttsjobmgr.h"
49 #include "kttsjobmgr.moc"
54 * This function is the 'main' function of this part. It takes
55 * the form 'void *init_lib<library name>() It always returns a
58 KDE_EXPORT
void *init_libkttsjobmgrpart()
60 return new KttsJobMgrFactory
;
65 * We need one static instance of the factory for our C 'main'
68 KInstance
*KttsJobMgrFactory::s_instance
= 0L;
70 KttsJobMgrFactory::~KttsJobMgrFactory()
74 delete s_instance
->aboutData();
81 QObject
*KttsJobMgrFactory::createObject(QObject
*parent
, const char *name
, const char*,
84 QObject
*obj
= new KttsJobMgrPart((QWidget
*)parent
, name
);
85 emit
objectCreated(obj
);
89 KInstance
*KttsJobMgrFactory::instance()
92 s_instance
= new KInstance( aboutData() );
96 KAboutData
*KttsJobMgrFactory::aboutData()
98 KAboutData
*about
= new KAboutData("kttsjobmgr", I18N_NOOP("KttsJobMgr"), "1.99");
102 KttsJobMgrPart::KttsJobMgrPart(QWidget
*parent
, const char *name
) :
103 DCOPStub("kttsd", "KSpeech"),
104 DCOPObject("kttsjobmgr_kspeechsink"),
105 KParts::ReadOnlyPart(parent
)
108 // Initialize some variables.
109 m_selectOnTextSet
= false;
112 setInstance(KttsJobMgrFactory::instance());
114 // All the ktts components use the same catalogue.
115 KGlobal::locale()->insertCatalog("kttsd");
117 // Create a QVBox to host everything.
118 KVBox
* vBox
= new KVBox(parent
);
119 //vBox->setMargin(6);
121 // Create a splitter to contain the Job List View and the current sentence.
122 QSplitter
* splitter
= new QSplitter(vBox
);
123 splitter
->setOrientation(Qt::Vertical
);
125 // Create Job List View widget.
126 m_jobListView
= new KListView( splitter
);
127 m_jobListView
->setObjectName( "joblistview" );
128 m_jobListView
->setSelectionModeExt(KListView::Single
);
129 m_jobListView
->addColumn(i18n("Job Num"));
130 m_jobListView
->addColumn(i18n("Owner"));
131 m_jobListView
->addColumn(i18n("Talker ID"));
132 m_jobListView
->addColumn(i18n("State"));
133 m_jobListView
->addColumn(i18n("Position"));
134 m_jobListView
->addColumn(i18n("Sentences"));
135 m_jobListView
->addColumn(i18n("Part Num"));
136 m_jobListView
->addColumn(i18n("Parts"));
138 // Do not sort the list.
139 m_jobListView
->setSorting(-1);
141 QString jobListViewWT
= i18n(
142 "<p>These are all the text jobs. The <b>State</b> column "
145 "<li><b>Queued</b> - the job is waiting and will not be spoken until its state "
146 "is changed to <b>Waiting</b> by clicking the <b>Resume</b> or <b>Restart</b> buttons.</li>"
147 "<li><b>Waiting</b> - the job is ready to be spoken. It will be spoken when the jobs "
148 "preceding it in the list have finished.</li>"
149 "<li><b>Speaking</b> - the job is speaking. The <b>Position</b> column shows the current "
150 "sentence of the job being spoken. You may pause a speaking job by clicking the "
151 "<b>Hold</b> button.</li>"
152 "<li><b>Paused</b> - the job is currently paused. Paused jobs prevent jobs below them "
153 "from speaking. Use the <b>Resume</b> or <b>Restart</b> buttons to resume speaking the "
154 "job, or click <b>Later</b> to move the job down in the list.</li>"
155 "<li><b>Finished</b> - the job has finished speaking. When a second job finishes, "
156 "this one will be deleted. You may click <b>Restart</b> to repeat the job.</li>"
158 "<em>Note</em>: Messages, Warnings, and Screen Reader Output do not appear in this list. "
159 "See the Handbook for more information."
161 m_jobListView
->setWhatsThis( jobListViewWT
);
163 // splitter->setResizeMode(m_jobListView, QSplitter::Stretch);
165 // Create a VBox to hold buttons and current sentence.
166 KVBox
* bottomBox
= new KVBox(splitter
);
168 // Create a box to hold buttons.
169 m_buttonBox
= new KVBox(bottomBox
);
170 m_buttonBox
->setSpacing(6);
172 // Create 3 HBoxes to host buttons.
173 KHBox
* hbox1
= new KHBox(m_buttonBox
);
174 hbox1
->setSpacing(6);
175 KHBox
* hbox2
= new KHBox(m_buttonBox
);
176 hbox2
->setSpacing(6);
177 KHBox
* hbox3
= new KHBox(m_buttonBox
);
178 hbox3
->setSpacing(6);
180 // Do not let button box stretch vertically.
181 m_buttonBox
->setSizePolicy(QSizePolicy(QSizePolicy::Expanding
, QSizePolicy::Fixed
));
183 // All the buttons with "job_" at start of their names will be enabled/disabled when a job is
184 // selected in the Job List View.
185 // All the buttons with "part_" at the start of their names will be enabled/disabled when a
186 // job is selected in the Job List View that has multiple parts.
190 btn
= new QPushButton(KGlobal::iconLoader()->loadIconSet("stop", KIcon::Small
, 0, true),
191 i18n("Hold"), hbox1
, "job_hold");
193 "<p>Changes a job to Paused state. If currently speaking, the job stops speaking. "
194 "Paused jobs prevent jobs that follow them from speaking, so either click "
195 "<b>Resume</b> to make the job speakable, or click <b>Later</b> to move it "
196 "down in the list.</p>");
197 btn
->setWhatsThis( wt
);
198 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_job_hold()));
199 btn
= new QPushButton(KGlobal::iconLoader()->loadIconSet("exec", KIcon::Small
, 0, true),
200 i18n("Resume"), hbox1
, "job_resume");
202 "<p>Resumes a paused job or changes a Queued job to Waiting. If the job is the "
203 "top speakable job in the list, it begins speaking.</p>");
204 btn
->setWhatsThis( wt
);
205 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_job_resume()));
206 btn
= new QPushButton(KGlobal::iconLoader()->loadIconSet("redo", KIcon::Small
, 0, true),
207 i18n("R&estart"), hbox1
, "job_restart");
209 "<p>Rewinds a job to the beginning and changes its state to Waiting. If the job "
210 "is the top speakable job in the list, it begins speaking.</p>");
211 btn
->setWhatsThis( wt
);
212 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_job_restart()));
213 btn
= new QPushButton(KGlobal::iconLoader()->loadIconSet("edittrash", KIcon::Small
, 0, true),
214 i18n("Re&move"), hbox1
, "job_remove");
216 "<p>Deletes the job. If it is currently speaking, it stops speaking. The next "
217 "speakable job in the list begins speaking.</p>");
218 btn
->setWhatsThis( wt
);
219 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_job_remove()));
220 btn
= new QPushButton(KGlobal::iconLoader()->loadIconSet("down", KIcon::Small
, 0, true),
221 i18n("&Later"), hbox1
, "job_later");
223 "<p>Moves a job downward in the list so that it will be spoken later. If the job "
224 "is currently speaking, its state changes to Paused.</p>");
225 btn
->setWhatsThis( wt
);
226 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_job_move()));
228 btn
= new QPushButton(KGlobal::iconLoader()->loadIconSet("2leftarrow", KIcon::Small
, 0, true),
229 i18n("Pre&vious Part"), hbox2
, "part_prevpart");
231 "<p>Rewinds a multi-part job to the previous part.</p>");
232 btn
->setWhatsThis( wt
);
233 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_job_prev_par()));
234 btn
= new QPushButton(KGlobal::iconLoader()->loadIconSet("1leftarrow", KIcon::Small
, 0, true),
235 i18n("&Previous Sentence"), hbox2
, "job_prevsentence");
237 "<p>Rewinds a job to the previous sentence.</p>");
238 btn
->setWhatsThis( wt
);
239 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_job_prev_sen()));
240 btn
= new QPushButton(KGlobal::iconLoader()->loadIconSet("1rightarrow", KIcon::Small
, 0, true),
241 i18n("&Next Sentence"), hbox2
, "job_nextsentence");
243 "<p>Advances a job to the next sentence.</p>");
244 btn
->setWhatsThis( wt
);
245 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_job_next_sen()));
246 btn
= new QPushButton(KGlobal::iconLoader()->loadIconSet("2rightarrow", KIcon::Small
, 0, true),
247 i18n("Ne&xt Part"), hbox2
, "part_nextpart");
249 "<p>Advances a multi-part job to the next part.</p>");
250 btn
->setWhatsThis( wt
);
251 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_job_next_par()));
253 btn
= new QPushButton(KGlobal::iconLoader()->loadIconSet("klipper", KIcon::Small
, 0, true),
254 i18n("&Speak Clipboard"), hbox3
, "speak_clipboard");
256 "<p>Queues the current contents of the clipboard for speaking and sets its state "
257 "to Waiting. If the job is the topmost in the list, it begins speaking. "
258 "The job will be spoken by the topmost Talker in the <b>Talkers</b> tab.</p>");
259 btn
->setWhatsThis( wt
);
260 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_speak_clipboard()));
261 btn
= new QPushButton(KGlobal::iconLoader()->loadIconSet("fileopen", KIcon::Small
, 0, true),
262 i18n("Spea&k File"), hbox3
, "speak_file");
264 "<p>Prompts you for a file name and queues the contents of the file for speaking. "
265 "You must click the <b>Resume</b> button before the job will be speakable. "
266 "The job will be spoken by the topmost Talker in the <b>Talkers</b> tab.</p>");
267 btn
->setWhatsThis( wt
);
268 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_speak_file()));
269 btn
= new QPushButton(KGlobal::iconLoader()->loadIconSet("translate", KIcon::Small
, 0, true),
270 i18n("Change Talker"), hbox3
, "job_changetalker");
272 "<p>Prompts you with a list of your configured Talkers from the <b>Talkers</b> tab. "
273 "The job will be spoken using the selected Talker.</p>");
274 btn
->setWhatsThis( wt
);
275 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_job_change_talker()));
276 btn
= new QPushButton(KGlobal::iconLoader()->loadIconSet("reload_page", KIcon::Small
, 0, true),
277 i18n("&Refresh"), hbox3
, "refresh");
279 "<p>Refresh the list of jobs.</p>");
280 btn
->setWhatsThis( wt
);
281 connect (btn
, SIGNAL(clicked()), this, SLOT(slot_refresh()));
283 // Disable job buttons until a job is selected.
284 enableJobActions(false);
285 enableJobPartActions(false);
287 // Create a VBox for the current sentence and sentence label.
288 KVBox
* sentenceVBox
= new KVBox(bottomBox
);
290 // Create a label for current sentence.
291 QLabel
* currentSentenceLabel
= new QLabel(sentenceVBox
);
292 currentSentenceLabel
->setSizePolicy(QSizePolicy(QSizePolicy::Preferred
, QSizePolicy::Fixed
));
293 currentSentenceLabel
->setText(i18n("Current Sentence"));
295 // Create a box to contain the current sentence.
296 m_currentSentence
= new KTextEdit(sentenceVBox
);
297 m_currentSentence
->setReadOnly(true);
298 #warning "kde4: port them"
299 //m_currentSentence->setWordWrap(Q3TextEdit::WidgetWidth);
300 //m_currentSentence->setWrapPolicy(Q3TextEdit::AtWordOrDocumentBoundary);
301 //m_currentSentence->setHScrollBarMode(Q3ScrollView::AlwaysOff);
302 //m_currentSentence->setVScrollBarMode(Q3ScrollView::Auto);
304 "<p>The text of the sentence currently speaking.</p>");
305 m_currentSentence
->setWhatsThis( wt
);
307 // Set the main widget for the part.
310 connect(m_jobListView
, SIGNAL(selectionChanged(Q3ListViewItem
* )),
311 this, SLOT(slot_selectionChanged(Q3ListViewItem
* )));
313 // Fill the Job List View.
314 refreshJobListView();
315 // Select first item (if any).
316 autoSelectInJobListView();
318 // Connect DCOP Signals emitted by KTTSD to our own DCOP methods.
319 connectDCOPSignal("kttsd", "KSpeech",
323 connectDCOPSignal("kttsd", "KSpeech",
324 "markerSeen(QByteArray,QString)",
325 "markerSeen(QByteArray,QString)",
327 if (!connectDCOPSignal("kttsd", "KSpeech",
328 "sentenceStarted(QByteArray,uint,uint)",
329 "sentenceStarted(QByteArray,uint,uint)",
330 false)) kdDebug() << "KttsJobMgrPart::KttsJobMgrPart: failed to connect DCOP signal sentenceStarted" << endl
;
331 connectDCOPSignal(0, 0,
332 "sentenceFinished(QByteArray,uint,uint)",
333 "sentenceFinished(QByteArray,uint,uint)",
335 connectDCOPSignal("kttsd", "KSpeech",
336 "textSet(QByteArray,uint)",
337 "textSet(QByteArray,uint)",
339 connectDCOPSignal("kttsd", "KSpeech",
340 "textStarted(QByteArray,uint)",
341 "textStarted(QByteArray,uint)",
343 connectDCOPSignal("kttsd", "KSpeech",
344 "textFinished(QByteArray,uint)",
345 "textFinished(QByteArray,uint)",
347 connectDCOPSignal("kttsd", "KSpeech",
348 "textStopped(QByteArray,uint)",
349 "textStopped(QByteArray,uint)",
351 connectDCOPSignal("kttsd", "KSpeech",
352 "textPaused(QByteArray,uint)",
353 "textPaused(QByteArray,uint)",
355 connectDCOPSignal("kttsd", "KSpeech",
356 "textResumed(QByteArray,uint)",
357 "textResumed(QByteArray,uint)",
359 connectDCOPSignal("kttsd", "KSpeech",
360 "textRemoved(QByteArray,uint)",
361 "textRemoved(QByteArray,uint)",
364 m_extension
= new KttsJobMgrBrowserExtension(this);
366 m_jobListView
->show();
368 // Divide splitter in half. ListView gets half. Buttons and Current Sentence get half.
369 int halfSplitterSize
= splitter
->height()/2;
370 QList
<int> splitterSizes
;
371 splitterSizes
.append(halfSplitterSize
);
372 splitterSizes
.append(halfSplitterSize
);
373 splitter
->setSizes(splitterSizes
);
376 KttsJobMgrPart::~KttsJobMgrPart()
378 KGlobal::locale()->removeCatalog("kttsd");
382 bool KttsJobMgrPart::openFile()
387 bool KttsJobMgrPart::closeURL()
393 * This slot is connected to the Job List View selectionChanged signal.
395 void KttsJobMgrPart::slot_selectionChanged(Q3ListViewItem
*)
397 // Enable job buttons.
398 enableJobActions(true);
399 enableJobPartActions((getCurrentJobPartCount() > 1));
403 * Slots connected to buttons.
405 void KttsJobMgrPart::slot_job_hold()
407 uint jobNum
= getCurrentJobNum();
415 void KttsJobMgrPart::slot_job_resume()
417 uint jobNum
= getCurrentJobNum();
425 void KttsJobMgrPart::slot_job_restart()
427 uint jobNum
= getCurrentJobNum();
428 // kdDebug() << "KttsJobMgrPart::slot_job_restart: jobNum = " << jobNum << endl;
436 void KttsJobMgrPart::slot_job_prev_par()
438 uint jobNum
= getCurrentJobNum();
441 // Get current part number.
442 uint partNum
= jumpToTextPart(0, jobNum
);
443 if (partNum
> 1) jumpToTextPart(--partNum
, jobNum
);
448 void KttsJobMgrPart::slot_job_prev_sen()
450 uint jobNum
= getCurrentJobNum();
453 moveRelTextSentence(-1, jobNum
);
458 void KttsJobMgrPart::slot_job_next_sen()
460 uint jobNum
= getCurrentJobNum();
463 moveRelTextSentence(1, jobNum
);
468 void KttsJobMgrPart::slot_job_next_par()
470 uint jobNum
= getCurrentJobNum();
473 // Get current part number.
474 uint partNum
= jumpToTextPart(0, jobNum
);
475 jumpToTextPart(++partNum
, jobNum
);
480 void KttsJobMgrPart::slot_job_remove()
482 uint jobNum
= getCurrentJobNum();
486 m_currentSentence
->clear();
490 void KttsJobMgrPart::slot_job_move()
492 uint jobNum
= getCurrentJobNum();
495 moveTextLater(jobNum
);
496 refreshJobListView();
497 // Select the job we just moved.
498 Q3ListViewItem
* item
= findItemByJobNum(jobNum
);
499 if (item
) m_jobListView
->setSelected(item
, true);
503 void KttsJobMgrPart::slot_job_change_talker()
505 Q3ListViewItem
* item
= m_jobListView
->selectedItem();
508 QString talkerID
= item
->text(jlvcTalkerID
);
509 QStringList talkerIDs
= m_talkerCodesToTalkerIDs
.values();
510 int ndx
= talkerIDs
.findIndex(talkerID
);
512 if (ndx
>= 0) talkerCode
= m_talkerCodesToTalkerIDs
.keys()[ndx
];
513 SelectTalkerDlg
dlg(widget(), "selecttalkerdialog", i18n("Select Talker"), talkerCode
, true);
514 int dlgResult
= dlg
.exec();
515 if (dlgResult
!= KDialogBase::Accepted
) return;
516 talkerCode
= dlg
.getSelectedTalkerCode();
517 int jobNum
= item
->text(jlvcJobNum
).toInt();
518 changeTextTalker(talkerCode
, jobNum
);
523 void KttsJobMgrPart::slot_speak_clipboard()
525 // Get the clipboard object.
526 QClipboard
*cb
= kapp
->clipboard();
529 // Copy text from the clipboard.
531 QMimeSource
* data
= cb
->data();
534 if (data
->provides("text/html"))
536 if (supportsMarkup(NULL
, KSpeech::mtHtml
))
538 QByteArray d
= data
->encodedData("text/html");
542 if (data
->provides("text/ssml"))
544 if (supportsMarkup(NULL
, KSpeech::mtSsml
))
546 QByteArray d
= data
->encodedData("text/ssml");
555 if ( !text
.isEmpty() )
557 uint jobNum
= setText(text
, NULL
);
558 // kdDebug() << "KttsJobMgrPart::slot_speak_clipboard: started jobNum " << jobNum << endl;
560 // Set flag so that the job we just created will be selected when textSet signal is received.
561 m_selectOnTextSet
= true;
565 void KttsJobMgrPart::slot_speak_file()
567 KEncodingFileDialog dlg
;
568 KEncodingFileDialog::Result result
= dlg
.getOpenFileNameAndEncoding();
569 if (result
.fileNames
.count() == 1)
571 // kdDebug() << "KttsJobMgr::slot_speak_file: calling setFile with filename " <<
572 // result.fileNames[0] << " and encoding " << result.encoding << endl;
573 setFile(result
.fileNames
[0], NULL
, result
.encoding
);
577 void KttsJobMgrPart::slot_refresh()
579 // Clear TalkerID cache.
580 m_talkerCodesToTalkerIDs
.clear();
581 // Get current job number.
582 uint jobNum
= getCurrentJobNum();
583 refreshJobListView();
584 // Select the previously-selected job.
587 Q3ListViewItem
* item
= findItemByJobNum(jobNum
);
588 if (item
) m_jobListView
->setSelected(item
, true);
594 * Convert a KTTSD job state integer into a display string.
595 * @param state KTTSD job state
596 * @return Display string for the state.
598 QString
KttsJobMgrPart::stateToStr(int state
)
602 case KSpeech::jsQueued
: return i18n("Queued");
603 case KSpeech::jsSpeakable
: return i18n("Waiting");
604 case KSpeech::jsSpeaking
: return i18n("Speaking");
605 case KSpeech::jsPaused
: return i18n("Paused");
606 case KSpeech::jsFinished
: return i18n("Finished");
607 default: return i18n("Unknown");
612 * Get the Job Number of the currently-selected job in the Job List View.
613 * @return Job Number of currently-selected job.
614 * 0 if no currently-selected job.
616 uint
KttsJobMgrPart::getCurrentJobNum()
619 Q3ListViewItem
* item
= m_jobListView
->selectedItem();
622 QString jobNumStr
= item
->text(jlvcJobNum
);
623 jobNum
= jobNumStr
.toUInt(0, 10);
629 * Get the number of parts in the currently-selected job in the Job List View.
630 * @return Number of parts in currently-selected job.
631 * 0 if no currently-selected job.
633 int KttsJobMgrPart::getCurrentJobPartCount()
636 Q3ListViewItem
* item
= m_jobListView
->selectedItem();
639 QString partCountStr
= item
->text(jlvcPartCount
);
640 partCount
= partCountStr
.toUInt(0, 10);
646 * Given a Job Number, returns the Job List View item containing the job.
647 * @param jobNum Job Number.
648 * @return QListViewItem containing the job or 0 if not found.
650 Q3ListViewItem
* KttsJobMgrPart::findItemByJobNum(const uint jobNum
)
652 return m_jobListView
->findItem(QString::number(jobNum
), jlvcJobNum
);
656 * Refresh display of a single job in the JobListView.
657 * @param jobNum Job Number.
659 void KttsJobMgrPart::refreshJob(uint jobNum
)
661 QByteArray jobInfo
= getTextJobInfo(jobNum
);
662 QDataStream
stream(&jobInfo
, QIODevice::ReadOnly
);
674 stream
>> sentenceCount
;
677 QString talkerID
= cachedTalkerCodeToTalkerID(talker
);
678 Q3ListViewItem
* item
= findItemByJobNum(jobNum
);
681 item
->setText(jlvcTalkerID
, talkerID
);
682 item
->setText(jlvcState
, stateToStr(state
));
683 item
->setText(jlvcPosition
, QString::number(seq
));
684 item
->setText(jlvcSentences
, QString::number(sentenceCount
));
685 item
->setText(jlvcPartNum
, QString::number(partNum
));
686 item
->setText(jlvcPartCount
, QString::number(partCount
));
691 * Fill the Job List View.
693 void KttsJobMgrPart::refreshJobListView()
695 // kdDebug() << "KttsJobMgrPart::refreshJobListView: Running" << endl;
696 m_jobListView
->clear();
697 enableJobActions(false);
698 enableJobPartActions(false);
699 QString jobNumbers
= getTextJobNumbers();
700 // kdDebug() << "jobNumbers: " << jobNumbers << endl;
701 QStringList jobNums
= QStringList::split(",", jobNumbers
);
702 Q3ListViewItem
* lastItem
= 0;
703 QStringList::ConstIterator
endJobNums(jobNums
.constEnd());
704 for( QStringList::ConstIterator it
= jobNums
.constBegin(); it
!= endJobNums
; ++it
)
706 QString jobNumStr
= *it
;
707 // kdDebug() << "jobNumStr: " << jobNumStr << endl;
708 uint jobNum
= jobNumStr
.toUInt(0, 10);
709 QByteArray jobInfo
= getTextJobInfo(jobNum
);
710 QDataStream
stream(&jobInfo
, QIODevice::ReadOnly
);
720 stream
>> talkerCode
;
722 stream
>> sentenceCount
;
725 QString talkerID
= cachedTalkerCodeToTalkerID(talkerCode
);
728 lastItem
= new Q3ListViewItem(m_jobListView
, lastItem
, jobNumStr
, appId
, talkerID
,
729 stateToStr(state
), QString::number(seq
), QString::number(sentenceCount
),
730 QString::number(partNum
), QString::number(partCount
));
732 lastItem
= new Q3ListViewItem(m_jobListView
, jobNumStr
, appId
, talkerID
,
733 stateToStr(state
), QString::number(seq
), QString::number(sentenceCount
),
734 QString::number(partNum
), QString::number(partCount
));
739 * If nothing selected in Job List View and list not empty, select top item.
740 * If nothing selected and list is empty, disable job buttons.
742 void KttsJobMgrPart::autoSelectInJobListView()
744 // If something selected, nothing to do.
745 if (m_jobListView
->selectedItem()) return;
746 // If empty, disable job buttons.
747 Q3ListViewItem
* item
= m_jobListView
->firstChild();
750 enableJobActions(false);
751 enableJobPartActions(false);
754 // Select first item. Should fire itemSelected event which will enable job buttons.
755 m_jobListView
->setSelected(item
, true);
759 * Return the Talker ID corresponding to a Talker Code, retrieving from cached list if present.
760 * @param talkerCode Talker Code.
763 QString
KttsJobMgrPart::cachedTalkerCodeToTalkerID(const QString
& talkerCode
)
765 // If in the cache, return that.
766 if (m_talkerCodesToTalkerIDs
.contains(talkerCode
))
767 return m_talkerCodesToTalkerIDs
[talkerCode
];
770 // Otherwise, retrieve Talker ID from KTTSD and cache it.
771 QString talkerID
= talkerCodeToTalkerId(talkerCode
);
772 m_talkerCodesToTalkerIDs
[talkerCode
] = talkerID
;
778 * Enables or disables all the job-related buttons.
779 * @param enable True to enable the job-related butons. False to disable.
781 void KttsJobMgrPart::enableJobActions(bool enable
)
783 if (!m_buttonBox
) return;
785 QList
<QObject
*> l
= m_buttonBox
->queryList( "QPushButton", "job_*", true, true );
786 QListIterator
<QObject
*> i(l
);
789 ((QPushButton
*)i
.next())->setEnabled( enable
);
793 // Later button only enables if currently selected list item is not bottom of list.
794 Q3ListViewItem
* item
= m_jobListView
->selectedItem();
797 bool enableLater
= item
->nextSibling();
799 l
= m_buttonBox
->queryList( "QPushButton", "job_later", false, true );
800 QListIterator
<QObject
*> it(l
); // iterate over the buttons
802 // for each found object...
803 ((QPushButton
*)it
.next())->setEnabled( enableLater
);
809 * Enables or disables all the job part-related buttons.
810 * @param enable True to enable the job par-related butons. False to disable.
812 void KttsJobMgrPart::enableJobPartActions(bool enable
)
814 if (!m_buttonBox
) return;
815 QList
<QObject
*> l
= m_buttonBox
->queryList( "QPushButton", "part_*", true, true );
816 QListIterator
<QObject
*> i(l
);
819 ((QPushButton
*)i
.next())->setEnabled( enable
);
823 /** DCOP Methods connected to DCOP Signals emitted by KTTSD. */
826 * This signal is emitted when KTTSD starts or restarts after a call to reinit.
828 ASYNC
KttsJobMgrPart::kttsdStarted() { slot_refresh(); };
831 * This signal is emitted when the speech engine/plugin encounters a marker in the text.
832 * @param appId DCOP application ID of the application that queued the text.
833 * @param markerName The name of the marker seen.
836 ASYNC
KttsJobMgrPart::markerSeen(const QByteArray
&, const QString
&)
841 * This signal is emitted whenever a sentence begins speaking.
842 * @param appId DCOP application ID of the application that queued the text.
843 * @param jobNum Job number of the text job.
844 * @param seq Sequence number of the text.
847 ASYNC
KttsJobMgrPart::sentenceStarted(const QByteArray
&, const uint jobNum
, const uint seq
)
849 // kdDebug() << "KttsJobMgrPart::sentencedStarted: jobNum = " << jobNum << " seq = " << seq << endl;
850 Q3ListViewItem
* item
= findItemByJobNum(jobNum
);
853 item
->setText(jlvcState
, stateToStr(KSpeech::jsSpeaking
));
854 item
->setText(jlvcPosition
, QString::number(seq
));
855 m_currentSentence
->setText(getTextJobSentence(jobNum
, seq
));
860 * This signal is emitted when a sentence has finished speaking.
861 * @param appId DCOP application ID of the application that queued the text.
862 * @param jobNum Job number of the text job.
863 * @param seq Sequence number of the text.
866 ASYNC
KttsJobMgrPart::sentenceFinished(const QByteArray
& /*appId*/, const uint
/*jobNum*/, const uint
/*seq*/)
868 // kdDebug() << "KttsJobMgrPart::sentencedFinished: jobNum = " << jobNum << endl;
870 QListViewItem* item = findItemByJobNum(jobNum);
873 item->setText(jlvcState, stateToStr(KSpeech::jsSpeaking));
879 * This signal is emitted whenever a new text job is added to the queue.
880 * @param appId The DCOP senderId of the application that created the job.
881 * @param jobNum Job number of the text job.
883 ASYNC
KttsJobMgrPart::textSet(const QByteArray
&, const uint jobNum
)
885 QByteArray jobInfo
= getTextJobInfo(jobNum
);
886 QDataStream
stream(&jobInfo
, QIODevice::ReadOnly
);
896 stream
>> talkerCode
;
898 stream
>> sentenceCount
;
901 QString talkerID
= cachedTalkerCodeToTalkerID(talkerCode
);
902 Q3ListViewItem
* item
= new Q3ListViewItem(m_jobListView
, m_jobListView
->lastItem(),
903 QString::number(jobNum
), appId
, talkerID
,
904 stateToStr(state
), QString::number(seq
), QString::number(sentenceCount
),
905 QString::number(partNum
), QString::number(partCount
));
906 // Should we select this job?
907 if (m_selectOnTextSet
)
909 m_jobListView
->setSelected(item
, true);
910 m_selectOnTextSet
= false;
912 // If a job not already selected, select this one.
913 autoSelectInJobListView();
917 * This signal is emitted whenever a new part is appended to a text job.
918 * @param appId The DCOP senderId of the application that created the job.
919 * @param jobNum Job number of the text job.
920 * @param partNum Part number of the new part. Parts are numbered starting
923 ASYNC
KttsJobMgrPart::textAppended(const QByteArray
& appId
, const uint jobNum
, const int /*partNum*/)
925 textSet(appId
, jobNum
);
929 * This signal is emitted whenever speaking of a text job begins.
930 * @param appId The DCOP senderId of the application that created the job.
931 * @param jobNum Job number of the text job.
933 ASYNC
KttsJobMgrPart::textStarted(const QByteArray
&, const uint jobNum
)
935 Q3ListViewItem
* item
= findItemByJobNum(jobNum
);
938 item
->setText(jlvcState
, stateToStr(KSpeech::jsSpeaking
));
939 item
->setText(jlvcPosition
, "1");
944 * This signal is emitted whenever a text job is finished. The job has
945 * been marked for deletion from the queue and will be deleted when another
946 * job reaches the Finished state. (Only one job in the text queue may be
947 * in state Finished at one time.) If @ref startText or @ref resumeText is
948 * called before the job is deleted, it will remain in the queue for speaking.
949 * @param appId The DCOP senderId of the application that created the job.
950 * @param jobNum Job number of the text job.
952 ASYNC
KttsJobMgrPart::textFinished(const QByteArray
&, const uint jobNum
)
954 // kdDebug() << "KttsJobMgrPart::textFinished: jobNum = " << jobNum << endl;
955 Q3ListViewItem
* item
= findItemByJobNum(jobNum
);
958 item
->setText(jlvcState
, stateToStr(KSpeech::jsFinished
));
959 // Update sentence pointer, since signal may not be emitted for final CR.
962 m_currentSentence
->setText(QString::null
);
966 * This signal is emitted whenever a speaking text job stops speaking.
967 * @param appId The DCOP senderId of the application that created the job.
968 * @param jobNum Job number of the text job.
970 ASYNC
KttsJobMgrPart::textStopped(const QByteArray
&, const uint jobNum
)
972 // kdDebug() << "KttsJobMgrPart::textStopped: jobNum = " << jobNum << endl;
973 Q3ListViewItem
* item
= findItemByJobNum(jobNum
);
976 item
->setText(jlvcState
, stateToStr(KSpeech::jsQueued
));
977 item
->setText(jlvcPosition
, "1");
982 * This signal is emitted whenever a speaking text job is paused.
983 * @param appId The DCOP senderId of the application that created the job.
984 * @param jobNum Job number of the text job.
986 ASYNC
KttsJobMgrPart::textPaused(const QByteArray
&, const uint jobNum
)
988 // kdDebug() << "KttsJobMgrPart::textPaused: jobNum = " << jobNum << endl;
989 Q3ListViewItem
* item
= findItemByJobNum(jobNum
);
992 item
->setText(jlvcState
, stateToStr(KSpeech::jsPaused
));
997 * This signal is emitted when a text job, that was previously paused, resumes speaking.
998 * @param appId The DCOP senderId of the application that created the job.
999 * @param jobNum Job number of the text job.
1001 ASYNC
KttsJobMgrPart::textResumed(const QByteArray
&, const uint jobNum
)
1003 Q3ListViewItem
* item
= findItemByJobNum(jobNum
);
1006 item
->setText(jlvcState
, stateToStr(KSpeech::jsSpeaking
));
1011 * This signal is emitted whenever a text job is deleted from the queue.
1012 * The job is no longer in the queue when this signal is emitted.
1013 * @param appId The DCOP senderId of the application that created the job.
1014 * @param jobNum Job number of the text job.
1016 ASYNC
KttsJobMgrPart::textRemoved(const QByteArray
&, const uint jobNum
)
1018 Q3ListViewItem
* item
= findItemByJobNum(jobNum
);
1020 autoSelectInJobListView();
1023 KttsJobMgrBrowserExtension::KttsJobMgrBrowserExtension(KttsJobMgrPart
*parent
)
1024 : KParts::BrowserExtension(parent
)
1028 KttsJobMgrBrowserExtension::~KttsJobMgrBrowserExtension()