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