odstraneni nekolika gui bugu, pridani librtmp, prepsani parseru na aktualni verzi...
[ctkuk.git] / WebEngine.cpp
blob19824089d073d621473692654dab87c75bfe6a96
1 #include "WebEngine.h"
3 #include <QXmlQuery>
4 #include <QTextStream>
5 #include <QFile>
7 #ifdef HTMLTIDY_LOCAL
8 #include <tidy.h>
9 #endif // HTMLTIDY_LOCAL
11 //////////
12 // TODO:
13 // - parsing
14 // -- refaktor parsingu ... sloucit nacitani podle jednotlivych datovych struktur
15 // -- nastava chyba pri parsovani - ta je zrejme zpusobena timeoutem, protoze se vrati prazdny obsah
16 // - poslat tedy ten samy request, pokud toto nastane
17 // + zive vysilani
20 // - co kdyz spustim 2 requesty po sobe a prvni se jeste nedokoncil? (prepise se mi reply/request)
21 // -- zvazit blokovani nejakym booleanem, cimz se otevre cesta i pro vlakna - 1 request = 1 vlakno
22 // - doxygen
23 // - leaky? m_net, m_reply, m_request...nejsem si tim jistej...
24 //////////
26 void
27 WebEngine::slotNewestVideosReady(QNetworkReply *reply) // reply == m_reply
29 int err;
30 QString result;
31 if((err = parse("parser/top_new.xq", reply->readAll(), &result)) != ERR_NO)
33 emit error(new WebEngineError(err));
34 return;
36 // get data
37 QTextStream stream(&result, QIODevice::ReadOnly);
38 QString tmp;
39 QVector<VideoInfo *> *videos = new QVector<VideoInfo *>();
40 VideoInfo *video;
41 while(1)
43 tmp = stream.readLine();
44 if(tmp.isNull()) break;
46 tmp = tmp.trimmed();
47 if(tmp.length() > 0)
49 video = new VideoInfo;
50 video->id = tmp;
51 video->title = stream.readLine().trimmed();
52 video->img = stream.readLine().trimmed();
53 video->desc = stream.readLine().trimmed();
54 video->date = QDate::fromString(stream.readLine().trimmed(), "d. M. yyyy");
55 video->watched = stream.readLine().trimmed().toInt();
56 videos->push_back(video);
59 m_working = false;
60 emit newestVideosReady(videos);
63 void
64 WebEngine::slotMostWatchedVideosReady(QNetworkReply *reply)
66 int err;
67 QString result;
68 if((err = parse("parser/top_new.xq", reply->readAll(), &result)) != ERR_NO)
70 emit error(new WebEngineError(err));
71 return;
73 // parsing data
74 QTextStream stream(&result, QIODevice::ReadOnly);
75 QString tmp;
76 QVector<VideoInfo *> *videos = new QVector<VideoInfo *>();
77 VideoInfo *video;
78 while(1)
80 tmp = stream.readLine();
81 if(tmp.isNull()) break;
83 tmp = tmp.trimmed();
84 if(tmp.length() > 0)
86 video = new VideoInfo;
87 video->id = tmp;
88 video->title = stream.readLine().trimmed();
89 video->img = stream.readLine().trimmed();
90 video->desc = stream.readLine().trimmed();
91 video->date = QDate::fromString(stream.readLine().trimmed(), "d. M. yyyy");
92 video->watched = stream.readLine().trimmed().toInt();
93 videos->push_back(video);
96 m_working = false;
97 emit mostWatchedVideosReady(videos);
100 void
101 WebEngine::slotAlphabetReady(QNetworkReply *reply)
103 int err;
104 QString result;
105 if((err = parse("parser/alphabet.xq", reply->readAll(), &result)) != ERR_NO)
107 emit error(new WebEngineError(err));
108 return;
110 // parsing data
111 QTextStream stream(&result, QIODevice::ReadOnly);
112 QString tmp;
113 QVector<LinkInfo *> *genres = new QVector<LinkInfo *>();
114 LinkInfo *genre = NULL;
115 while(1)
117 tmp = stream.readLine();
118 if(tmp.isNull()) break;
120 tmp = tmp.trimmed();
121 if(tmp.length() > 0)
123 genre = new LinkInfo;
124 genre->id = tmp;
125 genre->title = stream.readLine().trimmed();
126 genres->push_back(genre);
129 m_working = false;
130 emit alphabetReady(genres);
133 void
134 WebEngine::slotGenresReady(QNetworkReply *reply)
136 int err;
137 QString result;
138 if((err = parse("parser/genres.xq", reply->readAll(), &result)) != ERR_NO)
140 emit error(new WebEngineError(err));
141 return;
143 // parsing data
144 QTextStream stream(&result, QIODevice::ReadOnly);
145 QString tmp;
146 QVector<LinkInfo *> *genres = new QVector<LinkInfo *>();
147 LinkInfo *genre = NULL;
148 while(1)
150 tmp = stream.readLine();
151 if(tmp.isNull()) break;
153 tmp = tmp.trimmed();
154 if(tmp.length() > 0)
156 genre = new LinkInfo;
157 genre->id = tmp;
158 genre->title = stream.readLine().trimmed();
159 genres->push_back(genre);
162 m_working = false;
163 emit genresReady(genres);
166 void
167 WebEngine::slotShowsByAlphaReady(QNetworkReply *reply)
169 int err;
170 QString result;
171 if((err = parse("parser/shows.xq", reply->readAll(), &result)) != ERR_NO)
173 emit error(new WebEngineError(err));
174 return;
176 // parsing data
177 QTextStream stream(&result, QIODevice::ReadOnly);
178 QString tmp;
179 QVector<LinkInfo *> *shows = new QVector<LinkInfo *>();
180 LinkInfo *show = NULL;
181 while(1)
183 tmp = stream.readLine();
184 if(tmp.isNull()) break;
186 tmp = tmp.trimmed();
187 if(tmp.length() > 0)
189 show = new LinkInfo;
190 show->id = tmp;
191 show->title = stream.readLine().trimmed();
192 shows->push_back(show);
195 m_working = false;
196 emit showsByAlphaReady(shows);
199 void
200 WebEngine::slotShowsByGenreReady(QNetworkReply *reply)
202 int err;
203 QString result;
204 if((err = parse("parser/shows.xq", reply->readAll(), &result)) != ERR_NO)
206 emit error(new WebEngineError(err));
207 return;
209 // parsing data
210 QTextStream stream(&result, QIODevice::ReadOnly);
211 QString tmp;
212 QVector<LinkInfo *> *shows = new QVector<LinkInfo *>();
213 LinkInfo *show = NULL;
214 while(1)
216 tmp = stream.readLine();
217 if(tmp.isNull()) break;
219 tmp = tmp.trimmed();
220 if(tmp.length() > 0)
222 show = new LinkInfo;
223 show->id = tmp;
224 show->title = stream.readLine().trimmed();
225 shows->push_back(show);
228 m_working = false;
229 emit showsByGenreReady(shows);
232 void
233 WebEngine::slotVideosByDateReady(QNetworkReply *reply)
235 m_working = false;
236 emit error(new WebEngineError(-1)); // -1 == unexpected error
237 //emit videosByDateReady(videos);
240 void
241 WebEngine::slotShowVideosReady(QNetworkReply *reply)
243 int err;
244 QString result;
245 QByteArray *data = new QByteArray(reply->readAll());
247 if((err = parse("parser/episodes-pages.xq", *data, &result)) != ERR_NO)
249 emit error(new WebEngineError(err));
250 return;
252 int nextPage = result.toInt();
254 m_parser.addTask(new QPair<QString, QByteArray *>("parser/episodes.xq", data));
256 if(nextPage)
258 getShowVideos(m_requestedShowId, nextPage);
260 else
262 m_requestedShowId.clear();
263 m_working = false;
264 emit showAllVideosReady();
268 void
269 WebEngine::slotShowBonusVideosReady(QNetworkReply *reply)
271 m_working = false;
272 emit error(new WebEngineError(-1)); // -1 == unexpected error
273 //emit showBonusVideosReady(videos); link-ivysilani/id/bonusy/1,2,3..max
276 void
277 WebEngine::slotVideoLinkReady(QNetworkReply *reply)
279 int err;
280 QString *result = new QString("");
282 if((err = parse("parser/videolink.xq", reply->readAll(), result)) != ERR_NO)
284 emit error(new WebEngineError(err));
285 return;
289 emit videoLinkReady(result);
292 void
293 WebEngine::slotRemoteFileReady(QNetworkReply *reply)
295 QByteArray *data = new QByteArray(reply->readAll());
297 emit remoteFileReady(data);
300 void
301 WebEngine::slotError(QNetworkReply::NetworkError errCode)
303 m_working = false;
304 emit error(new WebEngineError(ERR_REQUEST));
307 void
308 WebEngine::emitError(WebEngineError *err)
310 emit error(err);
313 void
314 WebEngine::emitShowVideoReady(VideoInfo *video)
316 emit showVideoReady(video);
319 QByteArray WebEngine::userAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; cs; rv:1.9.2) Gecko/20100115 Firefox/3.6";
321 QString WebEngine::iVysilaniLink = "http://www.ceskatelevize.cz/ivysilani/";
322 QString WebEngine::theNewestLink = "http://www.ceskatelevize.cz/ivysilani/nejnovejsi/";
323 QString WebEngine::theMostWatchedLink = "http://www.ceskatelevize.cz/ivysilani/nejsledovanejsi/";
324 QString WebEngine::alphabeticalySortedLink = "http://www.ceskatelevize.cz/ivysilani/podle-abecedy/";
326 #ifdef HTMLTIDY_LOCAL
327 QByteArray &
328 WebEngine::htmlTidy(QByteArray &arr) const
330 TidyDoc tdoc = tidyCreate();
331 tidyParseString(tdoc, arr.data());
332 tidyCleanAndRepair(tdoc);
334 uint buflen = 0;
335 char *outbuf = NULL;
336 tidySaveString(tdoc, outbuf, &buflen); // do buflen se mi vrati velikost vystupu
338 outbuf = new char[buflen+1]; // pro '\0'
339 tidySaveString(tdoc, outbuf, &buflen);
340 outbuf[buflen] = 0;
342 arr = outbuf;
343 return arr;
345 #endif // HTMLTIDY_LOCAL
347 QString
348 WebEngine::htmlTidyViaWeb(const QString &url) const
350 QString retval = "http://services.w3.org/tidy/tidy?docAddr=" + url;
351 return retval;
356 QByteArray &
357 WebEngine::fromUtf8toLocal8Bit(QByteArray &arr) const
359 arr = QString::fromUtf8(arr.data()).toLocal8Bit();
360 return arr;
363 WebEngine::WebEngine(QObject *parent) : QObject(parent)
365 m_parent = parent;
366 m_net = NULL;
367 m_request = NULL;
368 m_reply = NULL;
369 m_working = false;
371 connect(&m_parser, SIGNAL(showVideoReady(VideoInfo *)), this, SLOT(emitShowVideoReady(VideoInfo *)));
372 connect(&m_parser, SIGNAL(error(WebEngineError *)), this, SLOT(emitError(WebEngineError *)));
375 WebEngine::~WebEngine()
377 if(!m_parser.isFinished())
379 m_parser.stop();
380 this->thread()->wait(250); // wait for 250ms
383 while(m_parser.isFinished())
385 m_parser.terminate();
386 this->thread()->wait(250); // wait for 250ms
389 if(!m_parent)
390 m_net->deleteLater(); // kdyz je prirazen rodic, smaze se objekt automaticky sam!
392 delete m_request;
395 void
396 WebEngine::doRequest(const QString &url, bool tidyHtml)
398 m_working = true;
399 m_net = new QNetworkAccessManager(this);
400 m_request = new QNetworkRequest;
401 m_request->setRawHeader("User-Agent", userAgent);
402 m_request->setUrl(QUrl(tidyHtml ? htmlTidyViaWeb(url) : url));
403 m_reply = m_net->get(*m_request);
405 connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)),
406 this , SLOT (slotError(QNetworkReply::NetworkError)));
409 void
410 WebEngine::doVideoRequest(const QString &url, bool tidyHtml)
412 m_netVideo = new QNetworkAccessManager(this);
413 m_requestVideo = new QNetworkRequest;
414 m_requestVideo->setRawHeader("User-Agent", userAgent);
415 m_requestVideo->setUrl(QUrl(tidyHtml ? htmlTidyViaWeb(url) : url));
416 m_replyVideo = m_netVideo->get(*m_requestVideo);
418 connect(m_replyVideo, SIGNAL(error(QNetworkReply::NetworkError)),
419 this , SLOT (slotError(QNetworkReply::NetworkError)));
423 WebEngine::parse(const QString &parserPath, const QByteArray &data, QString *result)
425 if(result == NULL)
427 return ERR_PARSING;
430 QFile parser(parserPath);
431 parser.open(QIODevice::ReadOnly);
432 if(!parser.isOpen())
434 return ERR_PARSER;
436 QByteArray get_videos = parser.readAll();
437 parser.close();
439 QXmlQuery query(QXmlQuery::XQuery10);
440 QByteArray _data = data;
441 if(query.setFocus(fromUtf8toLocal8Bit(_data)))
443 query.setQuery(get_videos);
444 if(query.isValid())
446 query.evaluateTo(result);
448 else
450 return ERR_PARSER;
453 else
455 return ERR_PARSING;
457 return ERR_NO;
460 void
461 WebEngine::getNewestVideos()
463 doRequest(theNewestLink);
465 connect(m_net, SIGNAL(finished(QNetworkReply *)),
466 this , SLOT (slotNewestVideosReady(QNetworkReply *)));
469 void
470 WebEngine::getMostWatchedVideos()
472 doRequest(theMostWatchedLink);
474 connect(m_net, SIGNAL(finished(QNetworkReply *)),
475 this , SLOT (slotMostWatchedVideosReady(QNetworkReply *)));
478 void
479 WebEngine::getAlphabet()
481 doRequest(alphabeticalySortedLink);
483 connect(m_net, SIGNAL(finished(QNetworkReply *)),
484 this , SLOT (slotAlphabetReady(QNetworkReply *)));
487 void
488 WebEngine::getGenres()
490 doRequest(alphabeticalySortedLink);
492 connect(m_net, SIGNAL(finished(QNetworkReply *)),
493 this , SLOT (slotGenresReady(QNetworkReply *)));
496 void
497 WebEngine::getShowsByAlpha(const QString &c)
499 doRequest(iVysilaniLink + c);
501 connect(m_net, SIGNAL(finished(QNetworkReply *)),
502 this , SLOT (slotShowsByAlphaReady(QNetworkReply *)));
504 void
505 WebEngine::getShowsByGenre(const QString &genre)
507 doRequest(iVysilaniLink + genre);
509 connect(m_net, SIGNAL(finished(QNetworkReply *)),
510 this , SLOT (slotShowsByGenreReady(QNetworkReply *)));
513 void
514 WebEngine::getVideosByDate(const QDate &date)
516 doRequest(iVysilaniLink + date.toString("d.M.yyyy"));
518 connect(m_net, SIGNAL(finished(QNetworkReply *)),
519 this , SLOT (slotVideosByDateReady(QNetworkReply *)));
522 void
523 WebEngine::getShowVideos(const QString &id, int page)
525 if(m_requestedShowId != id) // zmena poradu?
527 if(!m_parser.isRunning()) // prvni vyber poradu
529 m_parser.start();
531 else
533 m_parser.cleanTasks();
537 m_requestedShowId = id;
538 doRequest(iVysilaniLink + id + "/dalsi-casti/" + QString::number(page));
540 connect(m_net, SIGNAL(finished(QNetworkReply *)),
541 this , SLOT (slotShowVideosReady(QNetworkReply *)));
544 void
545 WebEngine::getShowBonusVideos(const QString &id)
547 doRequest(iVysilaniLink + id);
549 connect(m_net, SIGNAL(finished(QNetworkReply *)),
550 this , SLOT (slotShowBonusVideosReady(QNetworkReply *)));
553 void
554 WebEngine::getVideoLink(const QString &id)
556 doVideoRequest(iVysilaniLink + id);
558 connect(m_netVideo, SIGNAL(finished(QNetworkReply *)),
559 this , SLOT (slotVideoLinkReady(QNetworkReply *)));
562 void
563 WebEngine::getRemoteFile(const QString &url)
565 doVideoRequest(url, false);
567 connect(m_netVideo, SIGNAL(finished(QNetworkReply *)),
568 this , SLOT (slotRemoteFileReady(QNetworkReply *)));
571 bool
572 WebEngine::isWorking() const
574 return m_working;