37eae2fec11bf6cbb0c25fb6aeeab39882977362
[mdictionary] / src / mdictionary / gui / WordListWidget.cpp
1
2 /*******************************************************************************
3
4     This file is part of mDictionary.
5
6     mDictionary is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10
11     mDictionary is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with mDictionary.  If not, see <http://www.gnu.org/licenses/>.
18
19     Copyright 2010 Comarch S.A.
20
21 *******************************************************************************/
22
23 /*! \file WordListwidget.cpp
24     \brief Displays list of words found in dictionaries
25
26     \author Mateusz Półrola <mateusz.polrola@comarch.pl>
27 */
28
29 #include "WordListWidget.h"
30 #include "WordListProxyStyle.h"
31 #include "../../include/translation.h"
32 #include <QKeyEvent>
33
34
35 WordListWidget::WordListWidget(QWidget *parent):
36     QTreeView(parent) {
37
38     _isBookmarkModeActive = false;
39
40     //creating new model to store words and stars
41 #ifdef Q_WS_MAEMO_5
42     model = new QStandardItemModel(this);
43     setModel(model);
44
45     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
46
47     //set our custom style to draw checkboxes as stars
48     proxyStyle = new WordListProxyStyle();
49     setStyle(proxyStyle);
50
51     //for future use, set checkbox icons for maemo
52 //    ctxt->setContextProperty("CheckedPath", "qrc:/icons/96x96/staron.png");
53 //    ctxt->setContextProperty("UncheckedPath", "qrc:/icons/96x96/staroff.png");
54 #else
55
56     listModel = new WordListModel(this);
57
58     verticalLayout = new QVBoxLayout;
59     setLayout(verticalLayout);
60
61     qmlView = new QDeclarativeView(this);
62
63     ctxt = qmlView->rootContext();
64
65     ctxt->setContextProperty("wordModel", &(*listModel));
66     ctxt->setContextProperty("CheckedPath", "qrc:/icons/16x16/staron.png");
67     ctxt->setContextProperty("UncheckedPath", "qrc:/icons/16x16/staroff.png");
68
69     qmlView->setSource(QUrl::fromLocalFile("/usr/share/mdictionary/qml/WordListWidget.qml"));
70
71     QGraphicsObject *rootObject = qmlView->rootObject();
72
73     qmlView->setResizeMode(QDeclarativeView::SizeRootObjectToView);
74
75     verticalLayout->addWidget(qmlView);
76
77     connect(rootObject, SIGNAL(wordSelected(QString)), this, SLOT(wordClicked(QString)));
78     connect(listModel, SIGNAL(addToBookmarks(QString)), this, SLOT(addToBookmarks(QString)));
79     connect(listModel, SIGNAL(removeFromBookmarks(QString)), this, SLOT(removeFromBookmarks(QString)));
80
81     connect(this, SIGNAL(setWordListState(QVariant)), rootObject, SLOT(setEnabled(QVariant)));
82     connect(this, SIGNAL(setWordListEmpty(QVariant)), rootObject, SLOT(setWordListEmpty(QVariant)));
83     connect(this, SIGNAL(setFocusOnQML()), rootObject, SLOT(setFocus()));
84
85 #endif
86
87     setHeaderHidden(true);
88     setRootIsDecorated(false);
89
90     //setting size of star in pixels, on maemo checboxes are much bigger
91     #ifdef Q_WS_MAEMO_5
92         checkBoxWidth = 70;
93     #else
94         checkBoxWidth = 25;
95     #endif
96 }
97
98
99 WordListWidget::~WordListWidget() {
100     if(proxyStyle)
101         delete proxyStyle;
102 }
103
104 void WordListWidget::setFocusOnElement(){
105     setFocus();
106     qmlView->setFocus();
107     Q_EMIT setFocusOnQML();
108     qDebug()<<hasFocus()<<" "<<qmlView->hasFocus();
109 }
110
111 void WordListWidget::addWord(QString word, int row) {
112     QStandardItem* item = new QStandardItem(word);
113
114     //we don't want to allow user to edit word
115     item->setFlags(item->flags() ^ Qt::ItemIsEditable);
116
117     QStandardItem* itemCheckBox = new QStandardItem();
118     //creating checkbox item
119     itemCheckBox->setFlags((itemCheckBox->flags() ^ Qt::ItemIsEditable) |
120                            Qt::ItemIsUserCheckable);
121
122     /*checking if word is already in bookmarks, information about that is
123     stored in its translation object (not all translations have to be in
124     bookmarks)*/
125     bool bookmark = false;
126     Translation* t;
127     foreach(t, searchResult[word]) {
128         if(t->isBookmark()) {
129             bookmark = true;
130             break;
131         }
132     }
133
134     if(bookmark)
135         itemCheckBox->setCheckState(Qt::Checked);
136     else
137         itemCheckBox->setCheckState(Qt::Unchecked);
138
139     //add item to model
140     model->setItem(row,0, item);
141     model->setItem(row,1, itemCheckBox);
142 }
143
144
145 void WordListWidget::showSearchResults(
146         QHash<QString, QList<Translation *> > result) {
147
148     clear();
149     searchResult = result;
150
151 #ifdef Q_WS_MAEMO
152     if(searchResult.count()>0) {
153         setEnabled(true);
154         model->setColumnCount(2);
155         model->setRowCount(result.count());
156
157         int row=0;
158         QHash<QString, QList<Translation*> >::iterator i;
159         for(i = searchResult.begin(); i != searchResult.end(); i++) {
160                addWord(i.key(), row++);
161         }
162
163         model->sort(0);
164         resizeColumns();
165     }
166     else {
167         QStandardItem* item = new QStandardItem(tr("Can't find any matching words"));
168         item->setFlags(item->flags() ^ Qt::ItemIsEditable);
169         item->setTextAlignment(Qt::AlignCenter);
170         setEnabled(false);
171
172         model->setItem(0,item);
173     }
174 #else
175
176     QHash<QString, bool> wordsInBookmarks;
177     QHashIterator<QString, QList<Translation *> > i(result);
178     while (i.hasNext()){
179         i.next();
180
181         bool bookmark = false;
182         Translation* t;
183         foreach(t, searchResult[i.key()]) {
184             if(t->isBookmark()) {
185                 bookmark = true;
186                 break;
187             }
188         }
189         wordsInBookmarks.insert(i.key(), bookmark);
190     }
191
192     if (result.count() == 0){
193         //result.insert("!@#$%", QList<Translation*>());
194 //        wordsInBookmarks.insert("!@#$%", false);
195         Q_EMIT setWordListState(false);
196         Q_EMIT setWordListEmpty(true);
197     } else {
198         Q_EMIT setWordListEmpty(false);
199     }
200
201     if (listModel == 0){
202         listModel = new WordListModel(this);
203     }
204
205     listModel->setBookmarkModeActive(_isBookmarkModeActive);
206     _isBookmarkModeActive = false;
207     listModel->setTranslations(result, wordsInBookmarks);
208
209 #endif
210
211     setFocus();
212 }
213
214 #ifdef Q_WS_MAEMO
215 void WordListWidget::wordClicked(QModelIndex index) {
216     //we're getting translation based on data in index
217     Q_EMIT showTranslation(
218             searchResult[index.data().toString()]);
219 }
220
221 void WordListWidget::wordChecked(QModelIndex index) {
222
223     //save new item state
224     Qt::CheckState state =
225             Qt::CheckState(index.data(Qt::CheckStateRole).toInt());
226
227
228     //getting index of item which contains word which should be added/removed
229     //from bookmarks
230     QModelIndex item = selectedIndexes().at(0);
231     if(!item.isValid()) return;
232
233     //to shorten lag between clicking on a star and its change
234     repaint();
235
236     //depending on new state emit suitable signal
237     if(state == Qt::Checked) {
238         Q_EMIT addBookmark(searchResult[item.data().toString()]);
239     }
240     else {
241         Q_EMIT removeBookmark(searchResult[item.data().toString()]);
242
243         Translation* t;
244         bool onlyBookmarks = true;
245         foreach(t, searchResult[item.data().toString()]) {
246             if(t->isBookmark() == 1 || t->isBookmark()==0) {
247
248                 onlyBookmarks = false;
249                 t->setBookmark(0);
250             }
251             else {
252                 searchResult[item.data().toString()].removeAt(searchResult[item.data().toString()].indexOf(t));
253             }
254         }
255
256         if(onlyBookmarks) {
257             searchResult.remove(item.data().toString());
258             model->removeRow(item.row());
259         }
260     }
261 }
262 #else
263     void WordListWidget::wordClicked(QString word){
264         emit showTranslation(searchResult[word]);
265     }
266
267     void WordListWidget::addToBookmarks(QString word){
268         emit addBookmark(searchResult[word]);
269     }
270
271     void WordListWidget::removeFromBookmarks(QString word){
272         emit removeBookmark(searchResult[word]);
273     }
274
275 #endif
276
277
278 #ifdef Q_WS_MAEMO_5
279 void WordListWidget::mouseReleaseEvent(QMouseEvent *event) {
280
281     //firstly we normally handle this event
282     QTreeView::mouseReleaseEvent(event);
283
284     //then we check at which item user clicked
285     QModelIndex index = indexAt(event->pos());
286     if(!index.isValid()) return;
287
288     /*if there are no selected items we return, that occurs sometimes
289     on maemo, when user is scrolling list and clicks to stop the scroll,
290     system doesn't select item but emits mouseReleaseEvent*/
291     if(selectedIndexes().count() == 0) return;
292
293     //if user doesn't click either on a word or on a star, return
294     if(selectedIndexes().at(0) != index && selectedIndexes().at(1) != index)
295         return;
296
297     int c = index.column();
298     if(c==0)
299         //if column is 0 user clicked on a word
300         wordClicked(index);
301     else
302         //else user clicked on a star
303         wordChecked(index);
304 }
305
306 void WordListWidget::resizeEvent(QResizeEvent *event) {
307     resizeColumns();
308     QTreeView::resizeEvent(event);
309 }
310
311 void WordListWidget::keyPressEvent(QKeyEvent *event) {
312     QTreeView::keyPressEvent(event);
313
314     if(event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
315         if(selectedIndexes().count() == 0) return;
316
317         wordClicked(selectedIndexes().at(0));
318     }
319 }
320 #endif
321
322 void WordListWidget::resizeColumns() {
323     setColumnWidth(0, viewport()->width() -checkBoxWidth - 5);
324     setColumnWidth(1, checkBoxWidth);
325 }
326
327 void WordListWidget::lockList() {
328 #ifdef Q_WS_MAEMO_5
329     setEnabled(false);
330 #else
331     Q_EMIT setWordListState(false);
332 #endif
333 }
334
335 void WordListWidget::unlockList() {
336 #ifdef Q_WS_MAEMO_5
337     setEnabled(true);
338 #else
339     Q_EMIT setWordListState(true);
340 #endif
341 }
342
343 void WordListWidget::clear() {
344 #ifdef Q_WS_MAEMO_5
345     model->clear();
346 #else
347     if (listModel != 0){
348         listModel->clear();
349     }
350 #endif
351
352     QHash<QString, QList<Translation*> >::iterator i;
353     for(i = searchResult.begin(); i != searchResult.end(); i++) {
354            Translation*t;
355            foreach(t, i.value()) {
356                delete t;
357            }
358     }
359     searchResult.clear();
360 }
361
362 void WordListWidget::bookmarkModeActive(){
363     _isBookmarkModeActive = true;
364 }