Changeset View
Changeset View
Standalone View
Standalone View
src/alkonlinequote.cpp
1 | /*************************************************************************** | 1 | /*************************************************************************** | ||
---|---|---|---|---|---|
2 | * Copyright 2004 Ace Jones <acejones@users.sourceforge.net> * | 2 | * Copyright 2004 Ace Jones <acejones@users.sourceforge.net> * | ||
3 | * Copyright 2019 Thomas Baumgart <tbaumgart@kde.org> * | ||||
3 | * * | 4 | * * | ||
4 | * This file is part of libalkimia. * | 5 | * This file is part of libalkimia. * | ||
5 | * * | 6 | * * | ||
6 | * libalkimia is free software; you can redistribute it and/or * | 7 | * libalkimia is free software; you can redistribute it and/or * | ||
7 | * modify it under the terms of the GNU General Public License * | 8 | * modify it under the terms of the GNU General Public License * | ||
8 | * as published by the Free Software Foundation; either version 2.1 of * | 9 | * as published by the Free Software Foundation; either version 2.1 of * | ||
9 | * the License or (at your option) version 3 or any later version. * | 10 | * the License or (at your option) version 3 or any later version. * | ||
10 | * * | 11 | * * | ||
Show All 15 Lines | |||||
26 | #include "alkonlinequotesprofile.h" | 27 | #include "alkonlinequotesprofile.h" | ||
27 | #include "alkonlinequotesprofilemanager.h" | 28 | #include "alkonlinequotesprofilemanager.h" | ||
28 | #include "alkonlinequotesource.h" | 29 | #include "alkonlinequotesource.h" | ||
29 | #include "alkwebpage.h" | 30 | #include "alkwebpage.h" | ||
30 | 31 | | |||
31 | #include <QApplication> | 32 | #include <QApplication> | ||
32 | #include <QByteArray> | 33 | #include <QByteArray> | ||
33 | #include <QFile> | 34 | #include <QFile> | ||
34 | //#include <QFileInfo> | | |||
35 | #include <QRegExp> | 35 | #include <QRegExp> | ||
36 | #include <QTextStream> | 36 | #include <QTextStream> | ||
37 | #include <QTextCodec> | 37 | #include <QTextCodec> | ||
38 | 38 | | |||
39 | #include <KConfigGroup> | 39 | #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) | ||
40 | #include <KLocalizedString> | ||||
41 | #include <KIO/Scheduler> | ||||
42 | #include <KIO/Job> | ||||
43 | #include <QDebug> | ||||
44 | #include <QTemporaryFile> | ||||
45 | #define kDebug(a) qDebug() | ||||
46 | #define KIcon QIcon | ||||
47 | #define KUrl QUrl | ||||
48 | #define prettyUrl() toDisplayString() | ||||
49 | #else | ||||
40 | #include <KDebug> | 50 | #include <KDebug> | ||
41 | #include <KEncodingProber> | | |||
42 | #include <KGlobal> | 51 | #include <KGlobal> | ||
52 | #include <KLocale> | ||||
53 | #include <KUrl> | ||||
43 | #include <kio/netaccess.h> | 54 | #include <kio/netaccess.h> | ||
44 | #include <kio/scheduler.h> | 55 | #include <kio/scheduler.h> | ||
45 | #include <KLocale> | 56 | #endif | ||
57 | | ||||
58 | #include <KConfigGroup> | ||||
59 | #include <KEncodingProber> | ||||
46 | #include <KProcess> | 60 | #include <KProcess> | ||
47 | #include <KShell> | 61 | #include <KShell> | ||
48 | #include <KUrl> | | |||
49 | 62 | | |||
50 | AlkOnlineQuote::Errors::Errors() | 63 | AlkOnlineQuote::Errors::Errors() | ||
51 | { | 64 | { | ||
52 | } | 65 | } | ||
53 | 66 | | |||
54 | AlkOnlineQuote::Errors::Errors(Type type) | 67 | AlkOnlineQuote::Errors::Errors(Type type) | ||
55 | { | 68 | { | ||
56 | m_type.append(type); | 69 | m_type.append(type); | ||
Show All 32 Lines | 94 | public: | |||
89 | AlkOnlineQuoteSource m_source; | 102 | AlkOnlineQuoteSource m_source; | ||
90 | AlkOnlineQuote::Errors m_errors; | 103 | AlkOnlineQuote::Errors m_errors; | ||
91 | KUrl m_url; | 104 | KUrl m_url; | ||
92 | QEventLoop *m_eventLoop; | 105 | QEventLoop *m_eventLoop; | ||
93 | QString m_acceptLanguage; | 106 | QString m_acceptLanguage; | ||
94 | AlkOnlineQuotesProfile *m_profile; | 107 | AlkOnlineQuotesProfile *m_profile; | ||
95 | bool m_ownProfile; | 108 | bool m_ownProfile; | ||
96 | 109 | | |||
110 | #if QT_VERSION < QT_VERSION_CHECK(5,0,0) | ||||
97 | static int dbgArea() | 111 | static int dbgArea() | ||
98 | { | 112 | { | ||
habacker: With KDE4 moc ignores #if and includes this slot. It need to be defined also for KDE4 with an… | |||||
99 | static int s_area = KDebug::registerArea("Alkimia (AlkOnlineQuote)"); | 113 | static int s_area = KDebug::registerArea("Alkimia (AlkOnlineQuote)"); | ||
100 | return s_area; | 114 | return s_area; | ||
101 | } | 115 | } | ||
116 | #endif | ||||
102 | 117 | | |||
103 | Private(AlkOnlineQuote *parent) | 118 | Private(AlkOnlineQuote *parent) | ||
104 | : m_p(parent) | 119 | : m_p(parent) | ||
105 | , m_eventLoop(nullptr) | 120 | , m_eventLoop(nullptr) | ||
106 | , m_ownProfile(false) | 121 | , m_ownProfile(false) | ||
107 | { | 122 | { | ||
108 | connect(&m_filter, SIGNAL(processExited(QString)), this, SLOT(slotParseQuote(QString))); | 123 | connect(&m_filter, SIGNAL(processExited(QString)), this, SLOT(slotParseQuote(QString))); | ||
109 | } | 124 | } | ||
110 | 125 | | |||
111 | ~Private() | 126 | ~Private() | ||
112 | { | 127 | { | ||
113 | if (m_ownProfile) | 128 | if (m_ownProfile) | ||
114 | delete m_profile; | 129 | delete m_profile; | ||
115 | } | 130 | } | ||
116 | 131 | | |||
117 | bool initLaunch(const QString &_symbol, const QString &_id, const QString &_source); | 132 | bool initLaunch(const QString &_symbol, const QString &_id, const QString &_source); | ||
118 | bool launchWebKitCssSelector(const QString &_symbol, const QString &_id, | 133 | bool launchWebKitCssSelector(const QString &_symbol, const QString &_id, | ||
119 | const QString &_source); | 134 | const QString &_source); | ||
120 | bool launchWebKitHtmlParser(const QString &_symbol, const QString &_id, const QString &_source); | 135 | bool launchWebKitHtmlParser(const QString &_symbol, const QString &_id, const QString &_source); | ||
121 | bool launchNative(const QString &_symbol, const QString &_id, const QString &_source); | 136 | bool launchNative(const QString &_symbol, const QString &_id, const QString &_source); | ||
122 | bool launchFinanceQuote(const QString &_symbol, const QString &_id, const QString &_source); | 137 | bool launchFinanceQuote(const QString &_symbol, const QString &_id, const QString &_source); | ||
123 | void enter_loop(); | 138 | void enter_loop(); | ||
124 | bool parsePrice(const QString &pricestr); | 139 | bool parsePrice(const QString &pricestr); | ||
125 | bool parseDate(const QString &datestr); | 140 | bool parseDate(const QString &datestr); | ||
141 | bool downloadUrl(const KUrl& url); | ||||
142 | bool processDownloadedFile(const KUrl& url, const QString& tmpFile); | ||||
126 | 143 | | |||
127 | public slots: | 144 | public slots: | ||
128 | void slotLoadStarted(); | 145 | void slotLoadStarted(); | ||
129 | void slotLoadFinishedHtmlParser(bool ok); | 146 | void slotLoadFinishedHtmlParser(bool ok); | ||
130 | void slotLoadFinishedCssSelector(bool ok); | 147 | void slotLoadFinishedCssSelector(bool ok); | ||
131 | bool slotParseQuote(const QString &_quotedata); | 148 | bool slotParseQuote(const QString &_quotedata); | ||
149 | | ||||
150 | private slots: | ||||
151 | void downloadUrlDone(KJob* job); | ||||
132 | }; | 152 | }; | ||
133 | 153 | | |||
134 | bool AlkOnlineQuote::Private::initLaunch(const QString &_symbol, const QString &_id, const QString &_source) | 154 | bool AlkOnlineQuote::Private::initLaunch(const QString &_symbol, const QString &_id, const QString &_source) | ||
135 | { | 155 | { | ||
136 | m_symbol = _symbol; | 156 | m_symbol = _symbol; | ||
137 | m_id = _id; | 157 | m_id = _id; | ||
138 | m_errors = Errors::None; | 158 | m_errors = Errors::None; | ||
139 | 159 | | |||
▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Line(s) | 256 | { | |||
240 | AlkWebPage *webPage = AlkOnlineQuotesProfileManager::instance().webPage(); | 260 | AlkWebPage *webPage = AlkOnlineQuotesProfileManager::instance().webPage(); | ||
241 | connect(webPage, SIGNAL(loadStarted()), this, SLOT(slotLoadStarted())); | 261 | connect(webPage, SIGNAL(loadStarted()), this, SLOT(slotLoadStarted())); | ||
242 | connect(webPage, SIGNAL(loadFinished(bool)), this, | 262 | connect(webPage, SIGNAL(loadFinished(bool)), this, | ||
243 | SLOT(slotLoadFinishedCssSelector(bool))); | 263 | SLOT(slotLoadFinishedCssSelector(bool))); | ||
244 | webPage->setUrl(m_url); | 264 | webPage->setUrl(m_url); | ||
245 | m_eventLoop = new QEventLoop; | 265 | m_eventLoop = new QEventLoop; | ||
246 | m_eventLoop->exec(); | 266 | m_eventLoop->exec(); | ||
247 | delete m_eventLoop; | 267 | delete m_eventLoop; | ||
268 | m_eventLoop = nullptr; | ||||
248 | disconnect(webPage, SIGNAL(loadStarted()), this, SLOT(slotLoadStarted())); | 269 | disconnect(webPage, SIGNAL(loadStarted()), this, SLOT(slotLoadStarted())); | ||
249 | disconnect(webPage, SIGNAL(loadFinished(bool)), this, | 270 | disconnect(webPage, SIGNAL(loadFinished(bool)), this, | ||
250 | SLOT(slotLoadFinishedCssSelector(bool))); | 271 | SLOT(slotLoadFinishedCssSelector(bool))); | ||
251 | 272 | | |||
252 | return !(m_errors & Errors::URL || m_errors & Errors::Price | 273 | return !(m_errors & Errors::URL || m_errors & Errors::Price | ||
253 | || m_errors & Errors::Date || m_errors & Errors::Data); | 274 | || m_errors & Errors::Date || m_errors & Errors::Data); | ||
254 | } | 275 | } | ||
255 | 276 | | |||
256 | bool AlkOnlineQuote::Private::launchWebKitHtmlParser(const QString &_symbol, const QString &_id, | 277 | bool AlkOnlineQuote::Private::launchWebKitHtmlParser(const QString &_symbol, const QString &_id, | ||
257 | const QString &_source) | 278 | const QString &_source) | ||
258 | { | 279 | { | ||
259 | if (!initLaunch(_symbol, _id, _source)) { | 280 | if (!initLaunch(_symbol, _id, _source)) { | ||
260 | return false; | 281 | return false; | ||
261 | } | 282 | } | ||
262 | AlkWebPage *webPage = AlkOnlineQuotesProfileManager::instance().webPage(); | 283 | AlkWebPage *webPage = AlkOnlineQuotesProfileManager::instance().webPage(); | ||
263 | connect(webPage, SIGNAL(loadStarted()), this, SLOT(slotLoadStarted())); | 284 | connect(webPage, SIGNAL(loadStarted()), this, SLOT(slotLoadStarted())); | ||
264 | connect(webPage, SIGNAL(loadFinished(bool)), this, SLOT(slotLoadFinishedHtmlParser(bool))); | 285 | connect(webPage, SIGNAL(loadFinished(bool)), this, SLOT(slotLoadFinishedHtmlParser(bool))); | ||
265 | webPage->load(m_url, m_acceptLanguage); | 286 | webPage->load(m_url, m_acceptLanguage); | ||
266 | m_eventLoop = new QEventLoop; | 287 | m_eventLoop = new QEventLoop; | ||
267 | m_eventLoop->exec(); | 288 | m_eventLoop->exec(); | ||
268 | delete m_eventLoop; | 289 | delete m_eventLoop; | ||
290 | m_eventLoop = nullptr; | ||||
269 | disconnect(webPage, SIGNAL(loadStarted()), this, SLOT(slotLoadStarted())); | 291 | disconnect(webPage, SIGNAL(loadStarted()), this, SLOT(slotLoadStarted())); | ||
270 | disconnect(webPage, SIGNAL(loadFinished(bool)), this, SLOT(slotLoadFinishedHtmlParser(bool))); | 292 | disconnect(webPage, SIGNAL(loadFinished(bool)), this, SLOT(slotLoadFinishedHtmlParser(bool))); | ||
271 | 293 | | |||
272 | return !(m_errors & Errors::URL || m_errors & Errors::Price | 294 | return !(m_errors & Errors::URL || m_errors & Errors::Price | ||
273 | || m_errors & Errors::Date || m_errors & Errors::Data); | 295 | || m_errors & Errors::Date || m_errors & Errors::Data); | ||
274 | } | 296 | } | ||
275 | 297 | | |||
276 | bool AlkOnlineQuote::Private::launchNative(const QString &_symbol, const QString &_id, | 298 | bool AlkOnlineQuote::Private::launchNative(const QString &_symbol, const QString &_id, | ||
Show All 19 Lines | 317 | if (m_filter.waitForStarted()) { | |||
296 | result = true; | 318 | result = true; | ||
297 | } else { | 319 | } else { | ||
298 | emit m_p->error(i18n("Unable to launch: %1", url.toLocalFile())); | 320 | emit m_p->error(i18n("Unable to launch: %1", url.toLocalFile())); | ||
299 | m_errors |= Errors::Script; | 321 | m_errors |= Errors::Script; | ||
300 | result = slotParseQuote(QString()); | 322 | result = slotParseQuote(QString()); | ||
301 | } | 323 | } | ||
302 | } else { | 324 | } else { | ||
303 | slotLoadStarted(); | 325 | slotLoadStarted(); | ||
326 | result = downloadUrl(url); | ||||
327 | } | ||||
328 | return result; | ||||
329 | } | ||||
330 | | ||||
331 | bool AlkOnlineQuote::Private::processDownloadedFile(const KUrl& url, const QString& tmpFile) | ||||
332 | { | ||||
333 | bool result = false; | ||||
304 | 334 | | |||
305 | QString tmpFile; | | |||
306 | if (KIO::NetAccess::download(url, tmpFile, 0)) { | | |||
307 | // kDebug(Private::dbgArea()) << "Downloaded " << tmpFile; | | |||
308 | kDebug(Private::dbgArea()) << "Downloaded" << tmpFile << "from" << url; | | |||
309 | QFile f(tmpFile); | 335 | QFile f(tmpFile); | ||
310 | if (f.open(QIODevice::ReadOnly)) { | 336 | if (f.open(QIODevice::ReadOnly)) { | ||
311 | // Find out the page encoding and convert it to unicode | 337 | // Find out the page encoding and convert it to unicode | ||
312 | QByteArray page = f.readAll(); | 338 | QByteArray page = f.readAll(); | ||
313 | KEncodingProber prober(KEncodingProber::Universal); | 339 | KEncodingProber prober(KEncodingProber::Universal); | ||
314 | prober.feed(page); | 340 | prober.feed(page); | ||
315 | QTextCodec *codec = QTextCodec::codecForName(prober.encoding()); | 341 | QTextCodec *codec = QTextCodec::codecForName(prober.encoding()); | ||
316 | if (!codec) { | 342 | if (!codec) { | ||
317 | codec = QTextCodec::codecForLocale(); | 343 | codec = QTextCodec::codecForLocale(); | ||
318 | } | 344 | } | ||
319 | QString quote = codec->toUnicode(page); | 345 | QString quote = codec->toUnicode(page); | ||
320 | f.close(); | 346 | f.close(); | ||
321 | emit m_p->status(i18n("URL found: %1...", url.prettyUrl())); | 347 | emit m_p->status(i18n("URL found: %1...", url.prettyUrl())); | ||
KDE4 QUrl does not support prettyUrl(), only KUrl - may be toString() would also be okay habacker: KDE4 QUrl does not support prettyUrl(), only KUrl - may be toString() would also be okay | |||||
322 | if (AlkOnlineQuotesProfileManager::instance().webPageEnabled()) | 348 | if (AlkOnlineQuotesProfileManager::instance().webPageEnabled()) | ||
323 | AlkOnlineQuotesProfileManager::instance().webPage()->setContent(quote.toLocal8Bit()); | 349 | AlkOnlineQuotesProfileManager::instance().webPage()->setContent(quote.toLocal8Bit()); | ||
324 | result = slotParseQuote(quote); | 350 | result = slotParseQuote(quote); | ||
325 | } else { | 351 | } else { | ||
326 | emit m_p->error(i18n("Failed to open downloaded file")); | 352 | emit m_p->error(i18n("Failed to open downloaded file")); | ||
327 | m_errors |= Errors::URL; | 353 | m_errors |= Errors::URL; | ||
328 | result = slotParseQuote(QString()); | 354 | result = slotParseQuote(QString()); | ||
329 | } | 355 | } | ||
356 | return result; | ||||
357 | } | ||||
358 | | ||||
359 | #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) | ||||
360 | bool AlkOnlineQuote::Private::downloadUrl(const QUrl& url) | ||||
361 | { | ||||
362 | QTemporaryFile tmpFile; | ||||
363 | tmpFile.open(); | ||||
364 | auto tmpFileName = QUrl::fromLocalFile(tmpFile.fileName()); | ||||
365 | | ||||
366 | m_eventLoop = new QEventLoop; | ||||
367 | | ||||
368 | KJob *job = KIO::file_copy(url, tmpFileName, -1, KIO::HideProgressInfo | KIO::Overwrite); | ||||
369 | connect(job, SIGNAL(result(KJob*)), this, SLOT(downloadUrlDone(KJob*))); | ||||
370 | | ||||
371 | auto result = m_eventLoop->exec(QEventLoop::ExcludeUserInputEvents); | ||||
372 | delete m_eventLoop; | ||||
373 | m_eventLoop = nullptr; | ||||
374 | | ||||
375 | return result; | ||||
376 | } | ||||
377 | | ||||
378 | void AlkOnlineQuote::Private::downloadUrlDone(KJob* job) | ||||
379 | { | ||||
380 | QString tmpFileName = dynamic_cast<KIO::FileCopyJob*>(job)->destUrl().toLocalFile(); | ||||
381 | QUrl url = dynamic_cast<KIO::FileCopyJob*>(job)->srcUrl(); | ||||
382 | | ||||
383 | bool result; | ||||
384 | if (!job->error()) { | ||||
385 | qDebug() << "Downloaded" << tmpFileName << "from" << url; | ||||
386 | result = processDownloadedFile(url, tmpFileName); | ||||
387 | } else { | ||||
388 | emit m_p->error(job->errorString()); | ||||
389 | m_errors |= Errors::URL; | ||||
390 | result = slotParseQuote(QString()); | ||||
391 | } | ||||
392 | m_eventLoop->exit(result); | ||||
393 | } | ||||
394 | | ||||
395 | #else | ||||
396 | | ||||
397 | // This is simply a placeholder. It is unused but needs to be present | ||||
398 | // to make the linker happy (since the declaration of the slot cannot | ||||
399 | // be made dependendant on QT_VERSION with the Qt4 moc compiler. | ||||
400 | void AlkOnlineQuote::Private::downloadUrlDone(KJob* job) | ||||
401 | { | ||||
402 | } | ||||
403 | | ||||
404 | bool AlkOnlineQuote::Private::downloadUrl(const KUrl& url) | ||||
405 | { | ||||
406 | bool result = false; | ||||
407 | | ||||
408 | QString tmpFile; | ||||
409 | if (KIO::NetAccess::download(url, tmpFile, 0)) { | ||||
410 | // kDebug(Private::dbgArea()) << "Downloaded " << tmpFile; | ||||
411 | kDebug(Private::dbgArea()) << "Downloaded" << tmpFile << "from" << url; | ||||
412 | result = processDownloadedFile(url, tmpFile); | ||||
330 | KIO::NetAccess::removeTempFile(tmpFile); | 413 | KIO::NetAccess::removeTempFile(tmpFile); | ||
331 | } else { | 414 | } else { | ||
332 | emit m_p->error(KIO::NetAccess::lastErrorString()); | 415 | emit m_p->error(KIO::NetAccess::lastErrorString()); | ||
333 | m_errors |= Errors::URL; | 416 | m_errors |= Errors::URL; | ||
334 | result = slotParseQuote(QString()); | 417 | result = slotParseQuote(QString()); | ||
335 | } | 418 | } | ||
336 | } | | |||
337 | return result; | 419 | return result; | ||
338 | } | 420 | } | ||
421 | #endif | ||||
339 | 422 | | |||
340 | bool AlkOnlineQuote::Private::launchFinanceQuote(const QString &_symbol, const QString &_id, | 423 | bool AlkOnlineQuote::Private::launchFinanceQuote(const QString &_symbol, const QString &_id, | ||
341 | const QString &_sourcename) | 424 | const QString &_sourcename) | ||
342 | { | 425 | { | ||
343 | bool result = true; | 426 | bool result = true; | ||
344 | m_symbol = _symbol; | 427 | m_symbol = _symbol; | ||
345 | m_id = _id; | 428 | m_id = _id; | ||
346 | m_errors = Errors::None; | 429 | m_errors = Errors::None; | ||
▲ Show 20 Lines • Show All 238 Lines • Show Last 20 Lines |
With KDE4 moc ignores #if and includes this slot. It need to be defined also for KDE4 with an empty implementation.