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
20 #include <QtCore/QDir>
21 #include <QtGui/QApplication>
22 #include <QtGui/QDockWidget>
23 #include <QtCore/QFileInfo>
24 #include <QtCore/QFile>
25 #include <QtCore/QByteArray>
26 #include <QtGui/QCloseEvent>
28 // include files for KDE
31 #include <kiconloader.h>
32 #include <kmessagebox.h>
33 #include <kdialogbase.h>
34 #include <kfiledialog.h>
37 #include <kstatusbar.h>
39 #include <kstandardaction.h>
40 #include <kedittoolbar.h>
41 #include <kshortcutsdialog.h>
43 #include <kstandarddirs.h>
46 // application specific includes
48 #include "ksayitviewimpl.h"
49 #include "voicesetupdlg.h"
50 #include "ksayitsystemtray.h"
51 // #include "effectstack.h"
52 // #include "fxpluginhandler.h"
54 #include "doctreeviewimpl.h"
55 #include "ksayitbookmarkhandler.h"
57 // #define KSAYITUI "/home/voglrobe/Projekte/ksayit/ksayit/ksayitui.rc"
58 #define KSAYITUI "ksayitui.rc"
59 #define ID_STATUS_MSG 1
61 KSayItApp::KSayItApp(QWidget
* parent
, const char* name
, Qt::WFlags f
,
62 const QByteArray
&objID
)
63 : KMainWindow(parent
, name
, f
)
73 m_currentBookmarkFile
.clear();
75 config
=KGlobal::config();
76 m_kttslib
= new KTTSDLib(this, "KTTSD-Library", kapp
);
81 initBookmarkManager( i18n("Untitled") );
84 setAutoSaveSettings("MainWindow");
88 // connect TTS plugin handler to this object
89 connect(m_kttslib
, SIGNAL(signalFinished()),
90 this, SLOT(slotTTSFinished()) );
92 // only used if library thinks it has to call the preferences dialog.
93 // e.g. when it detects a bad configuration.
94 connect(m_kttslib
, SIGNAL(signalCallPreferences()),
95 this, SLOT(slotPreferences()) );
98 cb
= QApplication::clipboard();
99 connect(cb
, SIGNAL(dataChanged()), this, SLOT(slotClipboardChanged()) );
101 // create SystemTray object
102 tray
= new KSayItSystemTray(this, "system_tray");
103 connect(tray
, SIGNAL(signalCallPreferences()), this, SLOT(slotPreferences()) );
104 connect(tray
, SIGNAL(signalSayActivated()), this, SLOT(slotSayText()) );
105 connect(tray
, SIGNAL(signalSayClipboard()), this, SLOT(slotSayClipboard()) );
106 connect(tray
, SIGNAL(signalShutUpActivated()), this, SLOT(slotStopActivated()) );
107 connect(tray
, SIGNAL(signalPauseActivated()), this, SLOT(slotPauseActivated()) );
108 connect(tray
, SIGNAL(signalNextActivated()), this, SLOT(slotNextSentenceActivated()) );
109 connect(tray
, SIGNAL(signalPrevActivated()), this, SLOT(slotPrevSentenceActivated()) );
111 tray
->setEnabled(true);
113 // create the FX plugin handler
114 // pluginhandler = new FXPluginHandler(this, "fxpluginhandler", config);
115 // m_fxpluginhandler->searchPlugins();
117 // create object for effectstack
118 // es = new EffectStack(m_fxpluginhandler, config);
120 // emit signalConfigChanged();
121 m_kttslib
->reloadConfiguration();
122 // m_fxpluginhandler ->readConfiguration();
125 // treeview->clear();
126 // treeview->createEmptyDocument();
130 KSayItApp::~KSayItApp()
132 // delete kapp->mainWidget();
135 // delete m_fxpluginhandler;
144 void KSayItApp::initActions()
147 open
= KStandardAction::open(this, SLOT(slotFileOpen()), actionCollection());
148 save
= KStandardAction::save(this, SLOT(slotFileSave()), actionCollection());
149 saveAs
= KStandardAction::saveAs(this, SLOT(slotFileSaveAs()), actionCollection());
150 KStandardAction::quit(this, SLOT(slotFileQuit()), actionCollection());
151 KStandardAction::close(this, SLOT(slotCloseMainWindow()), actionCollection());
152 cut
= KStandardAction::cut(view
, SLOT(slotCut()), actionCollection());
153 copy
= KStandardAction::copy(view
, SLOT(slotCopy()), actionCollection());
154 paste
= KStandardAction::paste(view
, SLOT(slotPaste()), actionCollection());
155 preferences
= KStandardAction::preferences(this, SLOT(slotPreferences()), actionCollection());
156 KStandardAction::keyBindings(this, SLOT(slotEditKeys()), actionCollection());
157 KStandardAction::configureToolbars(this, SLOT(slotConfigureToolbar()), actionCollection());
159 #warning "KStandardAction::showToolbar was deprecated"
162 KStandardAction::showToolbar("mainToolBar", actionCollection());
164 statusBarAction
= KStandardAction::showStatusbar(this, SLOT(slotToggleStatusBar()), actionCollection());
166 // User defined actions
167 say
= new KAction (i18n("Say"),
169 this, SLOT (slotSayText()),
173 pause
= new KAction (i18n("Pause"),
175 this, SLOT (slotPauseActivated()),
179 shutup
= new KAction (i18n("Shut Up"),
181 this, SLOT (slotStopActivated()),
185 next_sentence
= new KAction (i18n("Next Sentence"),
187 this, SLOT (slotNextSentenceActivated()),
192 prev_sentence
= new KAction (i18n("Previous Sentence"),
194 this, SLOT(slotPrevSentenceActivated()),
198 clear
= new KAction (i18n("Clear"),
200 this, SLOT(slotClear()),
204 edit
= new KToggleAction( i18n("Edit Text"),
206 this, SLOT(slotEditToggled()),
210 bookmarkmenu
= new KActionMenu(
211 KIcon("bookmarks"), // icon
214 "bookmarks"); // name
215 bookmarkmenu
->setDelayed(false);
217 // default disable/enable
218 save
->setEnabled(false);
219 saveAs
->setEnabled(false);
220 copy
->setEnabled(false);
221 cut
->setEnabled(false);
222 paste
->setEnabled(false);
223 say
->setEnabled(false);
224 pause
->setEnabled(false);
225 shutup
->setEnabled(false);
226 next_sentence
->setEnabled(false);
227 prev_sentence
->setEnabled(false);
228 preferences
->setEnabled(true);
229 edit
->setChecked(false);
230 bookmarkmenu
->setEnabled(false);
233 m_textview_empty
= true;
237 void KSayItApp::initBookmarkManager(const QString
&filename
)
239 QString bkFile
= getBookmarkDir( filename
);
240 if ( bkFile
.isNull() )
243 m_currentBookmarkFile
= bkFile
;
244 bkManager
= KBookmarkManager::managerForFile( bkFile
, "ksayit" );
246 // create BookmarkHandler object
249 bkHandler
= new KSayItBookmarkHandler(bkManager
, this);
251 // create Bookmarkmenu
252 KMenu
*bkPopupMenu
= bookmarkmenu
->popupMenu();
255 bkMenu
= new KBookmarkMenu(bkManager
, bkHandler
, bkPopupMenu
, 0, true );
259 void KSayItApp::slotNotifyBookmarkHandler(const QString
&ID
, const QString
&title
)
262 bkHandler
->notifyBookmarkHandler(ID
, title
);
266 void KSayItApp::slotDeleteBookmark(const QString
&url
, const QString
&title
)
268 kDebug(100200) << "KSayItApp::slotDeleteBookmark(" << url
<< ")";
270 bkHandler
->deleteBookmark( url
, title
);
274 QString
KSayItApp::getBookmarkDir(const QString
&filename
)
276 QString bkRelPath
= "ksayit/ksayit_bookmarks/" + filename
+ ".bookmarks";
278 bkFile
= locateLocal("data", bkRelPath
);
283 void KSayItApp::slotSetBookmarkFilename(const QString
&newname
)
285 kDebug(100200) << "KSayItApp::slotSetBookmarkFilename(" << newname
<< ")";
287 initBookmarkManager(newname
);
291 void KSayItApp::slotChangeBookmarkFilename(const QString
&newname
)
293 kDebug(100200) << "KSayItApp::slotChangeBookmarkFilename(" << newname
<< ")";
295 if ( m_currentBookmarkFile
.isNull() )
298 QString newbkFile
= getBookmarkDir(newname
);
299 if ( newbkFile
.isNull() )
302 // copy old bookmarkfile to new file
303 if ( m_currentBookmarkFile
!= newbkFile
){
304 if ( QFile::exists(m_currentBookmarkFile
) ){
305 QString command
= QString("cp %1 %2").arg(m_currentBookmarkFile
).arg(newbkFile
);
306 system( command
.ascii() );
308 // install new BookmarkHandler based on the new file
309 initBookmarkManager(newname
);
314 QString
KSayItApp::setItemByBookmark( const QString
&ID
, const QString
&title
)
317 result
= treeview
->selectItemByID( ID
, title
);
322 void KSayItApp::initStatusBar()
325 statusBar()->insertItem(i18n("Ready."), ID_STATUS_MSG
, 1);
326 statusBar()->setItemAlignment(ID_STATUS_MSG
, Qt::AlignLeft
);
330 void KSayItApp::initView()
332 // create the main widget
333 view
= new KSayItViewImpl(this);
334 view
->setMinimumSize(view
->sizeHint());
335 setCentralWidget(view
);
337 connect( view
, SIGNAL(signalEnableCopyCut(bool)),
338 this, SLOT(slotEnableCopyCut(bool)));
339 connect( view
, SIGNAL(signalShowStatus(const QString
&)),
340 this, SLOT(slotStatusMsg(const QString
&)));
341 connect( view
, SIGNAL(signalSetCaption(const QString
&)),
342 this, SLOT(slotSetCaption(const QString
&)));
343 connect( view
, SIGNAL(signalTextChanged(bool)),
344 this, SLOT(slotTextChanged(bool)) );
347 QDockWidget
*docview
= new QDockWidget(this);
348 treeview
= new DocTreeViewImpl(docview
, "treeview");
349 treeview
->enableContextMenus( true );
350 // treeview->clear();
351 docview
->setWidget(treeview
);
352 docview
->setAllowedAreas(Qt::LeftDockWidgetArea
| Qt::TopDockWidgetArea
| Qt::BottomDockWidgetArea
);
353 connect( treeview
, SIGNAL(signalContentChanged(const QString
&)),
354 this, SLOT(slotTreeViewChanged(const QString
&)) );
355 connect( treeview
, SIGNAL(signalSetText(const QString
&)),
356 this, SLOT(slotSetText(const QString
&)) );
357 connect( treeview
, SIGNAL(signalAllNodesProcessed()),
358 this, SLOT(slotSayNode()) );
359 connect( treeview
, SIGNAL(signalEnableTextedit(bool)),
360 this, SLOT(slotEnableTextedit(bool)) );
361 connect( treeview
, SIGNAL(signalNotifyBookmarkManager(const QString
&, const QString
&)),
362 this, SLOT(slotNotifyBookmarkHandler(const QString
&, const QString
&)) );
363 connect( treeview
, SIGNAL(signalSetBookmarkFilename(const QString
&)),
364 this, SLOT(slotSetBookmarkFilename(const QString
&)) );
365 connect( treeview
, SIGNAL(signalChangeBookmarkFilename(const QString
&)),
366 this, SLOT(slotChangeBookmarkFilename(const QString
&)) );
367 connect( treeview
, SIGNAL(signalDeleteBookmark(const QString
&, const QString
&)),
368 this, SLOT(slotDeleteBookmark(const QString
&, const QString
&)) );
372 void KSayItApp::readOptions()
374 applyMainWindowSettings( config
, "MainWindow" );
375 statusBarAction
->setChecked(!statusBar()->isHidden());
378 void KSayItApp::closeEvent(QCloseEvent
*ce
)
381 if ( !this->isVisible() ){
389 /////////////////////////////////////////////////////////////////////
391 /////////////////////////////////////////////////////////////////////
394 ASYNC KSayItApp::dcopSayText(QString msg)
400 ASYNC KSayItApp::dcopStop()
406 ASYNC KSayItApp::dcopSayXmlFile(KUrl url)
408 slotStatusMsg(i18n("Say XML file..."));
409 m_enableChangeNotifications = false;
412 if ( !url.isEmpty() ){
414 treeview->openFile( url );
415 setActions(ACTIONS::PLAY | ACTIONS::FFWD);
416 save ->setEnabled(false);
417 saveAs->setEnabled(true);
418 edit->setChecked(false);
419 treeview->setEditMode( false );
422 catch( QString err ){
423 KMessageBox::error(this, err);
424 save ->setEnabled(false);
425 saveAs->setEnabled(true);
428 m_enableChangeNotifications = true;
434 /////////////////////////////////////////////////////////////////////
435 // SLOT IMPLEMENTATION
436 /////////////////////////////////////////////////////////////////////
438 void KSayItApp::slotEditToggled()
440 if ( edit
->isChecked() ){
441 treeview
->setEditMode( true );
442 slotStatusMsg(i18n("Edit Mode ON."));
444 treeview
->setEditMode( false );
445 slotStatusMsg(i18n("Edit Mode OFF."));
450 void KSayItApp::slotSaveOptions()
452 saveMainWindowSettings( config
, "MainWindow" );
457 void KSayItApp::slotConfigureToolbar()
459 saveMainWindowSettings( config
, "MainWindow" );
460 KEditToolBar
dlg(actionCollection(), KSAYITUI
);
461 connect(&dlg
,SIGNAL(newToolbarConfig()),this,SLOT(slotNewToolbarConfig()));
469 void KSayItApp::slotNewToolbarConfig()
471 applyMainWindowSettings( config
, "MainWindow" );
475 void KSayItApp::slotFileOpen()
477 slotStatusMsg(i18n("Open file..."));
478 m_enableChangeNotifications
= false;
480 // open filerequester
482 QString
usershome( getenv("HOME") );
483 KUrl url
= KFileDialog::getOpenURL(usershome
, QString(), this, i18n("File to Speak") );
485 if ( !url
.isEmpty() ){
487 treeview
->openFile( url
);
488 setActions(ACTIONS::PLAY
| ACTIONS::FFWD
);
489 save
->setEnabled(false);
490 saveAs
->setEnabled(true);
491 edit
->setChecked(false);
492 treeview
->setEditMode( false );
493 bookmarkmenu
->setEnabled(true);
496 // catch( QString err ){
497 // KMessageBox::error(this, err);
498 // save ->setEnabled(false);
499 // saveAs->setEnabled(true);
500 // bookmarkmenu->setEnabled(false);
503 m_enableChangeNotifications
= true;
507 void KSayItApp::slotFileSave()
509 slotStatusMsg(i18n("Save file..."));
511 treeview
->saveFile();
512 save
->setEnabled(false);
513 saveAs
->setEnabled(true);
515 // catch ( QString err )
517 // KMessageBox::error(this, err);
518 // save ->setEnabled(false);
519 // saveAs->setEnabled(true);
524 void KSayItApp::slotFileSaveAs()
526 slotStatusMsg(i18n("Save file as..."));
528 treeview
->saveFileAs();
529 save
->setEnabled(true);
530 saveAs
->setEnabled(true);
531 bookmarkmenu
->setEnabled(true);
533 // catch ( QString err )
535 // KMessageBox::error(this, err);
536 // save ->setEnabled(true);
537 // saveAs->setEnabled(true);
538 // bookmarkmenu->setEnabled(false);
543 void KSayItApp::slotEnableCopyCut(bool enable
)
545 copy
->setEnabled(enable
);
546 cut
->setEnabled(enable
);
550 void KSayItApp::slotEditKeys()
552 KShortcutsDialog::configure( actionCollection() ); //, xmlFile());
556 void KSayItApp::slotFileQuit()
558 slotStatusMsg(i18n("Exiting..."));
559 int really
= KMessageBox::questionYesNo( this, i18n("Do you really want to quit?"), QString(), KStandardGuiItem::quit(), KStandardGuiItem::cancel() );
560 if (really
== KMessageBox::Yes
){
564 slotStatusMsg(i18n("Ready."));
569 void KSayItApp::slotCloseMainWindow()
575 void KSayItApp::slotToggleStatusBar()
577 slotStatusMsg(i18n("Toggle the statusbar..."));
578 //turn Statusbar on or off
579 if(statusBar()->isVisible())
584 slotStatusMsg(i18n("Ready."));
588 void KSayItApp::slotStatusMsg(const QString
&text
)
590 // change status message permanently
591 statusBar()->clear();
592 statusBar()->changeItem(text
, ID_STATUS_MSG
);
596 void KSayItApp::slotSetCaption(const QString
&caption
)
598 this->setCaption(caption
);
602 void KSayItApp::slotPreferences()
604 // create Preferences object and open it
605 VoiceSetupDlg
*prefs
= new VoiceSetupDlg(this, "preferences", i18n("Setup"), true,
607 /*m_fxpluginhandler,*/
610 if (prefs
->exec() == QDialog::Accepted
){
612 m_kttslib
->reloadConfiguration();
613 // m_fxpluginhandler ->readConfiguration();
620 void KSayItApp::slotClipboardChanged()
622 if ( cb
->text().isEmpty() ){
623 tray
->changeState( StateCLIPEMPTY::Instance() );
624 paste
->setEnabled(false);
628 if ( cb
->data(QClipboard::Clipboard
)->provides("text/plain") ){
629 tray
->changeState( StateWAIT::Instance() );
630 paste
->setEnabled(true);
632 tray
->changeState( StateCLIPEMPTY::Instance() );
633 paste
->setEnabled(false);
638 void KSayItApp::slotTextChanged(bool empty
)
640 m_textview_empty
= empty
;
642 // do nothing if change notifications from the Textedit are
643 // currently not welcome.
644 if ( !m_enableChangeNotifications
)
647 // do nothing if say is in progress
651 kDebug(100200) << "KSayItApp::slotTextChanged( " << empty
<< " )";
657 setActions(ACTIONS::PLAY
);
659 // save ->setEnabled(!empty);
660 saveAs
->setEnabled(!empty
);
662 // update TreeView-Item
663 treeview
->setNodeContent( view
->getText() );
668 void KSayItApp::slotClear()
670 m_enableChangeNotifications
= false;
676 treeview
->createEmptyDocument();
677 treeview
->setEditMode( true );
678 edit
->setChecked(true);
679 slotStatusMsg(i18n("Edit Mode ON."));
682 save
->setEnabled(false);
683 saveAs
->setEnabled(false);
685 bookmarkmenu
->setEnabled(false);
686 m_enableChangeNotifications
= true;
690 void KSayItApp::slotSayClipboard()
692 // get Text from clipboard
693 slotStatusMsg(i18n("speaking Clipboard..."));
694 setActions(ACTIONS::PAUSE
| ACTIONS::STOP
| ACTIONS::FFWD
| ACTIONS::FREV
);
695 tray
->changeState( StateSAY::Instance() );
698 // sayActivated( clip.trimmed() );
699 // set text and say it
700 slotSetText( clip
.trimmed() );
705 void KSayItApp::slotSayText()
707 // say Text from text-window
708 setActions(ACTIONS::PAUSE
| ACTIONS::STOP
| ACTIONS::FFWD
| ACTIONS::FREV
);
709 tray
->changeState( StateSAY::Instance() );
711 slotStatusMsg(i18n("synthesizing..."));
717 // es->loadEffects();
718 treeview
->sayActiveNodeAndChilds();
723 void KSayItApp::slotSayNode()
729 void KSayItApp::slotSetText(const QString
&text
)
731 // also invoked by the treeview for the each node
735 // put text on the stack of KTTS
736 m_kttslib
->setText( text
);
739 void KSayItApp::sayActivated()
741 kDebug(100200) << "KSayItApp::sayActivated()";
743 preferences
->setEnabled(false);
747 m_kttslib
->sayText();
749 // catch (QString err){
750 // kDebug(100200) << "Exception caught in KSayItApp::sayActivated()";
751 // KMessageBox::sorry(0, err, i18n("Unable to speak text"));
757 void KSayItApp::slotTTSFinished()
759 kDebug(100200) << "KSayItApp::slotTTSFinished()";
760 // es->unloadEffects();
765 void KSayItApp::slotFinished()
767 kDebug(100200) << "KSayItApp::slotFinished()";
769 // disable/enable actions
772 if ( m_textview_empty
){
775 setActions(ACTIONS::PLAY
);
777 tray
->changeState( StateWAIT::Instance() );
778 preferences
->setEnabled(true);
780 slotStatusMsg(i18n("Ready."));
784 void KSayItApp::slotStopActivated()
791 void KSayItApp::slotPauseActivated()
793 kDebug(100200) << "KSayItApp::slotPauseActivated()";
797 setActions(ACTIONS::PLAY
| ACTIONS::STOP
);
798 tray
->changeState( StateSAY::Instance() );
799 slotStatusMsg(i18n("Paused..."));
803 void KSayItApp::slotNextSentenceActivated()
805 kDebug(100200) << "KSayItApp::slotNextSentenceActivated()";
810 void KSayItApp::slotPrevSentenceActivated()
812 kDebug(100200) << "KSayItApp::slotPrevSentenceActivated()";
817 void KSayItApp::setActions(int actions
)
819 // ACTIONS::PLAY | ACTIONS::STOP | ACTIONS::PAUSE | ACTIONS::FFWD | ACTIONS::FREV;
821 // Get the mask of supported actions from the plugin.
822 int mask
= m_kttslib
->getActions();
823 kDebug(100200) << QString("KSayItApp:PSA: %1").arg(mask
, 0, 2);
825 // disable actions not supported by the plugin
826 int ma
= actions
& mask
;
828 if (ma
& ACTIONS::PLAY
){
829 say
->setEnabled(true);
831 say
->setEnabled(false);
833 if (ma
& ACTIONS::STOP
){
834 shutup
->setEnabled(true);
836 shutup
->setEnabled(false);
838 if (ma
& ACTIONS::PAUSE
){
839 pause
->setEnabled(true);
841 pause
->setEnabled(false);
843 if (ma
& ACTIONS::FFWD
){
844 next_sentence
->setEnabled(true);
846 next_sentence
->setEnabled(false);
848 if (ma
& ACTIONS::FREV
){
849 prev_sentence
->setEnabled(true);
851 prev_sentence
->setEnabled(false);
854 tray
->setActions( say
->isEnabled(), pause
->isEnabled(), shutup
->isEnabled(),
855 next_sentence
->isEnabled(), prev_sentence
->isEnabled() );
859 void KSayItApp::slotTreeViewChanged(const QString
&str
)
861 kDebug(100200) << "KSayItApp::slotTreeViewChanged()";
864 setActions(ACTIONS::PLAY
);
866 m_enableChangeNotifications
= false;
869 m_enableChangeNotifications
= true;
873 void KSayItApp::slotEnableTextedit(bool enable
)
875 kDebug(100200) << "KSayItApp::slotEnableTextedit( " << enable
<< " )";
877 view
->enableTextedit( enable
);
881 void KSayItApp::resetView()
883 m_enableChangeNotifications
= false;
891 save
->setEnabled(false);
892 saveAs
->setEnabled(false);
894 m_enableChangeNotifications
= true;
898 void KSayItApp::slotAddBookmark()
900 kDebug(100200) << "KSayItApp::slotAddBookmark()";
906 void KSayItApp::slotEditBookmarks()
908 kDebug(100200) << "KSayItApp::slotEditBookmark()";
915 #include "ksayit.moc"