31 #include <QApplication>
36 #include <QTextStream>
39 #include <KConfigGroup>
41 #include <KEncodingProber>
43 #include <kio/netaccess.h>
44 #include <kio/scheduler.h>
66 if (!m_type.contains(t)) {
74 return m_type.contains(t);
99 static int s_area = KDebug::registerArea(
"Alkimia (AlkOnlineQuote)");
117 bool initLaunch(
const QString &_symbol,
const QString &_id,
const QString &_source);
119 const QString &_source);
121 bool launchNative(
const QString &_symbol,
const QString &_id,
const QString &_source);
122 bool launchFinanceQuote(
const QString &_symbol,
const QString &_id,
const QString &_source);
140 emit m_p->status(QString(
"(Debug) symbol=%1 id=%2...").arg(_symbol, _id));
143 QString source = _source;
144 if (source.isEmpty()) {
145 source =
"KMyMoney Currency";
148 if (!m_profile->quoteSources().contains(source)) {
149 emit m_p->error(i18n(
"Source <placeholder>%1</placeholder> does not exist.", source));
160 if (m_source.url().contains(
"%2")) {
163 QRegExp splitrx(
"([0-9a-z\\.]+)[^a-z0-9]+([0-9a-z\\.]+)", Qt::CaseInsensitive);
165 if (splitrx.indexIn(m_symbol) != -1) {
166 url = KUrl(m_source.url().arg(splitrx.cap(1), splitrx.cap(2)));
168 kDebug(
Private::dbgArea()) <<
"WebPriceQuote::launch() did not find 2 symbols";
172 url = KUrl(m_source.url().arg(m_symbol));
183 emit m_p->error(i18n(
"Unable to fetch url for %1").arg(m_symbol));
185 emit m_p->failed(m_id, m_symbol);
197 emit m_p->error(i18n(
"Unable to fetch url for %1").arg(m_symbol));
199 emit m_p->failed(m_id, m_symbol);
204 if (!symbol.isEmpty()) {
205 emit m_p->status(i18n(
"Symbol found: '%1'", symbol));
208 emit m_p->error(i18n(
"Unable to parse symbol for %1", m_symbol));
213 bool gotprice = parsePrice(price);
217 bool gotdate = parseDate(date);
219 if (gotprice && gotdate) {
220 emit m_p->quote(m_id, m_symbol, m_date, m_price);
222 emit m_p->failed(m_id, m_symbol);
231 emit m_p->status(i18n(
"Fetching URL %1...", m_url.prettyUrl()));
235 const QString &_source)
237 if (!initLaunch(_symbol, _id, _source)) {
241 connect(webPage, SIGNAL(loadStarted()),
this, SLOT(slotLoadStarted()));
242 connect(webPage, SIGNAL(loadFinished(
bool)),
this,
243 SLOT(slotLoadFinishedCssSelector(
bool)));
244 webPage->setUrl(m_url);
245 m_eventLoop =
new QEventLoop;
248 disconnect(webPage, SIGNAL(loadStarted()),
this, SLOT(slotLoadStarted()));
249 disconnect(webPage, SIGNAL(loadFinished(
bool)),
this,
250 SLOT(slotLoadFinishedCssSelector(
bool)));
257 const QString &_source)
259 if (!initLaunch(_symbol, _id, _source)) {
263 connect(webPage, SIGNAL(loadStarted()),
this, SLOT(slotLoadStarted()));
264 connect(webPage, SIGNAL(loadFinished(
bool)),
this, SLOT(slotLoadFinishedHtmlParser(
bool)));
265 webPage->
load(m_url, m_acceptLanguage);
266 m_eventLoop =
new QEventLoop;
269 disconnect(webPage, SIGNAL(loadStarted()),
this, SLOT(slotLoadStarted()));
270 disconnect(webPage, SIGNAL(loadFinished(
bool)),
this, SLOT(slotLoadFinishedHtmlParser(
bool)));
277 const QString &_source)
280 if (!initLaunch(_symbol, _id, _source)) {
285 if (url.isLocalFile()) {
286 emit m_p->status(i18nc(
"The process x is executing",
"Executing %1...", url.toLocalFile()));
288 m_filter.clearProgram();
289 m_filter << url.toLocalFile().split(
' ', QString::SkipEmptyParts);
290 m_filter.setSymbol(m_symbol);
292 m_filter.setOutputChannelMode(KProcess::MergedChannels);
295 if (m_filter.waitForStarted()) {
298 emit m_p->error(i18n(
"Unable to launch: %1", url.toLocalFile()));
300 result = slotParseQuote(QString());
306 if (KIO::NetAccess::download(url, tmpFile, 0)) {
310 if (f.open(QIODevice::ReadOnly)) {
312 QByteArray page = f.readAll();
313 KEncodingProber prober(KEncodingProber::Universal);
315 QTextCodec *codec = QTextCodec::codecForName(prober.encoding());
317 codec = QTextCodec::codecForLocale();
319 QString
quote = codec->toUnicode(page);
321 emit m_p->status(i18n(
"URL found: %1...", url.prettyUrl()));
324 result = slotParseQuote(
quote);
326 emit m_p->error(i18n(
"Failed to open downloaded file"));
328 result = slotParseQuote(QString());
330 KIO::NetAccess::removeTempFile(tmpFile);
332 emit m_p->error(KIO::NetAccess::lastErrorString());
334 result = slotParseQuote(QString());
341 const QString &_sourcename)
348 QString FQSource = _sourcename.section(
' ', 1);
351 "[^,]*,[^,]*,\"([^\"]*)\"",
357 m_filter.clearProgram();
358 m_filter <<
"perl" << m_financeQuoteScriptPath << FQSource << KShell::quoteArg(_symbol);
359 m_filter.setSymbol(m_symbol);
360 emit m_p->status(i18nc(
"Executing 'script' 'online source' 'investment symbol' ",
361 "Executing %1 %2 %3...", m_financeQuoteScriptPath, FQSource, _symbol));
363 m_filter.setOutputChannelMode(KProcess::MergedChannels);
367 if (m_filter.waitForFinished()) {
369 emit m_p->error(i18n(
"Unable to launch: %1", m_financeQuoteScriptPath));
371 result = slotParseQuote(QString());
374 Q_UNUSED(_sourcename);
375 #if !defined(Q_CC_MSVC)
376 #warning to be implemented
393 QString pricestr(_pricestr);
394 if (!pricestr.isEmpty()) {
395 int pos = pricestr.lastIndexOf(QRegExp(
"\\D"));
398 pos = pricestr.lastIndexOf(QRegExp(
"\\D"), pos - 1);
401 pricestr.remove(pos, 1);
402 pos = pricestr.lastIndexOf(QRegExp(
"\\D"), pos);
405 m_price = pricestr.toDouble();
407 emit m_p->status(i18n(
"Price found: '%1' (%2)", pricestr, m_price));
410 emit m_p->error(i18n(
"Unable to parse price for '%1'", m_symbol));
418 if (!datestr.isEmpty()) {
419 emit m_p->status(i18n(
"Date found: '%1'", datestr));
425 emit m_p->status(i18n(
"Date format found: '%1' -> '%2'", datestr, m_date.toString()));
428 emit m_p->error(i18n(
"Unable to parse date '%1' using format '%2': %3").arg(datestr,
431 m_date = QDate::currentDate();
432 emit m_p->status(i18n(
"Using current date for '%1'").arg(m_symbol));
436 emit m_p->error(i18n(
"Unable to parse date for '%1'").arg(m_symbol));
437 m_date = QDate::currentDate();
438 emit m_p->status(i18n(
"Using current date for '%1'").arg(m_symbol));
452 QString quotedata = _quotedata;
453 m_quoteData = quotedata;
454 bool gotprice =
false;
455 bool gotdate =
false;
460 if (!quotedata.isEmpty()) {
461 if (!m_source.skipStripping()) {
467 quotedata.remove(QRegExp(
"<[^>]*>"));
470 quotedata.replace(QRegExp(
"&\\w+;"),
" ");
473 quotedata = quotedata.simplified();
477 QRegExp symbolRegExp(m_source.sym());
478 QRegExp dateRegExp(m_source.date());
479 QRegExp priceRegExp(m_source.price());
481 if (symbolRegExp.indexIn(quotedata) > -1) {
483 emit m_p->status(i18n(
"Symbol found: '%1'", symbolRegExp.cap(1)));
486 emit m_p->error(i18n(
"Unable to parse symbol for %1", m_symbol));
489 if (priceRegExp.indexIn(quotedata) > -1) {
491 QString pricestr = priceRegExp.cap(1);
492 parsePrice(pricestr);
494 parsePrice(QString());
497 if (dateRegExp.indexIn(quotedata) > -1) {
499 QString datestr = dateRegExp.cap(1);
502 parseDate(QString());
505 if (gotprice && gotdate) {
506 emit m_p->quote(m_id, m_symbol, m_date, m_price);
508 emit m_p->failed(m_id, m_symbol);
513 emit m_p->error(i18n(
"Unable to update price for %1 (empty quote data)", m_symbol));
514 emit m_p->failed(m_id, m_symbol);
568 if (_source.contains(
"Finance::Quote")) {
570 }
else if (_source.endsWith(
".css")) {
572 }
else if (_source.endsWith(
".webkit")) {
584 #include "alkonlinequote.moc"