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