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