In settings widget on maemo add info button next to spin boxes
[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     connect(settingsWidget, SIGNAL(notify(Notify::NotifyType,QString)),
164             this, SLOT(showNotification(Notify::NotifyType,QString)));
165
166     bookmarksWidget = new BookmarksWidget(this);
167     bookmarksWidget->hide();
168
169     aboutWidget = new AboutWidget(this);
170     aboutWidget->hide();
171 }
172
173 void MainWindow::closeEvent(QCloseEvent *event) {
174     //request to stop all searches and close app
175     Q_EMIT quit();
176     event->accept();
177 }
178
179 bool MainWindow::isInExactSearch() {
180     return _exactSearch;
181 }
182
183 void MainWindow::setExactSearch(bool exact) {
184     _exactSearch = exact;
185 }
186
187 void MainWindow::setExactSearchString(QString word) {
188     searchString = word;
189 }
190
191 void MainWindow::wordListReady() {
192     //gets results from backbone
193     QMultiHash<QString, Translation*> backboneResult = backbone->result();
194     QHash<QString, QList<Translation*> > searchResult;
195
196     #ifdef Q_WS_MAEMO_5
197         hideWelcomeScreen();
198     #endif
199
200     //if nothing was found
201     if(backboneResult.count() == 0) {
202         showNotification(Notify::Info, tr("Can't find any matching words"));
203
204         //show empty list to remove results of old search
205         Q_EMIT showWordList(searchResult);
206     }
207     else {
208         //find translations of the same key word
209         QMultiHash<QString, Translation*>::iterator i;
210         for(i = backboneResult.begin(); i != backboneResult.end(); i++) {
211             searchResult[i.key()].push_back(i.value());
212         }
213
214         //show search results
215         Q_EMIT showWordList(searchResult);
216
217
218         if(isInExactSearch()) {
219             QList<Translation*> exactTranslation;
220             if(checkExactSearch(searchResult, exactTranslation)) {
221                 Q_EMIT searchTranslations(exactTranslation);
222             }
223             else {
224                 showNotification(Notify::Info,
225                            tr("Can't find exactly matching word"));
226             }
227
228             setExactSearch(false);
229         }
230     }
231 }
232
233 bool MainWindow::checkExactSearch(
234         QHash<QString, QList<Translation *> > searchResult,
235         QList<Translation *> &found) {
236
237     bool foundExactMatch = false;
238     QHash<QString, QList<Translation*> >::iterator j;
239     for(j = searchResult.begin(); j != searchResult.end(); j++) {
240         if(j.key().toLower() == searchString.toLower()
241             && !foundExactMatch) {
242             found = j.value();
243             return true;
244         }
245     }
246     return false;
247 }
248
249 void MainWindow::translationsReady() {
250     #ifndef Q_WS_MAEMO_5
251         hideWelcomeScreen();
252     #endif
253
254     Q_EMIT showTranslation(backbone->htmls());
255     notifyManager->screenChanged();
256 }
257
258
259 void MainWindow::hideWelcomeScreen() {
260 #ifdef Q_WS_MAEMO_5
261     //switch welcome screen with word list
262     if(!wordListWidget->isVisible()) {
263         mainLayout->removeWidget(welcomeScreenWidget);
264         welcomeScreenWidget->deleteLater();
265
266         mainLayout->insertWidget(0, wordListWidget);
267     }
268 #else
269     //switch welcome screen with translation widget
270     if(!translationWidget->isVisible()) {
271         splitter->insertWidget(1,translationWidget);
272         splitter->setStretchFactor(1, 150);
273         welcomeScreenWidget->deleteLater();
274     }
275 #endif
276 }
277
278 QList<CommonDictInterface*> MainWindow::getPlugins() {
279     return backbone->getPlugins();
280 }
281
282 QHash<CommonDictInterface*, bool> MainWindow::getDictionaries() {
283     return backbone->getDictionaries();
284 }
285
286
287 void MainWindow::search(QString word) {
288     setExactSearch(false);
289     searchBarWidget->search(word);
290 }
291
292 void MainWindow::searchExact(QString word) {
293     setExactSearch(true);
294     searchBarWidget->search(word);
295 }
296
297 void MainWindow::searchDelay(QString word) {
298     searchBarWidget->searchDelay(word);
299 }
300
301
302
303
304
305 void MainWindow::searchingInterrupted() {
306     //make sure to unset exact search mode
307     setExactSearch(false);
308 }
309
310 void MainWindow::addToHistory(QList<Translation *> trans) {
311     if(trans.count() > 0) {
312         backbone->history()->add(trans[0]->key());
313     }
314 }
315
316 void MainWindow::historyNext() {
317     if(backbone->history()->nextAvailable()) {
318         QString next = backbone->history()->next();
319         #ifndef Q_WS_MAEMO_5
320             setExactSearch(true);
321         #endif
322         searchDelay(next);
323     }
324 }
325
326 void MainWindow::historyPrev() {
327     if(backbone->history()->prevAvailable()) {
328         #ifndef Q_WS_MAEMO_5
329             setExactSearch(true);
330         #endif
331         QString prev = backbone->history()->previous();
332         searchDelay(prev);
333     }
334 }
335
336 void MainWindow::disableMenu() {
337     #ifdef Q_WS_MAEMO_5
338         if(menuBar->actions().contains(menuWidget)) {
339               menuBar->removeAction(menuWidget);
340         }
341     #else
342         menuBar->setEnabled(false);
343     #endif
344 }
345
346 void MainWindow::enableMenu() {
347     #ifdef Q_WS_MAEMO_5
348         if(!menuBar->actions().contains(menuWidget)) {
349             menuBar->addAction(menuWidget);
350         }
351     #else
352         menuBar->setEnabled(true);
353     #endif
354 }
355
356 void MainWindow::showHistory(QPoint p) {
357
358     HistoryListDialog historyDialog(backbone->history()->list(), searchBarWidget);
359
360     #ifndef Q_WS_MAEMO_5
361         QPoint newPos = mapFromGlobal(p);
362         newPos.setY(searchBarWidget->pos().y() -
363                     historyDialog.sizeHint().height());
364         newPos.setX(width() - historyDialog.sizeHint().width());
365
366         historyDialog.move(newPos);
367     #endif
368
369     if(historyDialog.exec() == QDialog::Accepted) {
370         backbone->history()->setCurrentElement(historyDialog.selectedRow());
371         searchExact(historyDialog.selectedWord());
372     }
373 }
374
375 void MainWindow::setSettings(Settings *s) {
376     backbone->setSettings(s);
377 }
378
379 Settings* MainWindow::settings() {
380     return backbone->settings();
381 }
382
383
384 void MainWindow::showNotification(Notify::NotifyType type, QString text) {
385     notifyManager->showNotification(type, text);
386 }
387
388 void MainWindow::connectBackbone() {
389
390     connect(this, SIGNAL(searchWordList(QString)),
391             this, SIGNAL(setBusy()));
392
393     connect(this, SIGNAL(searchTranslations(QList<Translation*>)),
394             this, SIGNAL(setBusy()));
395
396     connect(this, SIGNAL(stopSearching()),
397             this, SIGNAL(setIdle()));
398
399     connect(this, SIGNAL(searchWordList(QString)),
400             this, SLOT(setExactSearchString(QString)));
401
402     connect(this, SIGNAL(searchTranslations(QList<Translation*>)),
403             this, SLOT(addToHistory(QList<Translation*>)));
404
405
406
407     connect(this, SIGNAL(quit()),
408             backbone, SLOT(quit()));
409
410     connect(this, SIGNAL(searchWordList(QString)),
411             backbone, SLOT(search(QString)));
412
413     connect(this, SIGNAL(searchTranslations(QList<Translation*>)),
414             backbone, SLOT(searchHtml(QList<Translation*>)));
415
416     connect(this, SIGNAL(stopSearching()),
417             backbone, SLOT(stopSearching()));
418
419     connect(this, SIGNAL(stopSearching()),
420             this, SLOT(searchingInterrupted()));
421
422     connect(this, SIGNAL(addNewDictionary(CommonDictInterface*)),
423             backbone, SLOT(addDictionary(CommonDictInterface*)));
424
425     connect(this, SIGNAL(removeDictionary(CommonDictInterface*)),
426             backbone, SLOT(removeDictionary(CommonDictInterface*)));
427
428     connect(this, SIGNAL(selectedDictionaries(QList<CommonDictInterface*>)),
429             backbone, SLOT(selectedDictionaries(QList<CommonDictInterface*>)));
430
431
432     connect(backbone, SIGNAL(ready()),
433             this, SIGNAL(setIdle()));
434
435     connect(backbone, SIGNAL(htmlReady()),
436             this, SIGNAL(setIdle()));
437
438
439     connect(backbone, SIGNAL(ready()),
440             this, SLOT(wordListReady()));
441
442     connect(backbone, SIGNAL(htmlReady()),
443             this, SLOT(translationsReady()));
444
445     connect(backbone, SIGNAL(searchCanceled()),
446             this, SIGNAL(setIdle()));
447
448     connect(backbone, SIGNAL(notify(Notify::NotifyType,QString)),
449             this, SLOT(showNotification(Notify::NotifyType,QString)));
450 }
451
452 void MainWindow::connectSearchBar() {
453     connect(searchBarWidget, SIGNAL(searchForTranslations(QString)),
454             this, SIGNAL(searchWordList(QString)));
455
456     connect(searchBarWidget, SIGNAL(stopSearching()),
457             this, SIGNAL(stopSearching()));
458
459     connect(this, SIGNAL(setBusy()),
460             searchBarWidget, SLOT(setBusy()));
461
462     connect(this, SIGNAL(setIdle()),
463             searchBarWidget, SLOT(setIdle()));
464
465     connect(searchBarWidget, SIGNAL(historyNext()),
466             this, SLOT(historyNext()));
467
468     connect(searchBarWidget, SIGNAL(historyPrev()),
469             this, SLOT(historyPrev()));
470
471     connect(searchBarWidget, SIGNAL(historyShow(QPoint)),
472             this, SLOT(showHistory(QPoint)));
473
474     connect(searchBarWidget, SIGNAL(refreshHistoryButtons()),
475             backbone->history(), SLOT(refreshStatus()));
476
477     connect(backbone->history(), SIGNAL(historyChanged(bool,bool,bool)),
478             searchBarWidget, SLOT(updateHistoryButtons(bool,bool,bool)));
479 }
480
481 void MainWindow::connectWordList() {
482     connect(this,
483             SIGNAL(showWordList(QHash<QString, QList<Translation*> >)),
484             wordListWidget,
485             SLOT(showSearchResults(QHash<QString,QList<Translation*> >)));
486
487     connect(wordListWidget, SIGNAL(showTranslation(QList<Translation*>)),
488             this, SIGNAL(searchTranslations(QList<Translation*>)));
489
490
491
492
493     connect(this, SIGNAL(setBusy()),
494             wordListWidget, SLOT(lockList()));
495
496     connect(this, SIGNAL(setIdle()),
497             wordListWidget, SLOT(unlockList()));
498
499     connect(wordListWidget, SIGNAL(addBookmark(QList<Translation*>)),
500             backbone, SLOT(addBookmark(QList<Translation*>)));
501
502     connect(wordListWidget, SIGNAL(removeBookmark(QList<Translation*>)),
503             backbone, SLOT(removeBookmark(QList<Translation*>)));
504 }
505
506 void MainWindow::connectTranslationWidget() {
507     connect(this, SIGNAL(showTranslation(QStringList)),
508             translationWidget, SLOT(show(QStringList)));
509
510      #ifdef Q_WS_MAEMO_5
511         connect(translationWidget, SIGNAL(search(QString)),
512                 this, SLOT(search(QString)));
513     #else
514         connect(translationWidget, SIGNAL(search(QString)),
515                 this, SLOT(searchExact(QString)));
516     #endif
517
518
519 }
520
521 void MainWindow::connectDictManager() {
522     connect(dictManagerWidget, SIGNAL(addDictionary(CommonDictInterface*)),
523             this, SIGNAL(addNewDictionary(CommonDictInterface*)));
524
525     connect(dictManagerWidget, SIGNAL(removeDictionary(CommonDictInterface*)),
526             this, SIGNAL(removeDictionary(CommonDictInterface*)));
527
528     connect(dictManagerWidget,
529             SIGNAL(selectedDictionaries(QList<CommonDictInterface*>)),
530             this, SIGNAL(selectedDictionaries(QList<CommonDictInterface*>)));
531 }
532
533 void MainWindow::connectMenu() {
534     connect(this, SIGNAL(setBusy()),
535             this, SLOT(disableMenu()));
536
537     connect(this, SIGNAL(setIdle()),
538             this, SLOT(enableMenu()));
539 }
540
541
542 void MainWindow::connectBookmarksWidget() {
543     #ifdef Q_WS_MAEMO_5
544         //after removing bookmarks we search for them once again to clear word list
545         connect(bookmarksWidget, SIGNAL(removeAllBookmarks()),
546                 this, SLOT(removeBookmarks()));
547
548
549         connect(bookmarksWidget, SIGNAL(showAllBookmarks()),
550                 menuWidget, SLOT(hideMenu()));
551
552         connect(bookmarksWidget, SIGNAL(showAllBookmarks()),
553                 backbone, SLOT(fetchBookmarks()));
554
555
556     #else
557         connect(bookmarksRemoveAllAction, SIGNAL(triggered()),
558                 this, SLOT(removeBookmarks()));
559         connect(bookmarksShowAllAction, SIGNAL(triggered()),
560                 backbone, SLOT(fetchBookmarks()));
561
562     #endif
563 }
564
565
566 void MainWindow::removeBookmarks() {
567     QWidget* par;
568     #ifdef Q_WS_MAEMO_5
569         par = bookmarksWidget;
570     #else
571         par = this;
572     #endif
573     if(QMessageBox::question(par, tr("Delete all bookmarks"),
574              tr("Do you want to delete all bookmarks? (This action cannot be revoked)"),
575              QMessageBox::Yes, QMessageBox::Cancel) == QMessageBox::Yes) {
576         backbone->removeAllBookmarks();
577         if(searchString.size())
578             backbone->search(searchString);
579
580     }
581 }