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