1/***************************************************************************
2 kmouth.cpp - description
3 -------------------
4 begin : Mon Aug 26 15:41:23 CEST 2002
5 copyright : (C) 2002 by Gunnar Schmi Dt
6 email : kmouth@schmi-dt.de
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
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. *
15 * *
16 ***************************************************************************/
17
18// application specific includes
19#include "kmouth.h"
20#include "phraselist.h"
21#include "phrasebook/phrasebook.h"
22#include "phrasebook/phrasebookdialog.h"
23#include "optionsdialog.h"
24#include "configwizard.h"
25
26// include files for Qt
27#include <QtCore/QDir>
28#include <QtGui/QPainter>
29#include <QtGui/QPrintDialog>
30#include <QtGui/QMenu>
31
32// include files for KDE
33#include <kxmlguifactory.h>
34#include <kiconloader.h>
35#include <kmenubar.h>
36#include <kstatusbar.h>
37#include <klocale.h>
38#include <kconfig.h>
39#include <kstandardaction.h>
40#include <kmenu.h>
41#include <kstandarddirs.h>
42#include <kglobal.h>
43#include <ktoolbar.h>
44#include <kactioncollection.h>
45#include <kactionmenu.h>
46#include <ktoggleaction.h>
47#include <kstandardshortcut.h>
48#include <kapplication.h>
49#include <kdeprintdialog.h>
50
51#define ID_STATUS_MSG 1
52
53KMouthApp::KMouthApp(QWidget* , const char* name):KXmlGuiWindow(0)
54{
55 setObjectName( QLatin1String( name ) );
56 isConfigured = false;
57 config=KGlobal::config();
58
59 ///////////////////////////////////////////////////////////////////
60 // call inits to invoke all other construction parts
61 initStatusBar();
62 initPhraseList();
63 initActions();
64 optionsDialog = new OptionsDialog(this);
65 connect (optionsDialog, SIGNAL(configurationChanged()),
66 this, SLOT(slotConfigurationChanged()));
67 connect (optionsDialog, SIGNAL(configurationChanged()),
68 phraseList, SLOT(configureCompletion()));
69
70 phrases = new KActionCollection (static_cast<QWidget*>(this));
71
72 readOptions();
73 ConfigWizard *wizard = new ConfigWizard (this, "ConfigWizard", config.data());
74 if (wizard->configurationNeeded ()) {
75 if (wizard->requestConfiguration ()) {
76 isConfigured = true;
77 saveOptions();
78 wizard->saveConfig (config.data());
79 readOptions();
80 }
81 else
82 isConfigured = false;
83 }
84 else
85 isConfigured = true;
86 delete wizard;
87
88 if (isConfigured) {
89 phraseList->configureCompletion();
90 }
91
92 ///////////////////////////////////////////////////////////////////
93 // disable actions at startup
94 fileSaveAs->setEnabled(false);
95 filePrint->setEnabled(false);
96
97 printer = 0;
98}
99
100KMouthApp::~KMouthApp()
101{
102 delete printer;
103}
104
105bool KMouthApp::configured() {
106 return isConfigured;
107}
108
109void KMouthApp::initActions() {
110// The "File" menu
111 fileOpen = actionCollection()->addAction(QLatin1String( "file_open" ));
112 fileOpen->setIcon(KIcon( QLatin1String( "phrasehistory_open" )));
113 fileOpen->setText(i18n("&Open as History..."));
114 fileOpen->setShortcuts(KStandardShortcut::open());
115 connect(fileOpen, SIGNAL(triggered(bool)), this, SLOT(slotFileOpen()));
116 fileOpen->setToolTip(i18n("Opens an existing file as history"));
117 fileOpen->setWhatsThis (i18n("Opens an existing file as history"));
118
119 fileSaveAs = actionCollection()->addAction(QLatin1String( "file_save_as" ));
120 fileSaveAs->setIcon(KIcon( QLatin1String( "phrasehistory_save" )));
121 fileSaveAs->setText(i18n("Save &History As..."));
122 fileSaveAs->setShortcuts(KStandardShortcut::save());
123 connect(fileSaveAs, SIGNAL(triggered(bool)), this, SLOT(slotFileSaveAs()));
124 fileSaveAs->setToolTip(i18n("Saves the actual history as..."));
125 fileSaveAs->setWhatsThis (i18n("Saves the actual history as..."));
126
127 filePrint = actionCollection()->addAction(QLatin1String( "file_print" ));
128 filePrint->setIcon(KIcon( QLatin1String( "phrasehistory_print" )));
129 filePrint->setText(i18n("&Print History..."));
130 filePrint->setShortcuts(KStandardShortcut::print());
131 connect(filePrint, SIGNAL(triggered(bool)), this, SLOT(slotFilePrint()));
132 filePrint->setToolTip(i18n("Prints out the actual history"));
133 filePrint->setWhatsThis (i18n("Prints out the actual history"));
134
135 fileQuit = KStandardAction::quit(this, SLOT(slotFileQuit()), actionCollection());
136 fileQuit->setToolTip(i18n("Quits the application"));
137 fileQuit->setWhatsThis (i18n("Quits the application"));
138
139// The "Edit" menu
140 editCut = KStandardAction::cut(phraseList, SLOT(cut()), actionCollection());
141 editCut->setToolTip(i18n("Cuts the selected section and puts it to the clipboard"));
142 editCut->setWhatsThis (i18n("Cuts the selected section and puts it to the clipboard. If there is some text selected in the edit field it is placed it on the clipboard. Otherwise the selected sentences in the history (if any) are placed on the clipboard."));
143
144 editCopy = KStandardAction::copy(phraseList, SLOT(copy()), actionCollection());
145 editCopy->setToolTip(i18n("Copies the selected section to the clipboard"));
146 editCopy->setWhatsThis (i18n("Copies the selected section to the clipboard. If there is some text selected in the edit field it is copied to the clipboard. Otherwise the selected sentences in the history (if any) are copied to the clipboard."));
147
148 editPaste = KStandardAction::paste(phraseList, SLOT(paste()), actionCollection());
149 editPaste->setToolTip(i18n("Pastes the clipboard contents to current position"));
150 editPaste->setWhatsThis (i18n("Pastes the clipboard contents at the current cursor position into the edit field."));
151
152 editSpeak = actionCollection()->addAction(QLatin1String( "edit_speak" ));
153 editSpeak->setIcon(KIcon( QLatin1String( "speak" )));
154 editSpeak->setText(i18nc("Start speaking", "&Speak"));
155 connect(editSpeak, SIGNAL(triggered(bool)), phraseList, SLOT(speak()));
156 editSpeak->setToolTip(i18n("Speaks the currently active sentence(s)"));
157 editSpeak->setWhatsThis (i18n("Speaks the currently active sentence(s). If there is some text in the edit field it is spoken. Otherwise the selected sentences in the history (if any) are spoken."));
158
159// The "Phrase book" menu
160 phrasebookEdit = actionCollection()->addAction(QLatin1String( "phrasebook_edit" ));
161 phrasebookEdit->setText(i18n("&Edit..."));
162 connect(phrasebookEdit, SIGNAL(triggered(bool)), this, SLOT(slotEditPhrasebook()));
163
164// The "Options" menu
165 viewMenuBar = KStandardAction::showMenubar(this, SLOT(slotViewMenuBar()), actionCollection());
166 // FIXME: Disable so it will compile.
167 // viewToolBar = KStandardAction::showToolbar(this, SLOT(slotViewToolBar()), actionCollection());
168 // viewToolBar->setToolTip(i18n("Enables/disables the toolbar"));
169 // viewToolBar->setWhatsThis (i18n("Enables/disables the toolbar"));
170
171 viewPhrasebookBar = actionCollection()->add<KToggleAction>(QLatin1String( "showPhrasebookBar" ));
172 viewPhrasebookBar->setText(i18n("Show P&hrasebook Bar"));
173 connect(viewPhrasebookBar, SIGNAL(triggered(bool)), this, SLOT(slotViewPhrasebookBar()));
174 viewPhrasebookBar->setToolTip(i18n("Enables/disables the phrasebook bar"));
175 viewPhrasebookBar->setWhatsThis (i18n("Enables/disables the phrasebook bar"));
176
177 viewStatusBar = KStandardAction::showStatusbar(this, SLOT(slotViewStatusBar()), actionCollection());
178 viewStatusBar->setToolTip(i18n("Enables/disables the statusbar"));
179 viewStatusBar->setWhatsThis (i18n("Enables/disables the statusbar"));
180
181 configureTTS = actionCollection()->addAction(QLatin1String( "configureTTS" ));
182 configureTTS->setIcon(KIcon( QLatin1String( "configure" )));
183 configureTTS->setText(i18n("&Configure KMouth..."));
184 connect(configureTTS, SIGNAL(triggered(bool)), this, SLOT(slotConfigureTTS()));
185 configureTTS->setToolTip(i18n("Opens the configuration dialog"));
186 configureTTS->setWhatsThis (i18n("Opens the configuration dialog"));
187
188// The "Help" menu
189 // The "Help" menu will automatically get created.
190
191// The popup menu of the list of spoken sentences
192 phraseListSpeak = actionCollection()->addAction(QLatin1String( "phraselist_speak" ));
193 phraseListSpeak->setIcon(KIcon( QLatin1String( "speak" )));
194 phraseListSpeak->setText(i18n("&Speak"));
195 phraseListSpeak->setToolTip(i18n("Speaks the currently selected phrases in the history"));
196 connect(phraseListSpeak, SIGNAL(triggered(bool)), phraseList, SLOT(speakListSelection()));
197 phraseListSpeak->setWhatsThis (i18n("Speaks the currently selected phrases in the history"));
198
199 phraseListRemove = actionCollection()->addAction(QLatin1String( "phraselist_remove" ));
200 phraseListRemove->setIcon(KIcon( QLatin1String( "edit-delete" )));
201 phraseListRemove->setText(i18n("&Delete"));
202 connect(phraseListRemove, SIGNAL(triggered(bool)), phraseList, SLOT(removeListSelection()));
203 phraseListRemove->setToolTip(i18n("Deletes the currently selected phrases from the history"));
204 phraseListRemove->setWhatsThis (i18n("Deletes the currently selected phrases from the history"));
205
206 phraseListCut = actionCollection()->addAction(QLatin1String( "phraselist_cut" ));
207 phraseListCut->setIcon(KIcon( QLatin1String( "edit-cut" )));
208 phraseListCut->setText(i18n("Cu&t"));
209 connect(phraseListCut, SIGNAL(triggered(bool)), phraseList, SLOT(cutListSelection()));
210 phraseListCut->setToolTip(i18n("Cuts the currently selected phrases from the history and puts them to the clipboard"));
211 phraseListCut->setWhatsThis (i18n("Cuts the currently selected phrases from the history and puts them to the clipboard"));
212
213 phraseListCopy = actionCollection()->addAction(QLatin1String( "phraselist_copy" ));
214 phraseListCopy->setIcon(KIcon( QLatin1String( "edit-copy" )));
215 phraseListCopy->setText(i18n("&Copy"));
216 connect(phraseListCopy, SIGNAL(triggered(bool)), phraseList, SLOT(copyListSelection()));
217 phraseListCut->setToolTip(i18n("Copies the currently selected phrases from the history to the clipboard"));
218 phraseListCut->setWhatsThis (i18n("Copies the currently selected phrases from the history to the clipboard"));
219
220 phraselistSelectAll = actionCollection()->addAction(QLatin1String( "phraselist_select_all" ));
221 phraselistSelectAll->setText(i18n("Select &All Entries"));
222 connect(phraselistSelectAll, SIGNAL(triggered(bool)), phraseList, SLOT(selectAllEntries()));
223 phraselistSelectAll->setToolTip(i18n("Selects all phrases in the history"));
224 phraselistSelectAll->setWhatsThis (i18n("Selects all phrases in the history"));
225
226 phraselistDeselectAll = actionCollection()->addAction(QLatin1String( "phraselist_deselect_all" ));
227 phraselistDeselectAll->setText(i18n("D&eselect All Entries"));
228 connect(phraselistDeselectAll, SIGNAL(triggered(bool)), phraseList, SLOT(deselectAllEntries()));
229 phraselistDeselectAll->setToolTip(i18n("Deselects all phrases in the history"));
230 phraselistDeselectAll->setWhatsThis (i18n("Deselects all phrases in the history"));
231
232// The popup menu of the edit field
233 // The popup menu of the edit field will automatically get created.
234
235 // use the absolute path to your kmouthui.rc file for testing purpose in createGUI();
236 createGUI();
237}
238
239void KMouthApp::initStatusBar()
240{
241 ///////////////////////////////////////////////////////////////////
242 // STATUSBAR
243 // TODO: add your own items you need for displaying current application status.
244 statusBar()->insertItem(i18nc("The job is done", "Ready."), ID_STATUS_MSG);
245}
246
247void KMouthApp::initPhraseList()
248{
249 ////////////////////////////////////////////////////////////////////
250 // create the main widget here that is managed by KTMainWindow's view-region and
251 // connect the widget to your document to display document contents.
252
253 phraseList = new PhraseList(this);
254 setCentralWidget(phraseList);
255}
256
257void KMouthApp::openDocumentFile(const KUrl& url)
258{
259 slotStatusMsg(i18n("Opening file..."));
260
261 phraseList->open (url);
262 slotStatusMsg(i18nc("The job is done", "Ready."));
263}
264
265void KMouthApp::saveOptions() {
266 if (isConfigured) {
267 KConfigGroup cg( config, "General Options");
268 cg.writeEntry("Geometry", size());
269 cg.writeEntry("Show Menubar", viewMenuBar->isChecked());
270 // FIXME: Toolbar disabled so it will compile.
271 // cg.writeEntry("Show Toolbar", viewToolBar->isChecked());
272 cg.writeEntry("Show Phrasebook Bar", viewPhrasebookBar->isChecked());
273 cg.writeEntry("Show Statusbar",viewStatusBar->isChecked());
274 // FIXME: KToolBar no longer has barPos() method.
275 // cg.writeEntry("ToolBarPos", (int) toolBar("mainToolBar")->barPos());
276
277 if (phraseList != 0)
278 phraseList->saveCompletionOptions(config.data());
279 optionsDialog->saveOptions(config.data());
280 cg.changeGroup( "mainToolBar" );
281 toolBar(QLatin1String( "mainToolBar" ))->saveSettings( cg );
282 cg.changeGroup( "phrasebookBar");
283 toolBar(QLatin1String( "phrasebookBar" ))->saveSettings( cg );
284 }
285}
286
287
288void KMouthApp::readOptions()
289{
290 KConfigGroup cg( config, "General Options");
291
292 // bar status settings
293 bool bViewMenubar = cg.readEntry("Show Menubar", true);
294 viewMenuBar->setChecked(bViewMenubar);
295 slotViewMenuBar();
296
297 // FIXME: Toolbar disabled so it will compile.
298 // bool bViewToolbar = cg.readEntry("Show Toolbar", QVariant(true)).toBool();
299 // viewToolBar->setChecked(bViewToolbar);
300 // slotViewToolBar();
301
302 bool bViewPhrasebookbar = cg.readEntry("Show Phrasebook Bar", true);
303 viewPhrasebookBar->setChecked(bViewPhrasebookbar);
304
305 bool bViewStatusbar = cg.readEntry("Show Statusbar", true);
306 viewStatusBar->setChecked(bViewStatusbar);
307 slotViewStatusBar();
308
309 // bar position settings
310 // FIXME:
311 // KToolBar::BarPosition toolBarPos;
312 // toolBarPos=(KToolBar::BarPosition) cg.readEntry("ToolBarPos", int(KToolBar::Top));
313 // toolBar("mainToolBar")->setBarPos(toolBarPos);
314
315 QSize size=cg.readEntry("Geometry",QSize());
316 if(!size.isEmpty())
317 {
318 resize(size);
319 }
320
321 optionsDialog->readOptions(config.data());
322
323 toolBar(QLatin1String( "mainToolBar" ))->applySettings (config->group( "mainToolBar" ) );
324 toolBar(QLatin1String( "phrasebookBar" ))->applySettings (config->group( "phrasebookBar") );
325
326 QString standardBook = KGlobal::dirs()->findResource("appdata", QLatin1String( "standard.phrasebook" ));
327 if (!standardBook.isEmpty()) {
328 PhraseBook book;
329 book.open(KUrl( standardBook ));
330 slotPhrasebookConfirmed(book);
331 }
332 if (phraseList != 0)
333 phraseList->readCompletionOptions(config.data());
334}
335
336bool KMouthApp::queryClose()
337{
338 saveOptions();
339 return true;
340}
341
342void KMouthApp::enableMenuEntries(bool existSelectedEntries, bool existDeselectedEntries) {
343 bool existEntries = existSelectedEntries | existDeselectedEntries;
344 fileSaveAs->setEnabled (existEntries);
345 filePrint->setEnabled (existEntries);
346
347 phraselistSelectAll->setEnabled (existDeselectedEntries);
348
349 phraselistDeselectAll->setEnabled (existSelectedEntries);
350 phraseListSpeak->setEnabled (existSelectedEntries);
351 phraseListRemove->setEnabled (existSelectedEntries);
352 phraseListCut->setEnabled (existSelectedEntries);
353 phraseListCopy->setEnabled (existSelectedEntries);
354}
355
356/////////////////////////////////////////////////////////////////////
357// SLOT IMPLEMENTATION
358/////////////////////////////////////////////////////////////////////
359
360void KMouthApp::slotFileOpen() {
361 slotStatusMsg(i18n("Opening file..."));
362
363 phraseList->open();
364
365 slotStatusMsg(i18nc("The job is done", "Ready."));
366}
367
368void KMouthApp::slotFileSaveAs() {
369 slotStatusMsg(i18n("Saving history with a new filename..."));
370
371 phraseList->save();
372
373 slotStatusMsg(i18nc("The job is done", "Ready."));
374}
375
376void KMouthApp::slotFilePrint()
377{
378 slotStatusMsg(i18n("Printing..."));
379
380 if (printer == 0) {
381 printer = new QPrinter();
382 }
383
384 QPrintDialog *printDialog = KdePrint::createPrintDialog(printer, this);
385
386 if (printDialog->exec())
387 {
388 phraseList->print(printer);
389 }
390
391 slotStatusMsg(i18nc("The job is done", "Ready."));
392}
393
394void KMouthApp::slotFileQuit()
395{
396 slotStatusMsg(i18nc("Shutting down the application", "Exiting..."));
397 saveOptions();
398 // close the first window, the list makes the next one the first again.
399 // This ensures that queryClose() is called on each window to ask for closing
400 KMainWindow* w;
401 if (!memberList().isEmpty())
402 {
403 for (int i = 0; i < memberList().size(); ++i)
404 {
405 // only close the window if the closeEvent is accepted. If the user presses Cancel on the saveModified() dialog,
406 // the window and the application stay open.
407 w = memberList().at(i);
408 if(!w->close())
409 break;
410#ifdef __GNUC__
411#warning "kde4: how remove it ?.???"
412#endif
413 //memberList()->removeRef(w);
414 }
415 }
416}
417
418void KMouthApp::slotEditPhrasebook () {
419 PhraseBookDialog *phraseBookDialog = PhraseBookDialog::get();
420 // As we do not know whether the we are already connected to the slot,
421 // we first disconnect and then connect again.
422 disconnect (phraseBookDialog, SIGNAL(phrasebookConfirmed(PhraseBook&)),
423 this, SLOT(slotPhrasebookConfirmed(PhraseBook&)));
424 connect (phraseBookDialog, SIGNAL(phrasebookConfirmed(PhraseBook&)),
425 this, SLOT(slotPhrasebookConfirmed(PhraseBook&)));
426
427 // As we do not know whether the phrase book edit window is already open,
428 // we first open and then raise it, so that it is surely the top window.
429 phraseBookDialog->show();
430 phraseBookDialog->raise();
431}
432
433void KMouthApp::slotViewMenuBar() {
434 slotStatusMsg(i18n("Toggling menubar..."));
435
436 if(!viewMenuBar->isChecked())
437 menuBar()->hide();
438 else
439 menuBar()->show();
440
441 slotStatusMsg(i18nc("The job is done", "Ready."));
442}
443
444void KMouthApp::slotViewToolBar()
445{
446 slotStatusMsg(i18n("Toggling toolbar..."));
447 ///////////////////////////////////////////////////////////////////
448 // turn Toolbar on or off
449 if(!viewToolBar->isChecked())
450 {
451 toolBar(QLatin1String( "mainToolBar" ))->hide();
452 }
453 else
454 {
455 toolBar(QLatin1String( "mainToolBar" ))->show();
456 }
457
458 slotStatusMsg(i18nc("The job is done", "Ready."));
459}
460
461void KMouthApp::slotViewPhrasebookBar()
462{
463 slotStatusMsg(i18n("Toggling phrasebook bar..."));
464 ///////////////////////////////////////////////////////////////////
465 // turn Toolbar on or off
466 if(!viewPhrasebookBar->isChecked())
467 {
468 toolBar(QLatin1String( "phrasebookBar" ))->hide();
469 }
470 else
471 {
472 toolBar(QLatin1String( "phrasebookBar" ))->show();
473 }
474
475 slotStatusMsg(i18nc("The job is done", "Ready."));
476}
477
478void KMouthApp::slotViewStatusBar()
479{
480 slotStatusMsg(i18n("Toggle the statusbar..."));
481 ///////////////////////////////////////////////////////////////////
482 //turn Statusbar on or off
483 if(!viewStatusBar->isChecked())
484 {
485 statusBar()->hide();
486 }
487 else
488 {
489 statusBar()->show();
490 }
491
492 slotStatusMsg(i18nc("The job is done", "Ready."));
493}
494
495void KMouthApp::slotConfigureTTS() {
496 phraseList->saveWordCompletion();
497 optionsDialog->show();
498}
499
500
501void KMouthApp::slotStatusMsg(const QString &text)
502{
503 ///////////////////////////////////////////////////////////////////
504 // change status message permanently
505 statusBar()->clearMessage();
506 statusBar()->changeItem(text, ID_STATUS_MSG);
507}
508
509void KMouthApp::slotPhrasebookConfirmed (PhraseBook &book) {
510 QString name = QLatin1String( "phrasebooks" );
511 QMenu *popup = (QMenu *)factory()->container(name, this);
512 KToolBar *toolbar = toolBar (QLatin1String( "phrasebookBar" ));
513
514 delete phrases;
515 phrases = new KActionCollection (actionCollection());
516 book.addToGUI (popup, toolbar, phrases, this, SLOT(slotPhraseSelected(QString)));
517
518 QString bookLocation = KGlobal::dirs()->saveLocation ("appdata", QLatin1String( "/" ));
519 if (!bookLocation.isNull() && !bookLocation.isEmpty()) {
520 book.save (KUrl( bookLocation + QLatin1String( "standard.phrasebook" )));
521 }
522}
523
524void KMouthApp::slotConfigurationChanged()
525{
526 optionsDialog->saveOptions (config.data());
527}
528
529void KMouthApp::slotPhraseSelected (const QString &phrase) {
530 phraseList->insert (phrase);
531 if (optionsDialog->isSpeakImmediately())
532 phraseList->speak ();
533}
534
535TextToSpeechSystem *KMouthApp::getTTSSystem() const {
536 return optionsDialog->getTTSSystem();
537}
538
539#include "kmouth.moc"
540