Fix random error when remove word from bookmark. Fix show all bookmark feature.
[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
83 #endif
84
85     setHeaderHidden(true);
86     setRootIsDecorated(false);
87
88     //setting size of star in pixels, on maemo checboxes are much bigger
89     #ifdef Q_WS_MAEMO_5
90         checkBoxWidth = 70;
91     #else
92         checkBoxWidth = 25;
93     #endif
94 }
95
96
97 WordListWidget::~WordListWidget() {
98     if(proxyStyle)
99         delete proxyStyle;
100 }
101
102 void WordListWidget::addWord(QString word, int row) {
103     QStandardItem* item = new QStandardItem(word);
104
105     //we don't want to allow user to edit word
106     item->setFlags(item->flags() ^ Qt::ItemIsEditable);
107
108     QStandardItem* itemCheckBox = new QStandardItem();
109     //creating checkbox item
110     itemCheckBox->setFlags((itemCheckBox->flags() ^ Qt::ItemIsEditable) |
111                            Qt::ItemIsUserCheckable);
112
113     /*checking if word is already in bookmarks, information about that is
114     stored in its translation object (not all translations have to be in
115     bookmarks)*/
116     bool bookmark = false;
117     Translation* t;
118     foreach(t, searchResult[word]) {
119         if(t->isBookmark()) {
120             bookmark = true;
121             break;
122         }
123     }
124
125     if(bookmark)
126         itemCheckBox->setCheckState(Qt::Checked);
127     else
128         itemCheckBox->setCheckState(Qt::Unchecked);
129
130     //add item to model
131     model->setItem(row,0, item);
132     model->setItem(row,1, itemCheckBox);
133 }
134
135
136 void WordListWidget::showSearchResults(
137         QHash<QString, QList<Translation *> > result) {
138
139     clear();
140     searchResult = result;
141
142 #ifdef Q_WS_MAEMO
143     if(searchResult.count()>0) {
144         setEnabled(true);
145         model->setColumnCount(2);
146         model->setRowCount(result.count());
147
148         int row=0;
149         QHash<QString, QList<Translation*> >::iterator i;
150         for(i = searchResult.begin(); i != searchResult.end(); i++) {
151                addWord(i.key(), row++);
152         }
153
154         model->sort(0);
155         resizeColumns();
156     }
157     else {
158         QStandardItem* item = new QStandardItem(tr("Can't find any matching words"));
159         item->setFlags(item->flags() ^ Qt::ItemIsEditable);
160         item->setTextAlignment(Qt::AlignCenter);
161         setEnabled(false);
162
163         model->setItem(0,item);
164     }
165 #else
166
167     QHash<QString, bool> wordsInBookmarks;
168     QHashIterator<QString, QList<Translation *> > i(result);
169     while (i.hasNext()){
170         i.next();
171
172         bool bookmark = false;
173         Translation* t;
174         foreach(t, searchResult[i.key()]) {
175             if(t->isBookmark()) {
176                 bookmark = true;
177                 break;
178             }
179         }
180         wordsInBookmarks.insert(i.key(), bookmark);
181     }
182
183     if (result.count() == 0){
184         result.insert("!@#$%", QList<Translation*>());
185         wordsInBookmarks.insert("!@#$%", false);
186         Q_EMIT setWordListState(false);
187     }
188
189     if (listModel == 0){
190         listModel = new WordListModel(this);
191     }
192
193     listModel->setBookmarkModeActive(isBookmarkModeActive);
194     isBookmarkModeActive = false;
195     listModel->setTranslations(result, wordsInBookmarks);
196
197 #endif
198
199     setFocus();
200 }
201
202 #ifdef Q_WS_MAEMO
203 void WordListWidget::wordClicked(QModelIndex index) {
204     //we're getting translation based on data in index
205     Q_EMIT showTranslation(
206             searchResult[index.data().toString()]);
207 }
208
209 void WordListWidget::wordChecked(QModelIndex index) {
210
211     //save new item state
212     Qt::CheckState state =
213             Qt::CheckState(index.data(Qt::CheckStateRole).toInt());
214
215
216     //getting index of item which contains word which should be added/removed
217     //from bookmarks
218     QModelIndex item = selectedIndexes().at(0);
219     if(!item.isValid()) return;
220
221     //to shorten lag between clicking on a star and its change
222     repaint();
223
224     //depending on new state emit suitable signal
225     if(state == Qt::Checked) {
226         Q_EMIT addBookmark(searchResult[item.data().toString()]);
227     }
228     else {
229         Q_EMIT removeBookmark(searchResult[item.data().toString()]);
230
231         Translation* t;
232         bool onlyBookmarks = true;
233         foreach(t, searchResult[item.data().toString()]) {
234             if(t->isBookmark() == 1 || t->isBookmark()==0) {
235
236                 onlyBookmarks = false;
237                 t->setBookmark(0);
238             }
239             else {
240                 searchResult[item.data().toString()].removeAt(searchResult[item.data().toString()].indexOf(t));
241             }
242         }
243
244         if(onlyBookmarks) {
245             searchResult.remove(item.data().toString());
246             model->removeRow(item.row());
247         }
248     }
249 }
250 #else
251     void WordListWidget::wordClicked(QString word){
252         emit showTranslation(searchResult[word]);
253     }
254
255     void WordListWidget::addToBookmarks(QString word){
256         emit addBookmark(searchResult[word]);
257     }
258
259     void WordListWidget::removeFromBookmarks(QString word){
260         emit removeBookmark(searchResult[word]);
261     }
262
263 #endif
264
265
266 #ifdef Q_WS_MAEMO_5
267 void WordListWidget::mouseReleaseEvent(QMouseEvent *event) {
268
269     //firstly we normally handle this event
270     QTreeView::mouseReleaseEvent(event);
271
272     //then we check at which item user clicked
273     QModelIndex index = indexAt(event->pos());
274     if(!index.isValid()) return;
275
276     /*if there are no selected items we return, that occurs sometimes
277     on maemo, when user is scrolling list and clicks to stop the scroll,
278     system doesn't select item but emits mouseReleaseEvent*/
279     if(selectedIndexes().count() == 0) return;
280
281     //if user doesn't click either on a word or on a star, return
282     if(selectedIndexes().at(0) != index && selectedIndexes().at(1) != index)
283         return;
284
285     int c = index.column();
286     if(c==0)
287         //if column is 0 user clicked on a word
288         wordClicked(index);
289     else
290         //else user clicked on a star
291         wordChecked(index);
292 }
293
294 void WordListWidget::resizeEvent(QResizeEvent *event) {
295     resizeColumns();
296     QTreeView::resizeEvent(event);
297 }
298
299 void WordListWidget::keyPressEvent(QKeyEvent *event) {
300     QTreeView::keyPressEvent(event);
301
302     if(event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
303         if(selectedIndexes().count() == 0) return;
304
305         wordClicked(selectedIndexes().at(0));
306     }
307 }
308 #endif
309
310 void WordListWidget::resizeColumns() {
311     setColumnWidth(0, viewport()->width() -checkBoxWidth - 5);
312     setColumnWidth(1, checkBoxWidth);
313 }
314
315 void WordListWidget::lockList() {
316 #ifdef Q_WS_MAEMO_5
317     setEnabled(false);
318 #else
319     Q_EMIT setWordListState(false);
320 #endif
321 }
322
323 void WordListWidget::unlockList() {
324 #ifdef Q_WS_MAEMO_5
325     setEnabled(true);
326 #else
327     Q_EMIT setWordListState(true);
328 #endif
329 }
330
331 void WordListWidget::clear() {
332 #ifdef Q_WS_MAEMO_5
333     model->clear();
334 #else
335     if (listModel != 0){
336         listModel->clear();
337     }
338 #endif
339
340     QHash<QString, QList<Translation*> >::iterator i;
341     for(i = searchResult.begin(); i != searchResult.end(); i++) {
342            Translation*t;
343            foreach(t, i.value()) {
344                delete t;
345            }
346     }
347     searchResult.clear();
348 }
349
350 void WordListWidget::bookmarkModeActive(){
351     isBookmarkModeActive = true;
352 }