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