1 /***************************************************************************
2 ksayit.cpp - description
4 begin : Son Aug 10 13:26:57 EDT 2003
5 copyright : (C) 2003 by Robert Vogl
6 email : voglrobe@saphir
7 ***************************************************************************/
9 /***************************************************************************
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 ***************************************************************************/
17 #include <stdlib.h> // getenv, system
19 // include files for QT
21 #include <QApplication>
22 #include <QDockWidget>
27 #include <QCloseEvent>
29 // include files for KDE
32 #include <kiconloader.h>
33 #include <kmessagebox.h>
34 #include <kdialogbase.h>
35 #include <kfiledialog.h>
38 #include <kstatusbar.h>
40 #include <kstdaction.h>
41 #include <kedittoolbar.h>
42 #include <kkeydialog.h>
44 #include <kstandarddirs.h>
47 // application specific includes
49 #include "ksayitviewimpl.h"
50 #include "voicesetupdlg.h"
51 #include "ksayitsystemtray.h"
52 // #include "effectstack.h"
53 // #include "fxpluginhandler.h"
55 #include "doctreeviewimpl.h"
56 #include "ksayitbookmarkhandler.h"
58 // #define KSAYITUI "/home/voglrobe/Projekte/ksayit/ksayit/ksayitui.rc"
59 #define KSAYITUI "ksayitui.rc"
60 #define ID_STATUS_MSG 1
62 KSayItApp::KSayItApp(QWidget
* parent
, const char* name
, Qt::WFlags f
,
63 const QByteArray
&objID
)
64 : KMainWindow(parent
, name
, f
)
74 m_currentBookmarkFile
.clear();
76 config
=KGlobal::config();
77 m_kttslib
= new KTTSDLib(this, "KTTSD-Library", kapp
);
82 initBookmarkManager( i18n("Untitled") );
85 setAutoSaveSettings("MainWindow");
89 // connect TTS plugin handler to this object
90 connect(m_kttslib
, SIGNAL(signalFinished()),
91 this, SLOT(slotTTSFinished()) );
93 // only used if library thinks it has to call the preferences dialog.
94 // e.g. when it detects a bad configuration.
95 connect(m_kttslib
, SIGNAL(signalCallPreferences()),
96 this, SLOT(slotPreferences()) );
99 cb
= QApplication::clipboard();
100 connect(cb
, SIGNAL(dataChanged()), this, SLOT(slotClipboardChanged()) );
102 // create SystemTray object
103 tray
= new KSayItSystemTray(this, "system_tray");
104 connect(tray
, SIGNAL(signalCallPreferences()), this, SLOT(slotPreferences()) );
105 connect(tray
, SIGNAL(signalSayActivated()), this, SLOT(slotSayText()) );
106 connect(tray
, SIGNAL(signalSayClipboard()), this, SLOT(slotSayClipboard()) );
107 connect(tray
, SIGNAL(signalShutUpActivated()), this, SLOT(slotStopActivated()) );
108 connect(tray
, SIGNAL(signalPauseActivated()), this, SLOT(slotPauseActivated()) );
109 connect(tray
, SIGNAL(signalNextActivated()), this, SLOT(slotNextSentenceActivated()) );
110 connect(tray
, SIGNAL(signalPrevActivated()), this, SLOT(slotPrevSentenceActivated()) );
112 tray
->setEnabled(true);
114 // create the FX plugin handler
115 // pluginhandler = new FXPluginHandler(this, "fxpluginhandler", config);
116 // m_fxpluginhandler->searchPlugins();
118 // create object for effectstack
119 // es = new EffectStack(m_fxpluginhandler, config);
121 // emit signalConfigChanged();
122 m_kttslib
->reloadConfiguration();
123 // m_fxpluginhandler ->readConfiguration();
126 // treeview->clear();
127 // treeview->createEmptyDocument();
131 KSayItApp::~KSayItApp()
133 // delete kapp->mainWidget();
136 // delete m_fxpluginhandler;
145 void KSayItApp::initActions()
148 open
= KStdAction::open(this, SLOT(slotFileOpen()), actionCollection());
149 save
= KStdAction::save(this, SLOT(slotFileSave()), actionCollection());
150 saveAs
= KStdAction::saveAs(this, SLOT(slotFileSaveAs()), actionCollection());
151 KStdAction::quit(this, SLOT(slotFileQuit()), actionCollection());
152 KStdAction::close(this, SLOT(slotCloseMainWindow()), actionCollection());
153 cut
= KStdAction::cut(view
, SLOT(slotCut()), actionCollection());
154 copy
= KStdAction::copy(view
, SLOT(slotCopy()), actionCollection());
155 paste
= KStdAction::paste(view
, SLOT(slotPaste()), actionCollection());
156 preferences
= KStdAction::preferences(this, SLOT(slotPreferences()), actionCollection());
157 KStdAction::keyBindings(this, SLOT(slotEditKeys()), actionCollection());
158 KStdAction::configureToolbars(this, SLOT(slotConfigureToolbar()), actionCollection());
159 #warning "KStdAction::showToolbar was deprecated"
161 KStdAction::showToolbar("mainToolBar", actionCollection());
163 statusBarAction
= KStdAction::showStatusbar(this, SLOT(slotToggleStatusBar()), actionCollection());
165 // User defined actions
166 say
= new KAction (i18n("Say"),
168 this, SLOT (slotSayText()),
172 pause
= new KAction (i18n("Pause"),
174 this, SLOT (slotPauseActivated()),
178 shutup
= new KAction (i18n("Shut Up"),
180 this, SLOT (slotStopActivated()),
184 next_sentence
= new KAction (i18n("Next Sentence"),
186 this, SLOT (slotNextSentenceActivated()),
191 prev_sentence
= new KAction (i18n("Previous Sentence"),
193 this, SLOT(slotPrevSentenceActivated()),
197 clear
= new KAction (i18n("Clear"),
199 this, SLOT(slotClear()),
203 edit
= new KToggleAction( i18n("Edit Text"),
205 this, SLOT(slotEditToggled()),
209 bookmarkmenu
= new KActionMenu(
210 KIcon("bookmark"), // icon
213 "bookmarks"); // name
214 bookmarkmenu
->setDelayed(false);
216 // default disable/enable
217 save
->setEnabled(false);
218 saveAs
->setEnabled(false);
219 copy
->setEnabled(false);
220 cut
->setEnabled(false);
221 paste
->setEnabled(false);
222 say
->setEnabled(false);
223 pause
->setEnabled(false);
224 shutup
->setEnabled(false);
225 next_sentence
->setEnabled(false);
226 prev_sentence
->setEnabled(false);
227 preferences
->setEnabled(true);
228 edit
->setChecked(false);
229 bookmarkmenu
->setEnabled(false);
232 m_textview_empty
= true;
236 void KSayItApp::initBookmarkManager(const QString
&filename
)
238 QString bkFile
= getBookmarkDir( filename
);
239 if ( bkFile
.isNull() )
242 m_currentBookmarkFile
= bkFile
;
243 bkManager
= KBookmarkManager::managerForFile( bkFile
, false );
245 // create BookmarkHandler object
248 bkHandler
= new KSayItBookmarkHandler(bkManager
, this);
250 // create Bookmarkmenu
251 KMenu
*bkPopupMenu
= bookmarkmenu
->popupMenu();
254 bkMenu
= new KBookmarkMenu(bkManager
, bkHandler
, bkPopupMenu
, 0, true );
258 void KSayItApp::slotNotifyBookmarkHandler(const QString
&ID
, const QString
&title
)
261 bkHandler
->notifyBookmarkHandler(ID
, title
);
265 void KSayItApp::slotDeleteBookmark(const QString
&url
, const QString
&title
)
267 kDebug(100200) << "KSayItApp::slotDeleteBookmark(" << url
<< ")" << endl
;
269 bkHandler
->deleteBookmark( url
, title
);
273 QString
KSayItApp::getBookmarkDir(const QString
&filename
)
275 QString bkRelPath
= "ksayit/ksayit_bookmarks/" + filename
+ ".bookmarks";
277 bkFile
= locateLocal("data", bkRelPath
);
282 void KSayItApp::slotSetBookmarkFilename(const QString
&newname
)
284 kDebug(100200) << "KSayItApp::slotSetBookmarkFilename(" << newname
<< ")" << endl
;
286 initBookmarkManager(newname
);
290 void KSayItApp::slotChangeBookmarkFilename(const QString
&newname
)
292 kDebug(100200) << "KSayItApp::slotChangeBookmarkFilename(" << newname
<< ")" << endl
;
294 if ( m_currentBookmarkFile
.isNull() )
297 QString newbkFile
= getBookmarkDir(newname
);
298 if ( newbkFile
.isNull() )
301 // copy old bookmarkfile to new file
302 if ( m_currentBookmarkFile
!= newbkFile
){
303 if ( QFile::exists(m_currentBookmarkFile
) ){
304 QString command
= QString("cp %1 %2").arg(m_currentBookmarkFile
).arg(newbkFile
);
305 system( command
.ascii() );
307 // install new BookmarkHandler based on the new file
308 initBookmarkManager(newname
);
313 QString
KSayItApp::setItemByBookmark( const QString
&ID
, const QString
&title
)
316 result
= treeview
->selectItemByID( ID
, title
);
321 void KSayItApp::initStatusBar()
324 statusBar()->insertItem(i18n("Ready."), ID_STATUS_MSG
, 1);
325 statusBar()->setItemAlignment(ID_STATUS_MSG
, Qt::AlignLeft
);
329 void KSayItApp::initView()
331 // create the main widget
332 view
= new KSayItViewImpl(this);
333 view
->setMinimumSize(view
->sizeHint());
334 setCentralWidget(view
);
336 connect( view
, SIGNAL(signalEnableCopyCut(bool)),
337 this, SLOT(slotEnableCopyCut(bool)));
338 connect( view
, SIGNAL(signalShowStatus(const QString
&)),
339 this, SLOT(slotStatusMsg(const QString
&)));
340 connect( view
, SIGNAL(signalSetCaption(const QString
&)),
341 this, SLOT(slotSetCaption(const QString
&)));
342 connect( view
, SIGNAL(signalTextChanged(bool)),
343 this, SLOT(slotTextChanged(bool)) );
346 QDockWidget
*docview
= new QDockWidget(this);
347 treeview
= new DocTreeViewImpl(docview
, "treeview");
348 treeview
->enableContextMenus( true );
349 // treeview->clear();
350 docview
->setWidget(treeview
);
351 docview
->setAllowedAreas(Qt::LeftDockWidgetArea
| Qt::TopDockWidgetArea
| Qt::BottomDockWidgetArea
);
352 connect( treeview
, SIGNAL(signalContentChanged(const QString
&)),
353 this, SLOT(slotTreeViewChanged(const QString
&)) );
354 connect( treeview
, SIGNAL(signalSetText(const QString
&)),
355 this, SLOT(slotSetText(const QString
&)) );
356 connect( treeview
, SIGNAL(signalAllNodesProcessed()),
357 this, SLOT(slotSayNode()) );
358 connect( treeview
, SIGNAL(signalEnableTextedit(bool)),
359 this, SLOT(slotEnableTextedit(bool)) );
360 connect( treeview
, SIGNAL(signalNotifyBookmarkManager(const QString
&, const QString
&)),
361 this, SLOT(slotNotifyBookmarkHandler(const QString
&, const QString
&)) );
362 connect( treeview
, SIGNAL(signalSetBookmarkFilename(const QString
&)),
363 this, SLOT(slotSetBookmarkFilename(const QString
&)) );
364 connect( treeview
, SIGNAL(signalChangeBookmarkFilename(const QString
&)),
365 this, SLOT(slotChangeBookmarkFilename(const QString
&)) );
366 connect( treeview
, SIGNAL(signalDeleteBookmark(const QString
&, const QString
&)),
367 this, SLOT(slotDeleteBookmark(const QString
&, const QString
&)) );
371 void KSayItApp::readOptions()
373 applyMainWindowSettings( config
, "MainWindow" );
374 statusBarAction
->setChecked(!statusBar()->isHidden());
377 void KSayItApp::closeEvent(QCloseEvent
*ce
)
380 if ( !this->isVisible() ){
388 /////////////////////////////////////////////////////////////////////
390 /////////////////////////////////////////////////////////////////////
393 ASYNC KSayItApp::dcopSayText(QString msg)
399 ASYNC KSayItApp::dcopStop()
405 ASYNC KSayItApp::dcopSayXmlFile(KUrl url)
407 slotStatusMsg(i18n("Say XML file..."));
408 m_enableChangeNotifications = false;
411 if ( !url.isEmpty() ){
413 treeview->openFile( url );
414 setActions(ACTIONS::PLAY | ACTIONS::FFWD);
415 save ->setEnabled(false);
416 saveAs->setEnabled(true);
417 edit->setChecked(false);
418 treeview->setEditMode( false );
421 catch( QString err ){
422 KMessageBox::error(this, err);
423 save ->setEnabled(false);
424 saveAs->setEnabled(true);
427 m_enableChangeNotifications = true;
433 /////////////////////////////////////////////////////////////////////
434 // SLOT IMPLEMENTATION
435 /////////////////////////////////////////////////////////////////////
437 void KSayItApp::slotEditToggled()
439 if ( edit
->isChecked() ){
440 treeview
->setEditMode( true );
441 slotStatusMsg(i18n("Edit Mode ON."));
443 treeview
->setEditMode( false );
444 slotStatusMsg(i18n("Edit Mode OFF."));
449 void KSayItApp::slotSaveOptions()
451 saveMainWindowSettings( config
, "MainWindow" );
456 void KSayItApp::slotConfigureToolbar()
458 saveMainWindowSettings( config
, "MainWindow" );
459 KEditToolbar
dlg(actionCollection(), KSAYITUI
);
460 connect(&dlg
,SIGNAL(newToolbarConfig()),this,SLOT(slotNewToolbarConfig()));
468 void KSayItApp::slotNewToolbarConfig()
470 applyMainWindowSettings( config
, "MainWindow" );
474 void KSayItApp::slotFileOpen()
476 slotStatusMsg(i18n("Open file..."));
477 m_enableChangeNotifications
= false;
479 // open filerequester
481 QString
usershome( getenv("HOME") );
482 KUrl url
= KFileDialog::getOpenURL(usershome
, QString(), this, i18n("File to Speak") );
484 if ( !url
.isEmpty() ){
486 treeview
->openFile( url
);
487 setActions(ACTIONS::PLAY
| ACTIONS::FFWD
);
488 save
->setEnabled(false);
489 saveAs
->setEnabled(true);
490 edit
->setChecked(false);
491 treeview
->setEditMode( false );
492 bookmarkmenu
->setEnabled(true);
495 // catch( QString err ){
496 // KMessageBox::error(this, err);
497 // save ->setEnabled(false);
498 // saveAs->setEnabled(true);
499 // bookmarkmenu->setEnabled(false);
502 m_enableChangeNotifications
= true;
506 void KSayItApp::slotFileSave()
508 slotStatusMsg(i18n("Save file..."));
510 treeview
->saveFile();
511 save
->setEnabled(false);
512 saveAs
->setEnabled(true);
514 // catch ( QString err )
516 // KMessageBox::error(this, err);
517 // save ->setEnabled(false);
518 // saveAs->setEnabled(true);
523 void KSayItApp::slotFileSaveAs()
525 slotStatusMsg(i18n("Save file as..."));
527 treeview
->saveFileAs();
528 save
->setEnabled(true);
529 saveAs
->setEnabled(true);
530 bookmarkmenu
->setEnabled(true);
532 // catch ( QString err )
534 // KMessageBox::error(this, err);
535 // save ->setEnabled(true);
536 // saveAs->setEnabled(true);
537 // bookmarkmenu->setEnabled(false);
542 void KSayItApp::slotEnableCopyCut(bool enable
)
544 copy
->setEnabled(enable
);
545 cut
->setEnabled(enable
);
549 void KSayItApp::slotEditKeys()
551 KKeyDialog::configure( actionCollection() ); //, xmlFile());
555 void KSayItApp::slotFileQuit()
557 slotStatusMsg(i18n("Exiting..."));
558 int really
= KMessageBox::questionYesNo( this, i18n("Do you really want to quit?"), QString(), KStdGuiItem::quit(), KStdGuiItem::cancel() );
559 if (really
== KMessageBox::Yes
){
563 slotStatusMsg(i18n("Ready."));
568 void KSayItApp::slotCloseMainWindow()
574 void KSayItApp::slotToggleStatusBar()
576 slotStatusMsg(i18n("Toggle the statusbar..."));
577 //turn Statusbar on or off
578 if(statusBar()->isVisible())
583 slotStatusMsg(i18n("Ready."));
587 void KSayItApp::slotStatusMsg(const QString
&text
)
589 // change status message permanently
590 statusBar()->clear();
591 statusBar()->changeItem(text
, ID_STATUS_MSG
);
595 void KSayItApp::slotSetCaption(const QString
&caption
)
597 this->setCaption(caption
);
601 void KSayItApp::slotPreferences()
603 // create Preferences object and open it
604 VoiceSetupDlg
*prefs
= new VoiceSetupDlg(this, "preferences", i18n("Setup"), true,
606 /*m_fxpluginhandler,*/
609 if (prefs
->exec() == QDialog::Accepted
){
611 m_kttslib
->reloadConfiguration();
612 // m_fxpluginhandler ->readConfiguration();
619 void KSayItApp::slotClipboardChanged()
621 if ( cb
->text().isEmpty() ){
622 tray
->changeState( StateCLIPEMPTY::Instance() );
623 paste
->setEnabled(false);
627 if ( cb
->data(QClipboard::Clipboard
)->provides("text/plain") ){
628 tray
->changeState( StateWAIT::Instance() );
629 paste
->setEnabled(true);
631 tray
->changeState( StateCLIPEMPTY::Instance() );
632 paste
->setEnabled(false);
637 void KSayItApp::slotTextChanged(bool empty
)
639 m_textview_empty
= empty
;
641 // do nothing if change notifications from the Textedit are
642 // currently not welcome.
643 if ( !m_enableChangeNotifications
)
646 // do nothing if say is in progress
650 kDebug(100200) << "KSayItApp::slotTextChanged( " << empty
<< " )" << endl
;
656 setActions(ACTIONS::PLAY
);
658 // save ->setEnabled(!empty);
659 saveAs
->setEnabled(!empty
);
661 // update TreeView-Item
662 treeview
->setNodeContent( view
->getText() );
667 void KSayItApp::slotClear()
669 m_enableChangeNotifications
= false;
675 treeview
->createEmptyDocument();
676 treeview
->setEditMode( true );
677 edit
->setChecked(true);
678 slotStatusMsg(i18n("Edit Mode ON."));
681 save
->setEnabled(false);
682 saveAs
->setEnabled(false);
684 bookmarkmenu
->setEnabled(false);
685 m_enableChangeNotifications
= true;
689 void KSayItApp::slotSayClipboard()
691 // get Text from clipboard
692 slotStatusMsg(i18n("speaking Clipboard..."));
693 setActions(ACTIONS::PAUSE
| ACTIONS::STOP
| ACTIONS::FFWD
| ACTIONS::FREV
);
694 tray
->changeState( StateSAY::Instance() );
697 // sayActivated( clip.trimmed() );
698 // set text and say it
699 slotSetText( clip
.trimmed() );
704 void KSayItApp::slotSayText()
706 // say Text from text-window
707 setActions(ACTIONS::PAUSE
| ACTIONS::STOP
| ACTIONS::FFWD
| ACTIONS::FREV
);
708 tray
->changeState( StateSAY::Instance() );
710 slotStatusMsg(i18n("synthesizing..."));
716 // es->loadEffects();
717 treeview
->sayActiveNodeAndChilds();
722 void KSayItApp::slotSayNode()
728 void KSayItApp::slotSetText(const QString
&text
)
730 // also invoked by the treeview for the each node
734 // put text on the stack of KTTS
735 m_kttslib
->setText( text
);
738 void KSayItApp::sayActivated()
740 kDebug(100200) << "KSayItApp::sayActivated()" << endl
;
742 preferences
->setEnabled(false);
746 m_kttslib
->sayText();
748 // catch (QString err){
749 // kDebug(100200) << "Exception catched in KSayItApp::sayActivated()" << endl;
750 // KMessageBox::sorry(0, err, i18n("Unable to speak text"));
756 void KSayItApp::slotTTSFinished()
758 kDebug(100200) << "KSayItApp::slotTTSFinished()" << endl
;
759 // es->unloadEffects();
764 void KSayItApp::slotFinished()
766 kDebug(100200) << "KSayItApp::slotFinished()" << endl
;
768 // disable/enable actions
771 if ( m_textview_empty
){
774 setActions(ACTIONS::PLAY
);
776 tray
->changeState( StateWAIT::Instance() );
777 preferences
->setEnabled(true);
779 slotStatusMsg(i18n("Ready."));
783 void KSayItApp::slotStopActivated()
790 void KSayItApp::slotPauseActivated()
792 kDebug(100200) << "KSayItApp::slotPauseActivated()" << endl
;
796 setActions(ACTIONS::PLAY
| ACTIONS::STOP
);
797 tray
->changeState( StateSAY::Instance() );
798 slotStatusMsg(i18n("Paused..."));
802 void KSayItApp::slotNextSentenceActivated()
804 kDebug(100200) << "KSayItApp::slotNextSentenceActivated()" << endl
;
809 void KSayItApp::slotPrevSentenceActivated()
811 kDebug(100200) << "KSayItApp::slotPrevSentenceActivated()" << endl
;
816 void KSayItApp::setActions(int actions
)
818 // ACTIONS::PLAY | ACTIONS::STOP | ACTIONS::PAUSE | ACTIONS::FFWD | ACTIONS::FREV;
820 // Get the mask of supported actions from the plugin.
821 int mask
= m_kttslib
->getActions();
822 kDebug(100200) << QString("KSayItApp:PSA: %1").arg(mask
, 0, 2) << endl
;
824 // disable actions not supported by the plugin
825 int ma
= actions
& mask
;
827 if (ma
& ACTIONS::PLAY
){
828 say
->setEnabled(true);
830 say
->setEnabled(false);
832 if (ma
& ACTIONS::STOP
){
833 shutup
->setEnabled(true);
835 shutup
->setEnabled(false);
837 if (ma
& ACTIONS::PAUSE
){
838 pause
->setEnabled(true);
840 pause
->setEnabled(false);
842 if (ma
& ACTIONS::FFWD
){
843 next_sentence
->setEnabled(true);
845 next_sentence
->setEnabled(false);
847 if (ma
& ACTIONS::FREV
){
848 prev_sentence
->setEnabled(true);
850 prev_sentence
->setEnabled(false);
853 tray
->setActions( say
->isEnabled(), pause
->isEnabled(), shutup
->isEnabled(),
854 next_sentence
->isEnabled(), prev_sentence
->isEnabled() );
858 void KSayItApp::slotTreeViewChanged(const QString
&str
)
860 kDebug(100200) << "KSayItApp::slotTreeViewChanged()" << endl
;
863 setActions(ACTIONS::PLAY
);
865 m_enableChangeNotifications
= false;
868 m_enableChangeNotifications
= true;
872 void KSayItApp::slotEnableTextedit(bool enable
)
874 kDebug(100200) << "KSayItApp::slotEnableTextedit( " << enable
<< " )" << endl
;
876 view
->enableTextedit( enable
);
880 void KSayItApp::resetView()
882 m_enableChangeNotifications
= false;
890 save
->setEnabled(false);
891 saveAs
->setEnabled(false);
893 m_enableChangeNotifications
= true;
897 void KSayItApp::slotAddBookmark()
899 kDebug(100200) << "KSayItApp::slotAddBookmark()" << endl
;
905 void KSayItApp::slotEditBookmarks()
907 kDebug(100200) << "KSayItApp::slotEditBookmark()" << endl
;
914 #include "ksayit.moc"