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