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