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