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