Added css for desktop
[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
236 bool MainWindow::checkExactSearch(
237         QHash<QString, QList<Translation *> > searchResult,
238         QList<Translation *> &found) {
239
240     bool foundExactMatch = false;
241     QHash<QString, QList<Translation*> >::iterator j;
242     for(j = searchResult.begin(); j != searchResult.end(); j++) {
243         if(j.key().toLower() == searchString.toLower()
244             && !foundExactMatch) {
245             found = j.value();
246             return true;
247         }
248     }
249     return false;
250 }
251
252 void MainWindow::translationsReady() {
253     #ifndef Q_WS_MAEMO_5
254         hideWelcomeScreen();
255     #endif
256
257     Q_EMIT showTranslation(backbone->xmls());
258     #ifdef Q_WS_MAEMO_5
259         notifyManager->screenChanged();
260     #endif
261 }
262
263
264 void MainWindow::hideWelcomeScreen() {
265 #ifdef Q_WS_MAEMO_5
266     //switch welcome screen with word list
267     if(!wordListWidget->isVisible()) {
268         mainLayout->removeWidget(welcomeScreenWidget);
269         welcomeScreenWidget->deleteLater();
270
271         mainLayout->insertWidget(0, wordListWidget);
272     }
273 #else
274     //switch welcome screen with translation widget
275     if(!translationWidget->isVisible()) {
276         splitter->insertWidget(1,translationWidget);
277         splitter->setStretchFactor(1, 150);
278         welcomeScreenWidget->deleteLater();
279     }
280 #endif
281 }
282
283 QList<CommonDictInterface*> MainWindow::getPlugins() {
284     return backbone->getPlugins();
285 }
286
287 QHash<CommonDictInterface*, bool> MainWindow::getDictionaries() {
288     return backbone->getDictionaries();
289 }
290
291
292 void MainWindow::search(QString word) {
293     setExactSearch(false);
294     searchBarWidget->search(word);
295     #ifdef Q_WS_MAEMO_5
296     if(translationWidget->isVisible()) {
297             translationWidget->hide();
298             update();
299         }
300     #endif
301 }
302
303 void MainWindow::searchExact(QString word) {
304     setExactSearch(true);
305     searchBarWidget->search(word);
306 }
307
308 void MainWindow::searchDelay(QString word) {
309     searchBarWidget->searchDelay(word);
310 }
311
312
313
314
315
316 void MainWindow::searchingInterrupted() {
317     //make sure to unset exact search mode
318     setExactSearch(false);
319 }
320
321 void MainWindow::addToHistory(QList<Translation *> trans) {
322     if(trans.count() > 0) {
323         backbone->history()->add(trans[0]->key());
324     }
325 }
326
327 void MainWindow::historyNext() {
328     if(backbone->history()->nextAvailable()) {
329         QString next = backbone->history()->next();
330         #ifndef Q_WS_MAEMO_5
331             setExactSearch(true);
332         #endif
333         searchDelay(next);
334     }
335 }
336
337 void MainWindow::historyPrev() {
338     if(backbone->history()->prevAvailable()) {
339         #ifndef Q_WS_MAEMO_5
340             setExactSearch(true);
341         #endif
342         QString prev = backbone->history()->previous();
343         searchDelay(prev);
344     }
345 }
346
347 void MainWindow::disableMenu() {
348     #ifdef Q_WS_MAEMO_5
349         if(menuBar->actions().contains(menuWidget)) {
350               menuBar->removeAction(menuWidget);
351         }
352     #else
353         menuBar->setEnabled(false);
354     #endif
355 }
356
357 void MainWindow::enableMenu() {
358     #ifdef Q_WS_MAEMO_5
359         if(!menuBar->actions().contains(menuWidget)) {
360             menuBar->addAction(menuWidget);
361         }
362     #else
363         menuBar->setEnabled(true);
364     #endif
365 }
366
367 void MainWindow::showHistory(QPoint p) {
368
369     HistoryListDialog historyDialog(backbone->history()->list(), searchBarWidget);
370
371     #ifndef Q_WS_MAEMO_5
372         QPoint newPos = mapFromGlobal(p);
373         newPos.setY(searchBarWidget->pos().y() -
374                     historyDialog.sizeHint().height());
375         newPos.setX(width() - historyDialog.sizeHint().width());
376
377         historyDialog.move(newPos);
378     #endif
379
380     if(historyDialog.exec() == QDialog::Accepted) {
381         backbone->history()->setCurrentElement(historyDialog.selectedRow());
382         searchExact(historyDialog.selectedWord());
383     }
384 }
385
386 void MainWindow::setSettings(Settings *s) {
387     backbone->setSettings(s);
388 }
389
390 Settings* MainWindow::settings() {
391     return backbone->settings();
392 }
393
394
395 void MainWindow::showNotification(Notify::NotifyType type, QString text) {
396     notifyManager->showNotification(type, text);
397 }
398
399 void MainWindow::connectBackbone() {
400
401     connect(this, SIGNAL(searchWordList(QString)),
402             this, SIGNAL(setBusy()));
403
404     connect(this, SIGNAL(searchTranslations(QList<Translation*>)),
405             this, SIGNAL(setBusy()));
406
407     connect(this, SIGNAL(stopSearching()),
408             this, SIGNAL(setIdle()));
409
410     connect(this, SIGNAL(searchWordList(QString)),
411             this, SLOT(setExactSearchString(QString)));
412
413     connect(this, SIGNAL(searchTranslations(QList<Translation*>)),
414             this, SLOT(addToHistory(QList<Translation*>)));
415
416
417
418     connect(this, SIGNAL(quit()),
419             backbone, SLOT(quit()));
420
421     connect(this, SIGNAL(searchWordList(QString)),
422             backbone, SLOT(search(QString)));
423
424     connect(this, SIGNAL(searchTranslations(QList<Translation*>)),
425             backbone, SLOT(searchXml(QList<Translation*>)));
426
427     connect(this, SIGNAL(stopSearching()),
428             backbone, SLOT(stopSearching()));
429
430     connect(this, SIGNAL(stopSearching()),
431             this, SLOT(searchingInterrupted()));
432
433     connect(this, SIGNAL(addNewDictionary(CommonDictInterface*)),
434             backbone, SLOT(addDictionary(CommonDictInterface*)));
435
436     connect(this, SIGNAL(removeDictionary(CommonDictInterface*)),
437             backbone, SLOT(removeDictionary(CommonDictInterface*)));
438
439     connect(this, SIGNAL(selectedDictionaries(QList<CommonDictInterface*>)),
440             backbone, SLOT(selectedDictionaries(QList<CommonDictInterface*>)));
441
442
443     connect(backbone, SIGNAL(ready()),
444             this, SIGNAL(setIdle()));
445
446     connect(backbone, SIGNAL(xmlReady()),
447             this, SIGNAL(setIdle()));
448
449
450     connect(backbone, SIGNAL(ready()),
451             this, SLOT(wordListReady()));
452
453     connect(backbone, SIGNAL(xmlReady()),
454             this, SLOT(translationsReady()));
455
456     connect(backbone, SIGNAL(searchCanceled()),
457             this, SIGNAL(setIdle()));
458
459     connect(backbone, SIGNAL(notify(Notify::NotifyType,QString)),
460             this, SLOT(showNotification(Notify::NotifyType,QString)));
461
462     connect(backbone, SIGNAL(closeOk()),
463             this, SLOT(close()));
464 }
465
466 void MainWindow::connectSearchBar() {
467     connect(searchBarWidget, SIGNAL(searchForTranslations(QString)),
468             this, SIGNAL(searchWordList(QString)));
469
470     connect(searchBarWidget, SIGNAL(stopSearching()),
471             this, SIGNAL(stopSearching()));
472
473     connect(this, SIGNAL(setBusy()),
474             searchBarWidget, SLOT(setBusy()));
475
476     connect(this, SIGNAL(setIdle()),
477             searchBarWidget, SLOT(setIdle()));
478
479     connect(searchBarWidget, SIGNAL(historyNext()),
480             this, SLOT(historyNext()));
481
482     connect(searchBarWidget, SIGNAL(historyPrev()),
483             this, SLOT(historyPrev()));
484
485     connect(searchBarWidget, SIGNAL(historyShow(QPoint)),
486             this, SLOT(showHistory(QPoint)));
487
488     connect(searchBarWidget, SIGNAL(refreshHistoryButtons()),
489             backbone->history(), SLOT(refreshStatus()));
490
491     connect(backbone->history(), SIGNAL(historyChanged(bool,bool,bool)),
492             searchBarWidget, SLOT(updateHistoryButtons(bool,bool,bool)));
493 }
494
495 void MainWindow::connectWordList() {
496     connect(this,
497             SIGNAL(showWordList(QHash<QString, QList<Translation*> >)),
498             wordListWidget,
499             SLOT(showSearchResults(QHash<QString,QList<Translation*> >)));
500
501     connect(wordListWidget, SIGNAL(showTranslation(QList<Translation*>)),
502             this, SIGNAL(searchTranslations(QList<Translation*>)));
503
504
505
506
507     connect(this, SIGNAL(setBusy()),
508             wordListWidget, SLOT(lockList()));
509
510     connect(this, SIGNAL(setIdle()),
511             wordListWidget, SLOT(unlockList()));
512
513     connect(wordListWidget, SIGNAL(addBookmark(QList<Translation*>)),
514             backbone, SLOT(addBookmark(QList<Translation*>)));
515
516     connect(wordListWidget, SIGNAL(removeBookmark(QList<Translation*>)),
517             backbone, SLOT(removeBookmark(QList<Translation*>)));
518 }
519
520 void MainWindow::connectTranslationWidget() {
521     connect(this, SIGNAL(showTranslation(QStringList)),
522             translationWidget, SLOT(show(QStringList)));
523
524      #ifdef Q_WS_MAEMO_5
525         connect(translationWidget, SIGNAL(search(QString)),
526                 this, SLOT(search(QString)));
527     #else
528         connect(translationWidget, SIGNAL(search(QString)),
529                 this, SLOT(searchExact(QString)));
530     #endif
531
532
533 }
534
535 void MainWindow::connectDictManager() {
536     connect(dictManagerWidget, SIGNAL(addDictionary(CommonDictInterface*)),
537             this, SIGNAL(addNewDictionary(CommonDictInterface*)));
538
539     connect(dictManagerWidget, SIGNAL(removeDictionary(CommonDictInterface*)),
540             this, SIGNAL(removeDictionary(CommonDictInterface*)));
541
542     connect(dictManagerWidget,
543             SIGNAL(selectedDictionaries(QList<CommonDictInterface*>)),
544             this, SIGNAL(selectedDictionaries(QList<CommonDictInterface*>)));
545 }
546
547 void MainWindow::connectMenu() {
548     connect(this, SIGNAL(setBusy()),
549             this, SLOT(disableMenu()));
550
551     connect(this, SIGNAL(setIdle()),
552             this, SLOT(enableMenu()));
553 }
554
555
556 void MainWindow::connectBookmarksWidget() {
557     #ifdef Q_WS_MAEMO_5
558         //after removing bookmarks we search for them once again to clear the words list
559         connect(bookmarksWidget, SIGNAL(removeAllBookmarks()),
560                 this, SLOT(removeBookmarks()));
561
562
563         connect(bookmarksWidget, SIGNAL(showAllBookmarks()),
564                 menuWidget, SLOT(hideMenu()));
565
566         connect(bookmarksWidget, SIGNAL(showAllBookmarks()),
567                 backbone, SLOT(fetchBookmarks()));
568
569
570     #else
571         connect(bookmarksRemoveAllAction, SIGNAL(triggered()),
572                 this, SLOT(removeBookmarks()));
573         connect(bookmarksShowAllAction, SIGNAL(triggered()),
574                 backbone, SLOT(fetchBookmarks()));
575
576     #endif
577 }
578
579
580 void MainWindow::removeBookmarks() {
581     QWidget* par;
582     #ifdef Q_WS_MAEMO_5
583         par = bookmarksWidget;
584     #else
585         par = this;
586     #endif
587     if(QMessageBox::question(par, tr("Delete all bookmarks"),
588              tr("Do you want to delete all bookmarks? (This action cannot be revoked, and will clear current word list)"),
589              QMessageBox::Yes, QMessageBox::Cancel) == QMessageBox::Yes) {
590         backbone->removeAllBookmarks();
591         ((WordListWidget*)wordListWidget)->clear();
592     }
593
594
595 }