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