Root/htmlarea.cpp

1/***************************************************************************
2 * Copyright (C) 2010 by Mirko Lindner *
3 * mirko@sharism.cc *
4 * *
5 * This program 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 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program 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 this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20
21// #include <iostream>
22#include <QtGui>
23#include <QMessageBox>
24#include <QTextBrowser>
25#include <string>
26#include <sstream>
27// #include <vector>
28#include "qmain.h"
29#include <zim/file.h>
30#include <zim/search.h>
31#include <zim/fileimpl.h>
32
33#include <cxxtools/log.h>
34
35log_define("qvido.htmlarea");
36
37bool UserEventFilter::eventFilter(QObject *obj, QEvent *event)
38{
39        if (event->type() == QEvent::KeyPress) {
40                QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
41                log_debug("Ate key press " << keyEvent->key());
42                return true;
43        } else {
44                // standard event processing
45                return QObject::eventFilter(obj, event);
46        }
47}
48
49///////////////////////////////////////////
50// Functions related to htmlarea
51void HtmlArea::linking( const QUrl &txt ){
52    QString str = txt.toString();
53    
54// // check if url is an internal anchor if yes jump if not end request and query zimlib
55    if (str.startsWith("#") == 1){
56        this->scrollToAnchor(str);
57    }else{
58        log_debug(str.toUtf8().data());
59        this->setSource(this->source());
60        this->setNewContent(1, str);
61    }
62}
63
64void HtmlArea::setNewContent( int method, QString str = "" ){
65    
66    qobject_cast<QMain *>(this->parentWidget())->setEnabled(false);
67    QString current = this->toHtml();
68    this->setText("<html><body><br/><br/><br/><br/><p>Loading ... </p></body></html>");
69    qApp->processEvents();
70    
71    zim::Article article;
72    
73    if (method == 0){
74        article = this->getRandomArticle();
75    }else if( method == 1){
76        article = this->getArticleFromUrl(str);
77    }else if( method == 2){
78        // first search
79        zim::Search::Results result = this->searchArticleFromTitle(str);
80        // if result = 1 display article
81        if (result.size() == 1){
82            log_debug("result size 1");
83            //create ZIM file accessor
84            zim::File file = this->get_file();
85            article = file.getArticle(result[0].getArticle().getIndex());
86        }
87        // if result > 1 display options return at end
88        else if (result.size() > 1){
89            log_debug("more than one result");
90            QString res;
91            for (unsigned i = 0; i < result.size(); ++i)
92        {
93          res.append("<li><a href='" + QString::fromUtf8(result[i].getArticle().getUrl().c_str()) + "'>" + QString::fromUtf8(result[i].getArticle().getTitle().c_str()) + "</a></li>");
94        }
95            this->setText(res);
96            qApp->processEvents();
97            qobject_cast<QMain *>(this->parentWidget())->setEnabled(true);
98            return;
99        }
100
101    }
102    
103    //check if article is valid, if display if not show error
104    if (article.good()){
105        log_debug("article is good");
106        this->url = QString::fromUtf8(article.getUrl().c_str());
107        log_debug("Url set");
108        //TODO build history, set Title
109        //TODO certain zimfiles break here
110        // example full german file breaks here with article "Trockenrasierer"
111        std::string content = "<a name=\"top\"></a>";
112        content.append(article.getPage());
113        this->setText(QString::fromUtf8(content.c_str()));
114        
115        log_debug("Text set");
116// log_debug("index: " << article.getIndex());
117// log_debug("enabled: " << this->isEnabled());
118        qApp->processEvents();
119        qobject_cast<QMain *>(this->parentWidget())->setEnabled(true);
120        log_debug("string: " << str.toUtf8().data());
121        
122    }else{
123        this->setText(current);
124        //construct error text
125        QString errText = "The article you requested (";
126        errText.append(str);
127        errText.append(") could not be found.");
128        log_debug("string: " << str.toUtf8().data());
129        qApp->processEvents();
130        qobject_cast<QMain *>(this->parentWidget())->setEnabled(true);
131        
132        //construct and display error box
133        QMessageBox::information(qobject_cast<QMain *>(this->parentWidget()), "Error",
134                                                         errText,
135                                                         QMessageBox::Close);
136    }
137    
138}
139
140// // slots
141// // TODO ...is there any way to connect setNewContent to Actions directly using default values?
142void HtmlArea::getRandom(){
143    log_debug("getRandom called");
144    if(this->isEnabled()){
145        this->setNewContent( 0 );
146    }
147}
148
149void HtmlArea::searchArticle(QString term){
150    log_debug("searchArticle called");
151    if(this->isEnabled()){
152        this->setNewContent( 2 , term);
153    }
154}
155
156void HtmlArea::goToTop(){
157    this->scrollToAnchor("#top");
158}
159
160//
161////////////////////////////////////////////
162////////////////////////////////////////////
163// Debug functions
164void HtmlArea::sourceChange( const QUrl &txt ){
165    QString str = txt.toString();
166    log_debug("source: " << str.toStdString());
167}
168
169
170//
171////////////////////////////////////////////
172
173//reimplimentations
174QVariant HtmlArea::loadResource(int type, const QUrl &name)
175{
176
177        QVariant qv;
178        
179        // check if requested resource is an image
180        if (type == 2){
181            zim::Article article;
182            article = getArticleFromUrl(name.toString());
183            
184            if(article.good()){
185                QString mtype(article.getMimeType().c_str());
186                
187                QByteArray data = QByteArray::fromRawData(article.getData().data(), article.getData().size());
188
189                QImage img;
190                
191                mtype.remove("image/");
192                img.loadFromData(data, mtype.toUpper().toLatin1());
193                
194// log_debug("index: " << article.getIndex() << " height: " << article.getData().size() << " mtype: " << std::string(mtype.toUpper().toLatin1()));
195                qv = img;
196
197            }
198        }
199        
200        return qv;
201}
202
203
204////////////////////////////////////////////
205// Zimlib functions
206
207const zim::File& HtmlArea::get_file()
208{
209  static zim::File zimFile;
210
211  if (!zimFile.good())
212  {
213    zimFile = zim::File(qobject_cast<QMain *>(this->parentWidget())->fileLocation);
214    log_debug("number of articles: " << zimFile.getCountArticles());
215  }
216
217  return zimFile;
218}
219
220//get random article
221zim::Article HtmlArea::getRandomArticle(){
222        
223        //get file
224        zim::File file = this->get_file();
225        
226        //create empty article
227        zim::Article article;
228// log_debug("before random loop");
229    do
230        {
231                // generate random number
232                unsigned int seed = static_cast<unsigned int>(time(0));
233                zim::size_type idx = static_cast<zim::size_type>(static_cast<double>(file.getCountArticles()) * rand_r(&seed) / RAND_MAX);
234                
235                //retrieve article
236                article = file.getArticle(idx);
237// article = file.getArticle(151);
238                log_debug("idx: " << idx);
239                //loop in case article is redirect
240// log_debug("before redirect loop");
241                do
242                {
243                        article = article.getRedirectArticle();
244                        log_debug("random url: " << article.getUrl());
245                }while(article.isRedirect());
246    
247        }while(article.getUrl() == this->url.toStdString());
248        
249// log_debug("after random loop");
250        
251        return article;
252}
253
254zim::Article HtmlArea::getArticleFromUrl(QString url)
255{
256    // TODO unescape url
257
258        //create ZIM file accessor
259    zim::File file = this->get_file();
260        
261        //create empty article
262        zim::Article article;
263        
264        // remove '+' signs
265    QString term = url.replace( '+', ' ');
266
267        //set default namespace
268    char ns = 'A';
269
270        //check for different namespace
271    if (term.contains("/"))
272    {
273                if(term.startsWith("/")){
274                    term.remove(0,1);
275                }
276                int index = term.indexOf("/");
277        if ( index == 1)
278        {
279            ns = term[0].toLatin1();
280            term.remove(0, 2);
281        }
282                 //TODO what was this for?
283                /*
284        else
285        {
286            term.erase(1);
287            ns = term[0];
288            found2 = term.find("/");
289            term.erase(0, term.indexOf("/"));
290        }*/
291    }
292        
293// // // try to retrieve article
294    try
295    {
296            article = file.getArticle(ns, term.toUtf8().data());
297// QString mtype(article.getMimeType().c_str());
298// if(mtype.contains("image/") == false){
299// log_debug("term :" << term.toStdString());
300// }
301            return article;
302    }
303    catch (const std::exception& e)
304    {
305        std::cerr << e.what() << std::endl;
306    }
307}
308
309zim::Search::Results HtmlArea::searchArticleFromTitle(QString phrase)
310{
311        char ns;
312    ns = 'A';
313    
314        zim::File file = get_file();
315    
316        zim::Article article;
317        
318    zim::Search::Results result;
319    zim::Search search(file);
320    search.setSearchLimit(25);
321        char *terms = phrase.toUtf8().data();
322        
323    search.find(result, ns, terms);
324        log_debug("term :" << phrase.toUtf8().data());
325        return result;
326}
327
328///////////////////////////////////
329// functions related to navigation
330
331void HtmlArea::keyPressEvent(QKeyEvent *e){
332    log_debug("key pressed");
333    switch (e->key()) {
334         case Qt::Key_Right:
335                {
336// QPoint pos = qobject_cast<QMain *>(this->parentWidget())->cursor().pos();
337// qobject_cast<QMain *>(this->parentWidget())->cursor().setPos(pos.x() + 5, pos.y());
338// QPoint pos2 = qobject_cast<QMain *>(this->parentWidget())->cursor().pos();
339// log_debug("y: " << pos2.y() << " x: " << pos2.x());
340                    QPoint pos = qApp->overrideCursor()->pos();
341                    qApp->overrideCursor()->setPos(pos.x() + 5, pos.y());
342                }
343                return;
344                
345            case Qt::Key_Left:
346                {
347                    QPoint pos = qApp->overrideCursor()->pos();
348                    qApp->overrideCursor()->setPos(pos.x() - 5, pos.y());
349                }
350                return;
351                
352            case Qt::Key_Down:
353                {
354                    QPoint pos = qApp->overrideCursor()->pos();
355                    qApp->overrideCursor()->setPos(pos.x(), pos.y() + 5);
356                }
357                return;
358                
359            case Qt::Key_Up:
360                {
361                    QPoint pos = qApp->overrideCursor()->pos();
362                    qApp->overrideCursor()->setPos(pos.x(), pos.y() - 5);
363                }
364                return;
365    }
366    QTextBrowser::keyPressEvent(e);
367}

Archive Download this file

Branches:
master



interactive