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