Added exception and event handling: gui & plugin
[mdictionary] / trunk / src / base / gui / MainWindow.cpp
1 /*******************************************************************************
2
3     This file is part of mDictionary.
4
5     mDictionary is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9
10     mDictionary is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with mDictionary.  If not, see <http://www.gnu.org/licenses/>.
17
18     Copyright 2010 Comarch S.A.
19
20 *******************************************************************************/
21
22 //Created by Mateusz Półrola
23
24 #include "MainWindow.h"
25 #include "ui_MainWindow.h"
26 #include <QtGui>
27 #ifdef Q_WS_MAEMO_5
28     #include <QMaemo5InformationBox>
29 #endif
30
31
32 MainWindow::MainWindow(Backbone *backbone, QWidget *parent):
33     GUIInterface(parent) {
34
35     this->backbone = backbone;
36
37
38     initializeUI();
39
40     connectBackbone();
41     connectSearchBar();
42     connectWordList();
43     connectTranslationWidget();
44     connectDictManager();
45     connectMenu();
46     connectBookmarksWidget();
47
48     setExactSearch(false);
49
50     setWindowTitle("mDictionary");
51
52     showMaximized();
53 }
54
55 MainWindow::~MainWindow() {
56
57 }
58
59
60 void MainWindow::initializeUI() {
61
62     #ifdef Q_WS_MAEMO_5
63         setAttribute(Qt::WA_Maemo5StackedWindow);
64     #endif
65
66     //translationWidget is antoher stacked window, so we don't add it to layout
67     //only create it with this widget as parent
68     translationWidget = new TranslationWidget(this);
69
70
71     mainLayout = new QVBoxLayout;
72     QWidget* w = new QWidget;
73     w->setLayout(mainLayout);
74     setCentralWidget(w);
75     menuBar = new QMenuBar;
76     setMenuBar(menuBar);
77
78     searchBarWidget = new SearchBarWidget;
79
80     wordListWidget = new WordListWidget;
81
82     welcomeScreenWidget = new WelcomeScreenWidget;
83
84
85     #ifdef Q_WS_MAEMO_5
86     //At start we set widget as welcome screen widget
87         mainLayout->addWidget(welcomeScreenWidget);
88         mainLayout->addWidget(searchBarWidget, 0, Qt::AlignBottom);
89     #else
90         translationWidget->hide();
91         //we add to splitter word list and welcome screen
92         splitter = new QSplitter(Qt::Horizontal);
93         splitter->addWidget(wordListWidget);
94         splitter->addWidget(welcomeScreenWidget);
95         splitter->setStretchFactor(1, 150);
96         mainLayout->addWidget(splitter);
97         mainLayout->addWidget(searchBarWidget);
98     #endif
99
100
101     dictManagerWidget = new DictManagerWidget(this);
102     dictManagerWidget->hide();
103
104     settingsWidget = new SettingsWidget(this);
105     settingsWidget->hide();
106
107     bookmarksWidget = new BookmarksWidget(this);
108     bookmarksWidget->hide();
109
110     aboutWidget = new AboutWidget(this);
111     aboutWidget->hide();
112
113     //creating menus
114
115     #ifdef Q_WS_MAEMO_5
116         menuWidget = new MenuWidget(this);
117         menuWidget->addSubMenu(tr("Settings"), settingsWidget);
118         menuWidget->addSubMenu(tr("Dictionaries"), dictManagerWidget);
119         menuWidget->addSubMenu(tr("Bookmarks"), bookmarksWidget);
120         menuWidget->addSubMenu(tr("About"), aboutWidget);
121         menuBar->addAction(menuWidget);
122     #else
123         dictionariesAction = menuBar->addAction(tr("Dictionaries"));
124         connect(dictionariesAction, SIGNAL(triggered()),
125                 dictManagerWidget, SLOT(show()));
126
127         settingsAction = menuBar->addAction(tr("Settings"));
128         connect(settingsAction, SIGNAL(triggered()),
129                 settingsWidget, SLOT(show()));
130
131         QMenu* m = menuBar->addMenu(tr("Bookmarks"));
132         bookmarksShowAllAction = new QAction(tr("Show all"), m);
133
134         bookmarksRemoveAllAction = new QAction(tr("Remove all"), m);
135
136         m->addAction(bookmarksShowAllAction);
137         m->addAction(bookmarksRemoveAllAction);
138
139         aboutAction = menuBar->addAction(tr("About"));
140         connect(aboutAction, SIGNAL(triggered()),
141                 aboutWidget, SLOT(show()));
142     #endif
143 }
144
145 void MainWindow::closeEvent(QCloseEvent *event) {
146     //reqest to stop all searches and close app
147         emit quit();
148         event->accept();
149 }
150
151 bool MainWindow::exactSearch() {
152     return _exactSearch;
153 }
154
155 void MainWindow::setExactSearch(bool exact) {
156     _exactSearch = exact;
157 }
158
159 void MainWindow::setSearchString(QString word) {
160     searchString = word;
161 }
162
163 void MainWindow::wordListReady() {
164     //gets results from backbone
165     QMultiHash<QString, Translation*> res = backbone->result();
166     QHash<QString, QList<Translation*> > searchResult;
167
168     #ifdef Q_WS_MAEMO_5
169     //switch welcome screen with word list
170     if(!wordListWidget->isVisible()) {
171         int i = mainLayout->indexOf(welcomeScreenWidget);
172         QBoxLayout* l = (QBoxLayout*)(mainLayout);
173         l->removeWidget(welcomeScreenWidget);
174         welcomeScreenWidget->deleteLater();
175         l->insertWidget(0, wordListWidget);
176     }
177     #endif
178
179     //if nothing was found
180     if(res.count() == 0) {
181         showNotify(Notify::Info, tr("Can't find any matching words"));
182
183         //show empty list to remove results of old search
184         emit showWordList(searchResult);
185     }
186     else {
187         //find translations of the same key word
188         QMultiHash<QString, Translation*>::iterator i;
189         for(i = res.begin(); i != res.end(); i++) {
190             searchResult[i.key()].push_back(i.value());
191         }
192
193
194         if(!exactSearch()) {
195             emit showWordList(searchResult);
196         }
197         else {
198             #ifndef Q_WS_MAEMO_5
199             //on desktop we show word list in exact search
200                 emit showWordList(searchResult);
201             #endif
202             bool foundExactMatch = false;
203             QHash<QString, QList<Translation*> >::iterator j;
204             for(j = searchResult.begin(); j != searchResult.end(); j++) {
205                 if(j.key() == searchString && !foundExactMatch) {
206                     foundExactMatch = true;
207                     emit searchTranslations(j.value());
208                     break;
209                 }
210             }
211
212             if(!foundExactMatch) {
213                 showNotify(Notify::Info,
214                            tr("Can't find exactly matching word"));
215
216                 emit showWordList(searchResult);
217             }
218
219         }
220     }
221     setExactSearch(false);
222 }
223
224 void MainWindow::translationsReady() {
225     #ifndef Q_WS_MAEMO_5
226     //switch welcome screen with translation widget
227     if(!translationWidget->isVisible()) {
228         QBoxLayout* l = (QBoxLayout*)(mainLayout);
229         QSplitter* s = (QSplitter*)((QWidgetItem*)(l->itemAt(0))->widget());
230         s->insertWidget(1,translationWidget);
231         s->setStretchFactor(1, 150);
232         welcomeScreenWidget->deleteLater();
233     }
234     #endif
235
236     emit showTranslation(backbone->htmls());
237 }
238
239 QList<CommonDictInterface*> MainWindow::getPlugins() {
240     return backbone->getPlugins();
241 }
242
243 QHash<CommonDictInterface*, bool> MainWindow::getDictionaries() {
244     return backbone->getDictionaries();
245 }
246
247
248 void MainWindow::search(QString word) {
249     setExactSearch(false);
250     searchBarWidget->search(word);
251 }
252
253 void MainWindow::searchExact(QString word) {
254     setExactSearch(true);
255     //searching with searchBar, not directly by emiting searchWordList(),
256     //because it will set search word in searchBar's edit line
257     //this function is only used by history and when searching from attributes
258     searchBarWidget->search(word);
259 }
260
261
262
263 void MainWindow::breakSearching() {
264     //make sure to unset exact search mode
265     setExactSearch(false);
266 }
267
268 void MainWindow::addToHistory(QList<Translation *> trans) {
269     if(trans.count() > 0) {
270         backbone->history()->add(trans[0]->key());
271     }
272 }
273
274 void MainWindow::historyNext() {
275     if(backbone->history()->nextAvailable()) {
276         QString next = backbone->history()->next();
277         #ifndef Q_WS_MAEMO_5
278             setExactSearch(true);
279         #endif
280         searchBarWidget->searchDelay(next);
281     }
282 }
283
284 void MainWindow::historyPrev() {
285     if(backbone->history()->prevAvailable()) {
286         #ifndef Q_WS_MAEMO_5
287             setExactSearch(true);
288         #endif
289         QString prev = backbone->history()->previous();
290         searchBarWidget->searchDelay(prev);
291     }
292 }
293
294 void MainWindow::disableMenu() {
295     #ifdef Q_WS_MAEMO_5
296         if(menuBar->actions().contains(menuWidget)) {
297               menuBar->removeAction(menuWidget);
298         }
299     #else
300         menuBar->setEnabled(false);
301     #endif
302 }
303
304 void MainWindow::enableMenu() {
305     #ifdef Q_WS_MAEMO_5
306         if(!menuBar->actions().contains(menuWidget)) {
307             menuBar->addAction(menuWidget);
308         }
309     #else
310         menuBar->setEnabled(true);
311     #endif
312 }
313
314 void MainWindow::showHistory() {
315     HistoryListDialog historyDialog(backbone->history()->list(), this);
316     if(historyDialog.exec() == QDialog::Accepted) {
317         backbone->history()->setCurrentElement(historyDialog.selectedRow());
318         searchExact(historyDialog.selectedWord());
319     }
320 }
321
322 void MainWindow::setSettings(Settings *s) {
323     backbone->setSettings(s);
324 }
325
326 Settings* MainWindow::settings() {
327     return backbone->settings();
328 }
329
330
331 void MainWindow::showNotify(Notify::NotifyType type, QString text) {
332
333     switch(type) {
334     case Notify::Info:
335         #ifdef Q_WS_MAEMO_5
336             QMaemo5InformationBox::information(this,
337                                 text,
338                                 QMaemo5InformationBox::DefaultTimeout);
339         #else
340             QMessageBox::information(this, "Information", text);
341         #endif
342         break;
343
344     case Notify::Warning:
345         qDebug() << text;
346         #ifndef Q_WS_MAEMO_5
347                 QMessageBox::warning(this, "Warning", text);
348                 break;
349         #else
350             QMessageBox::information(this, "Warning", text);
351         #endif
352
353     case Notify::Error:
354         #ifdef Q_WS_MAEMO_5
355             QMaemo5InformationBox::information(this,
356                                 text,
357                                 QMaemo5InformationBox::NoTimeout);
358         #else
359             QMessageBox::critical(this, "Error", text);
360         #endif
361         break;
362     }
363 }
364
365 void MainWindow::connectBackbone() {
366     connect(this, SIGNAL(quit()),
367             backbone, SLOT(quit()));
368
369     connect(this, SIGNAL(searchWordList(QString)),
370             backbone, SLOT(search(QString)));
371
372     connect(this, SIGNAL(searchTranslations(QList<Translation*>)),
373             backbone, SLOT(searchHtml(QList<Translation*>)));
374
375     connect(this, SIGNAL(stopSearching()),
376             backbone, SLOT(stopSearching()));
377
378     connect(this, SIGNAL(stopSearching()),
379             this, SLOT(breakSearching()));
380
381     connect(this, SIGNAL(addNewDictionary(CommonDictInterface*)),
382             backbone, SLOT(addDictionary(CommonDictInterface*)));
383
384     connect(this, SIGNAL(removeDictionary(CommonDictInterface*)),
385             backbone, SLOT(removeDictionary(CommonDictInterface*)));
386
387     connect(this, SIGNAL(selectedDictionaries(QList<CommonDictInterface*>)),
388             backbone, SLOT(selectedDictionaries(QList<CommonDictInterface*>)));
389
390
391     connect(backbone, SIGNAL(ready()),
392             this, SIGNAL(setIdle()));
393
394     connect(backbone, SIGNAL(htmlReady()),
395             this, SIGNAL(setIdle()));
396
397
398     connect(backbone, SIGNAL(ready()),
399             this, SLOT(wordListReady()));
400
401     connect(backbone, SIGNAL(htmlReady()),
402             this, SLOT(translationsReady()));
403
404     connect(backbone, SIGNAL(searchCanceled()),
405             this, SIGNAL(setIdle()));
406
407     connect(backbone, SIGNAL(notify(Notify::NotifyType,QString)),
408             this, SLOT(showNotify(Notify::NotifyType,QString)));
409
410
411
412
413     connect(this, SIGNAL(searchWordList(QString)),
414             this, SIGNAL(setBusy()));
415
416     connect(this, SIGNAL(searchTranslations(QList<Translation*>)),
417             this, SIGNAL(setBusy()));
418
419     connect(this, SIGNAL(stopSearching()),
420             this, SIGNAL(setIdle()));
421
422     connect(this, SIGNAL(searchWordList(QString)),
423             this, SLOT(setSearchString(QString)));
424
425     connect(this, SIGNAL(searchTranslations(QList<Translation*>)),
426             this, SLOT(addToHistory(QList<Translation*>)));
427
428
429 }
430
431 void MainWindow::connectSearchBar() {
432     connect(searchBarWidget, SIGNAL(searchForTranslations(QString)),
433             this, SIGNAL(searchWordList(QString)));
434
435     connect(searchBarWidget, SIGNAL(stopSearching()),
436             this, SIGNAL(stopSearching()));
437
438     connect(this, SIGNAL(setBusy()),
439             searchBarWidget, SLOT(setBusy()));
440
441     connect(this, SIGNAL(setIdle()),
442             searchBarWidget, SLOT(setIdle()));
443
444     connect(searchBarWidget, SIGNAL(historyNext()),
445             this, SLOT(historyNext()));
446
447     connect(searchBarWidget, SIGNAL(historyPrev()),
448             this, SLOT(historyPrev()));
449
450     connect(searchBarWidget, SIGNAL(historyShow()),
451             this, SLOT(showHistory()));
452
453     connect(searchBarWidget, SIGNAL(refreshHistoryButtons()),
454             backbone->history(), SLOT(refreshStatus()));
455
456     connect(backbone->history(), SIGNAL(historyChanged(bool,bool,bool)),
457             searchBarWidget, SLOT(updateHistoryButtons(bool,bool,bool)));
458 }
459
460 void MainWindow::connectWordList() {
461     connect(this,
462             SIGNAL(showWordList(QHash<QString, QList<Translation*> >)),
463             wordListWidget,
464             SLOT(showSearchResults(QHash<QString,QList<Translation*> >)));
465
466     connect(wordListWidget, SIGNAL(showTranslation(QList<Translation*>)),
467             this, SIGNAL(searchTranslations(QList<Translation*>)));
468
469
470
471
472     connect(this, SIGNAL(setBusy()),
473             wordListWidget, SLOT(lockList()));
474
475     connect(this, SIGNAL(setIdle()),
476             wordListWidget, SLOT(unlockList()));
477
478     connect(wordListWidget, SIGNAL(addBookmark(QList<Translation*>)),
479             backbone, SLOT(addBookmark(QList<Translation*>)));
480
481     connect(wordListWidget, SIGNAL(removeBookmark(QList<Translation*>)),
482             backbone, SLOT(removeBookmark(QList<Translation*>)));
483 }
484
485 void MainWindow::connectTranslationWidget() {
486     connect(this, SIGNAL(showTranslation(QStringList)),
487             translationWidget, SLOT(show(QStringList)));
488
489      #ifdef Q_WS_MAEMO_5
490         connect(translationWidget, SIGNAL(search(QString)),
491                 this, SLOT(search(QString)));
492     #else
493         connect(translationWidget, SIGNAL(search(QString)),
494                 this, SLOT(searchExact(QString)));
495     #endif
496
497
498 }
499
500 void MainWindow::connectDictManager() {
501     connect(dictManagerWidget, SIGNAL(addDictionary(CommonDictInterface*)),
502             this, SIGNAL(addNewDictionary(CommonDictInterface*)));
503
504     connect(dictManagerWidget, SIGNAL(removeDictionary(CommonDictInterface*)),
505             this, SIGNAL(removeDictionary(CommonDictInterface*)));
506
507     connect(dictManagerWidget,
508             SIGNAL(selectedDictionaries(QList<CommonDictInterface*>)),
509             this, SIGNAL(selectedDictionaries(QList<CommonDictInterface*>)));
510 }
511
512 void MainWindow::connectMenu() {
513     connect(this, SIGNAL(setBusy()),
514             this, SLOT(disableMenu()));
515
516     connect(this, SIGNAL(setIdle()),
517             this, SLOT(enableMenu()));
518 }
519
520
521 void MainWindow::connectBookmarksWidget() {
522     #ifdef Q_WS_MAEMO_5
523         //after removing bookmarks we search for it once again to clear word list
524         connect(bookmarksWidget, SIGNAL(removeAllBookmarks()),
525                 backbone, SLOT(removeAllBookmark()));
526
527         connect(bookmarksWidget, SIGNAL(removeAllBookmarks()),
528                 backbone, SLOT(fetchBookmarks()));
529
530
531         connect(bookmarksWidget, SIGNAL(showAllBookmarks()),
532                 menuWidget, SLOT(hideMenu()));
533
534         connect(bookmarksWidget, SIGNAL(showAllBookmarks()),
535                 backbone, SLOT(fetchBookmarks()));
536
537
538     #else
539         connect(bookmarksShowAllAction, SIGNAL(triggered()),
540                 backbone, SLOT(fetchBookmarks()));
541
542         connect(bookmarksRemoveAllAction, SIGNAL(triggered()),
543                 backbone, SLOT(removeAllBookmark()));
544
545         connect(bookmarksRemoveAllAction, SIGNAL(triggered()),
546                 backbone, SLOT(fetchBookmarks()));
547     #endif
548 }