Clean and order documentation in source files. Source ready to beta 2 release
[mdictionary] / src / mdictionary / gui / TranslationWidget.cpp
1 /*******************************************************************************
2
3     This file is part of mDictionary.
4
5     mDictionary is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9
10     mDictionary is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with mDictionary.  If not, see <http://www.gnu.org/licenses/>.
17
18     Copyright 2010 Comarch S.A.
19
20 *******************************************************************************/
21
22 /*! \file TranslationWidget.cpp
23     \brief Displays translation of a word found in dictionaries
24
25     \author Mateusz Półrola <mateusz.polrola@comarch.pl>
26 */
27
28 #include "TranslationWidget.h"
29 #include <QDebug>
30 #ifdef Q_WS_MAEMO_5
31     #include <QtGui/QX11Info>
32     #include <X11/Xlib.h>
33     #include <X11/Xatom.h>
34 #endif
35 #include <QWebFrame>
36
37 TranslationWidget::TranslationWidget(QWidget *parent):
38         QScrollArea(parent){
39
40     guiinterface = qobject_cast<GUIInterface*>(parent);
41
42     #ifdef Q_WS_MAEMO_5
43         setAttribute(Qt::WA_Maemo5StackedWindow);
44         setWindowFlags(windowFlags() | Qt::Window);
45     #endif
46
47     initializeUI();
48
49     setWindowTitle("mDictionary");
50
51     connect(webkit, SIGNAL(search()),
52            this, SLOT(searchSelected()));
53
54     QFile file(":/xsl/xsl.xsl");
55     if(!file.open(QFile::ReadOnly))
56         qDebug()<<"error can't open a xslt file";
57     else
58         xslt=file.readAll();
59 }
60
61
62 void TranslationWidget::show() {
63     QScrollArea::show();
64 }
65
66
67 void TranslationWidget::show(QStringList translations) {
68     showMaximized();
69
70     #ifdef Q_WS_MAEMO_5
71         if(!buttonsInitialized)
72             initButtons();
73     #endif
74
75     QString trans= createTranslation(translations);
76
77     QString head = "<html><head>";
78     head += "<link rel=\"stylesheet\" type=\"text/css\" "
79             "href=\"/usr/share/mdictionary/css/" "style.css"
80             "\" /></head><body ondragstart=\"return false\">";
81     trans = head + trans + "</body></html>";
82
83     trans.replace("$STAR$", "/usr/share/mdictionary/staron.png");
84
85     webkit->setHtml(trans, QUrl().fromLocalFile("/"));
86 }
87
88
89 QString TranslationWidget::createTranslation(QStringList translations) {
90     QString trans;
91     if(!translations.size())
92         return QString("Empty translation");
93     int element=-1;
94     do{
95         int a=0;
96         foreach(QString t, translations){
97             if(a!=element)
98                 trans += t + "\n";
99             a++;
100         }
101         trans=QString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>") + QString("\n <ar>")
102                + trans + QString("\n </ar>");
103
104         trans=checkTranslation(trans);
105         trans=XslConversion(trans);
106         element++;
107         if(element>translations.size())
108             return QString("Empty translation");
109     } while(trans==""); // trans=="" only when XslConversation have a error;
110     return trans;
111 }
112
113
114 QString TranslationWidget::XslConversion(QString translation)
115 {
116     QXmlQuery myQuery(QXmlQuery::XSLT20);
117     myQuery.setFocus(translation);
118     myQuery.setQuery(xslt);
119     QString result("");
120     myQuery.evaluateTo(&result);
121     return result;
122 }
123
124
125 QString TranslationWidget::checkTranslation(QString trans){
126     /*check all "&"*/
127     int pos=0;
128     int pos2;
129     int count=0;
130
131     /*check "<" and ">" in key */
132     while(pos!=-1){
133         pos=trans.indexOf("&",pos+1);
134         pos2=trans.indexOf("amp;",pos);
135         if(pos!=-1 && pos2!=-1 && pos+1==pos2)
136             continue;
137         pos2=trans.indexOf("gt;",pos);
138         if(pos!=-1 && pos2!=-1 && pos+1==pos2)
139             continue;
140         pos2=trans.indexOf("lt;",pos);
141         if(pos!=-1 && pos2!=-1 && pos+1==pos2)
142             continue;
143         pos2=trans.indexOf("apos;",pos);
144         if(pos!=-1 && pos2!=-1 && pos+1==pos2)
145             continue;
146         pos2=trans.indexOf("quot;",pos);
147         if(pos!=-1 && pos2!=-1 && pos+1==pos2)
148             continue;
149         if(pos!=-1)
150             trans.insert(pos+1,"amp;");
151     }
152
153     /*check "<" and ">" in key */
154     pos=0;
155     count=0;
156     while(pos<trans.size()){
157         if(pos==trans.indexOf("<key>",pos)){
158             count++;
159             pos+=4;
160         }
161         else if(pos==trans.indexOf("</key>",pos))
162             count--;
163         else if(count==1 && (trans.at(pos)=='<' ||  trans.at(pos)=='>' ))
164             trans.remove(pos,1);
165         pos++;
166     }
167
168     /*checking unclosed tag's*/
169     pos=0;
170     count=0;
171     while(pos<trans.size()){
172         if(trans.at(pos)=='<')
173             count++;
174         else if(trans.at(pos)=='>')
175             count--;
176         if(count==-1){     // remove ">"
177             trans.remove(pos,1);
178             count=0;
179         }
180         pos++;
181     }
182     pos=trans.size()-1;
183     count=0;
184     while(pos>-1){
185         if(trans.at(pos)=='>')
186             count++;
187         else if(trans.at(pos)=='<')
188             count--;
189         if(count==-1){     // remove "<"
190             trans.remove(pos,1);
191             count=0;
192         }
193         pos--;
194     }
195
196     /*check """ and "'" */
197     pos=0;
198     count=0;
199     while(pos<trans.size()){
200         if(trans.at(pos)=='<')
201             count++;
202         else if(trans.at(pos)=='>')
203             count--;
204         else if(trans.at(pos)=='\"' && count==0)
205             trans.replace(pos,1,"&quot;");
206         else if(trans.at(pos)=='\'' && count==0)
207             trans.replace(pos,1,"&apos;");
208         pos++;
209     }
210     return trans;
211 }
212
213
214 #ifdef Q_WS_MAEMO_5
215 void TranslationWidget::initButtons() {
216         int x = width() - showButtonsButton->sizeHint().width();
217         int y = height() - showButtonsButton->sizeHint().height();
218
219         showButtonsButton->move(QPoint(x,y));
220         showButtonsButton->show();
221
222         x = width() - zoomOutButton->sizeHint().width();
223         y = height() - 2*zoomOutButton->sizeHint().height();
224         zoomOutButton->move(QPoint(x, height()));
225
226         zoomOutButtonAnimation = new QPropertyAnimation(zoomOutButton,
227                                                         "pos", this);
228         zoomOutButtonAnimation->setStartValue(QPoint(x, height()));
229         zoomOutButtonAnimation->setEndValue(QPoint(x,y));
230         zoomOutButtonAnimation->setDuration(200);
231         zoomOutButtonAnimation->setEasingCurve(QEasingCurve::InOutBack);
232
233         x = width() - zoomInButton->sizeHint().width();
234         y = height() - 3*zoomInButton->sizeHint().height();
235         zoomInButton->move(QPoint(x, height()));
236
237         zoomInButtonAnimation = new QPropertyAnimation(zoomInButton,
238                                                       "pos", this);
239         zoomInButtonAnimation->setStartValue(QPoint(x, height()));
240         zoomInButtonAnimation->setEndValue(QPoint(x,y));
241         zoomInButtonAnimation->setDuration(400);
242         zoomInButtonAnimation->setEasingCurve(QEasingCurve::InOutBack);
243
244         x = 0;
245         y = height() - copyButton->sizeHint().height();
246
247         copyButton->move(QPoint(x, height()));
248         copyButtonAnimation = new QPropertyAnimation(copyButton, "pos", this);
249         copyButtonAnimation->setStartValue(QPoint(x, height()));
250         copyButtonAnimation->setEndValue(QPoint(x,y));
251         copyButtonAnimation->setDuration(200);
252         copyButtonAnimation->setEasingCurve(QEasingCurve::InOutBack);
253
254         x = 0;
255         y = height() - 2*copyButton->sizeHint().height();
256
257         selectAllButton->move(QPoint(x, height()));
258         selectAllButtonAnimation = new QPropertyAnimation(selectAllButton,
259                                                          "pos", this);
260         selectAllButtonAnimation->setStartValue(QPoint(x, height()));
261         selectAllButtonAnimation->setEndValue(QPoint(x,y));
262         selectAllButtonAnimation->setDuration(400);
263         selectAllButtonAnimation->setEasingCurve(QEasingCurve::InOutBack);
264
265         x = 0;
266         y = height() - 3*copyButton->sizeHint().height();
267
268         searchButton->move(QPoint(x, height()));
269         searchButtonAnimation = new QPropertyAnimation(searchButton,
270                                                       "pos", this);
271         searchButtonAnimation->setStartValue(QPoint(x, height()));
272         searchButtonAnimation->setEndValue(QPoint(x,y));
273         searchButtonAnimation->setDuration(600);
274         searchButtonAnimation->setEasingCurve(QEasingCurve::InOutBack);
275
276         buttonsAnimation = new QParallelAnimationGroup(this);
277         buttonsAnimation->addAnimation(zoomInButtonAnimation);
278         buttonsAnimation->addAnimation(zoomOutButtonAnimation);
279         buttonsAnimation->addAnimation(selectAllButtonAnimation);
280         buttonsAnimation->addAnimation(copyButtonAnimation);
281         buttonsAnimation->addAnimation(searchButtonAnimation);
282         buttonsInitialized = true;
283         buttonsVisible = false;
284
285         connect(showButtonsButton, SIGNAL(clicked()),
286                 this, SLOT(showButtons()));
287 }
288 #endif
289
290 void TranslationWidget::initializeUI() {
291     webkit = new TranslationView(this);
292     Settings* set = guiinterface->settings();
293     qreal fac = set->value("zoom").toFloat();
294     if(!fac)
295         fac++;
296     webkit->setZoomFactor(fac);
297     delete set;
298
299     QWidget*w = new QWidget(this);
300     verticalLayout = new QVBoxLayout(w);
301     verticalLayout->addWidget(webkit);
302
303     this->setWidget(w);
304     this->setWidgetResizable(true);
305
306     #ifdef Q_WS_MAEMO_5
307         zoomInButton = new QToolButton(this);
308         zoomInButton->setIcon(QIcon::fromTheme("pdf_zoomin"));
309         zoomInButton->setMinimumSize(zoomInButton->sizeHint());
310
311         zoomOutButton = new QToolButton(this);
312         zoomOutButton->setIcon(QIcon::fromTheme("pdf_zoomout"));
313         zoomOutButton->setMinimumSize(zoomOutButton->sizeHint());
314
315         selectAllButton = new QToolButton(this);
316         selectAllButton->setIcon(QIcon(":/icons/48x48/edit-select-all.png"));
317         selectAllButton->setMinimumSize(selectAllButton->sizeHint());
318
319         copyButton = new QToolButton(this);
320         copyButton->setIcon(QIcon::fromTheme("general_notes"));
321         copyButton->setMinimumSize(copyButton->sizeHint());
322
323         searchButton = new QToolButton(this);
324         searchButton->setIcon(QIcon::fromTheme("general_search"));
325         searchButton->setMinimumSize(searchButton->sizeHint());
326
327         showButtonsButton = new QToolButton(this);
328         showButtonsButton->setIcon(QIcon::fromTheme("general_sent"));
329         showButtonsButton->setMinimumSize(searchButton->sizeHint());
330
331         connect(zoomInButton, SIGNAL(clicked()),
332                 webkit, SLOT(zoomIn()));
333
334         connect(zoomOutButton, SIGNAL(clicked()),
335                 webkit, SLOT(zoomOut()));
336
337
338         connect(searchButton, SIGNAL(clicked()),
339                 this, SLOT(searchSelected()));
340
341         connect(copyButton, SIGNAL(clicked()),
342                 this, SLOT(copySelected()));
343
344         connect(selectAllButton, SIGNAL(clicked()),
345                 webkit, SLOT(selectAll()));
346
347         buttonsInitialized = false;
348
349
350
351         grabZoomKeys(true);
352     #endif
353 }
354
355 void TranslationWidget::searchSelected() {
356     if(webkit->selectedText().isEmpty()) {
357         Q_EMIT notify(Notify::Warning, tr("No text is selected"));
358     }
359     else {
360         #ifdef Q_WS_MAEMO_5
361             hide();
362         #endif
363         Q_EMIT search(webkit->selectedText().toLower());
364     }
365 }
366
367 void TranslationWidget::copySelected() {
368     if(webkit->selectedText().isEmpty()) {
369         Q_EMIT notify(Notify::Warning, tr("No text is selected"));
370     }
371     else {
372         Q_EMIT notify(Notify::Info, tr("Copyied selected text"));
373     }
374 }
375
376 #ifdef Q_WS_MAEMO_5
377 void TranslationWidget::showButtons() {
378     if(!buttonsVisible) {
379         buttonsAnimation->setDirection(QAbstractAnimation::Forward);
380         buttonsAnimation->start();
381         buttonsVisible = true;
382
383         showButtonsButton->setIcon(QIcon::fromTheme("general_received"));
384     }
385     else if(buttonsVisible) {
386         buttonsAnimation->setDirection(QAbstractAnimation::Backward);
387         buttonsAnimation->start();
388         buttonsVisible = false;
389         showButtonsButton->setIcon(QIcon::fromTheme("general_sent"));
390     }
391 }
392
393 void TranslationWidget::grabZoomKeys(bool grab) {
394      if (!winId()) {
395          return;
396      }
397
398     unsigned long val = (grab) ? 1 : 0;
399     Atom atom = XInternAtom(QX11Info::display(),
400                             "_HILDON_ZOOM_KEY_ATOM", False);
401     if (!atom) {
402         return;
403     }
404
405     XChangeProperty (QX11Info::display(),
406          winId(),
407          atom,
408          XA_INTEGER,
409          32,
410          PropModeReplace,
411          reinterpret_cast<unsigned char *>(&val),
412          1);
413 }
414
415 void TranslationWidget::hideEvent(QHideEvent* e) {
416     if(buttonsVisible)
417         showButtons();
418
419     QScrollArea::hideEvent(e);
420 }
421
422 void TranslationWidget::keyPressEvent(QKeyEvent* event) {
423     switch (event->key()) {
424         case Qt::Key_F7:
425         webkit->zoomIn();
426         event->accept();
427         break;
428
429         case Qt::Key_F8:
430         webkit->zoomOut();
431         event->accept();
432         break;
433     }
434     QWidget::keyPressEvent(event);
435 }
436 #endif
437
438
439 void TranslationWidget::updateZoom(qreal factor) {
440     Settings* set = guiinterface->settings();
441     set->setValue("zoom", QString("%1").arg(factor));
442     guiinterface->setSettings(set);
443 }
444
445
446