diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-03-01 19:17:32 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-03-01 19:17:32 +0000 |
commit | e38d2351b83fa65c66ccde443777647ef5cb6cff (patch) | |
tree | 1897fc20e9f73a81c520a5b9f76f8ed042124883 /src/fetch/yahoofetcher.cpp | |
download | tellico-e38d2351b83fa65c66ccde443777647ef5cb6cff.tar.gz tellico-e38d2351b83fa65c66ccde443777647ef5cb6cff.zip |
Added KDE3 version of Tellico
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/tellico@1097620 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/fetch/yahoofetcher.cpp')
-rw-r--r-- | src/fetch/yahoofetcher.cpp | 400 |
1 files changed, 400 insertions, 0 deletions
diff --git a/src/fetch/yahoofetcher.cpp b/src/fetch/yahoofetcher.cpp new file mode 100644 index 0000000..002b63b --- /dev/null +++ b/src/fetch/yahoofetcher.cpp @@ -0,0 +1,400 @@ +/*************************************************************************** + copyright : (C) 2006 by Robby Stephenson + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of version 2 of the GNU General Public License as * + * published by the Free Software Foundation; * + * * + ***************************************************************************/ + +#include "yahoofetcher.h" +#include "messagehandler.h" +#include "../translators/xslthandler.h" +#include "../translators/tellicoimporter.h" +#include "../imagefactory.h" +#include "../tellico_kernel.h" +#include "../tellico_utils.h" +#include "../collection.h" +#include "../entry.h" +#include "../tellico_debug.h" + +#include <klocale.h> +#include <kstandarddirs.h> +#include <kconfig.h> +#include <kio/job.h> + +#include <qdom.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qfile.h> + +namespace { + static const int YAHOO_MAX_RETURNS_TOTAL = 20; + static const char* YAHOO_BASE_URL = "http://search.yahooapis.com/AudioSearchService/V1/albumSearch"; + static const char* YAHOO_APP_ID = "tellico-robby"; +} + +using Tellico::Fetch::YahooFetcher; + +YahooFetcher::YahooFetcher(QObject* parent_, const char* name_) + : Fetcher(parent_, name_), m_xsltHandler(0), + m_limit(YAHOO_MAX_RETURNS_TOTAL), m_job(0), m_started(false) { +} + +YahooFetcher::~YahooFetcher() { + delete m_xsltHandler; + m_xsltHandler = 0; +} + +QString YahooFetcher::defaultName() { + return i18n("Yahoo! Audio Search"); +} + +QString YahooFetcher::source() const { + return m_name.isEmpty() ? defaultName() : m_name; +} + +bool YahooFetcher::canFetch(int type) const { + return type == Data::Collection::Album; +} + +void YahooFetcher::readConfigHook(const KConfigGroup& config_) { + Q_UNUSED(config_); +} + +void YahooFetcher::search(FetchKey key_, const QString& value_) { + m_key = key_; + m_value = value_; + m_started = true; + m_start = 1; + m_total = -1; + doSearch(); +} + +void YahooFetcher::continueSearch() { + m_started = true; + doSearch(); +} + +void YahooFetcher::doSearch() { +// myDebug() << "YahooFetcher::search() - value = " << value_ << endl; + + KURL u(QString::fromLatin1(YAHOO_BASE_URL)); + u.addQueryItem(QString::fromLatin1("appid"), QString::fromLatin1(YAHOO_APP_ID)); + u.addQueryItem(QString::fromLatin1("type"), QString::fromLatin1("all")); + u.addQueryItem(QString::fromLatin1("output"), QString::fromLatin1("xml")); + u.addQueryItem(QString::fromLatin1("start"), QString::number(m_start)); + u.addQueryItem(QString::fromLatin1("results"), QString::number(YAHOO_MAX_RETURNS_TOTAL)); + + if(!canFetch(Kernel::self()->collectionType())) { + message(i18n("%1 does not allow searching for this collection type.").arg(source()), MessageHandler::Warning); + stop(); + return; + } + + switch(m_key) { + case Title: + u.addQueryItem(QString::fromLatin1("album"), m_value); + break; + + case Person: + u.addQueryItem(QString::fromLatin1("artist"), m_value); + break; + + // raw is used for the entry updates + case Raw: +// u.removeQueryItem(QString::fromLatin1("type")); +// u.addQueryItem(QString::fromLatin1("type"), QString::fromLatin1("phrase")); + u.setQuery(u.query() + '&' + m_value); + break; + + default: + kdWarning() << "YahooFetcher::search() - key not recognized: " << m_key << endl; + stop(); + return; + } +// myDebug() << "YahooFetcher::search() - url: " << u.url() << endl; + + m_job = KIO::get(u, false, false); + connect(m_job, SIGNAL(data(KIO::Job*, const QByteArray&)), + SLOT(slotData(KIO::Job*, const QByteArray&))); + connect(m_job, SIGNAL(result(KIO::Job*)), + SLOT(slotComplete(KIO::Job*))); +} + +void YahooFetcher::stop() { + if(!m_started) { + return; + } + if(m_job) { + m_job->kill(); + m_job = 0; + } + m_data.truncate(0); + m_started = false; + emit signalDone(this); +} + +void YahooFetcher::slotData(KIO::Job*, const QByteArray& data_) { + QDataStream stream(m_data, IO_WriteOnly | IO_Append); + stream.writeRawBytes(data_.data(), data_.size()); +} + +void YahooFetcher::slotComplete(KIO::Job* job_) { +// myDebug() << "YahooFetcher::slotComplete()" << endl; + // since the fetch is done, don't worry about holding the job pointer + m_job = 0; + + if(job_->error()) { + job_->showErrorDialog(Kernel::self()->widget()); + stop(); + return; + } + + if(m_data.isEmpty()) { + myDebug() << "YahooFetcher::slotComplete() - no data" << endl; + stop(); + return; + } + +#if 0 + kdWarning() << "Remove debug from yahoofetcher.cpp" << endl; + QFile f(QString::fromLatin1("/tmp/test.xml")); + if(f.open(IO_WriteOnly)) { + QTextStream t(&f); + t.setEncoding(QTextStream::UnicodeUTF8); + t << QCString(m_data, m_data.size()+1); + } + f.close(); +#endif + + if(!m_xsltHandler) { + initXSLTHandler(); + if(!m_xsltHandler) { // probably an error somewhere in the stylesheet loading + stop(); + return; + } + } + + if(m_total == -1) { + QDomDocument dom; + if(!dom.setContent(m_data, false)) { + kdWarning() << "YahooFetcher::slotComplete() - server did not return valid XML." << endl; + return; + } + // total is top level element, with attribute totalResultsAvailable + QDomElement e = dom.documentElement(); + if(!e.isNull()) { + m_total = e.attribute(QString::fromLatin1("totalResultsAvailable")).toInt(); + } + } + + // assume yahoo is always utf-8 + QString str = m_xsltHandler->applyStylesheet(QString::fromUtf8(m_data, m_data.size())); + Import::TellicoImporter imp(str); + Data::CollPtr coll = imp.collection(); + if(!coll) { + myDebug() << "YahooFetcher::slotComplete() - no collection pointer" << endl; + stop(); + return; + } + + int count = 0; + Data::EntryVec entries = coll->entries(); + for(Data::EntryVec::Iterator entry = entries.begin(); count < m_limit && entry != entries.end(); ++entry, ++count) { + if(!m_started) { + // might get aborted + break; + } + QString desc = entry->field(QString::fromLatin1("artist")) + + QChar('/') + + entry->field(QString::fromLatin1("label")) + + QChar('/') + + entry->field(QString::fromLatin1("year")); + + SearchResult* r = new SearchResult(this, entry->title(), desc, entry->field(QString::fromLatin1("isbn"))); + m_entries.insert(r->uid, Data::EntryPtr(entry)); + emit signalResultFound(r); + } + m_start = m_entries.count() + 1; + m_hasMoreResults = m_start <= m_total; + stop(); // required +} + +Tellico::Data::EntryPtr YahooFetcher::fetchEntry(uint uid_) { + Data::EntryPtr entry = m_entries[uid_]; + if(!entry) { + kdWarning() << "YahooFetcher::fetchEntry() - no entry in dict" << endl; + return 0; + } + + KURL imageURL = entry->field(QString::fromLatin1("image")); + if(!imageURL.isEmpty()) { + QString id = ImageFactory::addImage(imageURL, true); + if(id.isEmpty()) { + // rich text causes layout issues +// emit signalStatus(i18n("<qt>The cover image for <i>%1</i> could not be loaded.</qt>").arg( +// entry->field(QString::fromLatin1("title")))); + message(i18n("The cover image could not be loaded."), MessageHandler::Warning); + } else { + entry->setField(QString::fromLatin1("cover"), id); + } + } + + getTracks(entry); + + // don't want to show image urls in the fetch dialog + entry->setField(QString::fromLatin1("image"), QString::null); + // no need for album id now ? + entry->setField(QString::fromLatin1("yahoo"), QString::null); + return entry; +} + +void YahooFetcher::initXSLTHandler() { + QString xsltfile = locate("appdata", QString::fromLatin1("yahoo2tellico.xsl")); + if(xsltfile.isEmpty()) { + kdWarning() << "YahooFetcher::initXSLTHandler() - can not locate yahoo2tellico.xsl." << endl; + return; + } + + KURL u; + u.setPath(xsltfile); + + delete m_xsltHandler; + m_xsltHandler = new XSLTHandler(u); + if(!m_xsltHandler->isValid()) { + kdWarning() << "YahooFetcher::initXSLTHandler() - error in yahoo2tellico.xsl." << endl; + delete m_xsltHandler; + m_xsltHandler = 0; + return; + } +} + +void YahooFetcher::getTracks(Data::EntryPtr entry_) { + // get album id + if(!entry_ || entry_->field(QString::fromLatin1("yahoo")).isEmpty()) { + return; + } + + const QString albumid = entry_->field(QString::fromLatin1("yahoo")); + + KURL u(QString::fromLatin1(YAHOO_BASE_URL)); + u.setFileName(QString::fromLatin1("songSearch")); + u.addQueryItem(QString::fromLatin1("appid"), QString::fromLatin1(YAHOO_APP_ID)); + u.addQueryItem(QString::fromLatin1("type"), QString::fromLatin1("all")); + u.addQueryItem(QString::fromLatin1("output"), QString::fromLatin1("xml")); + // go ahesad and ask for all results, since there might well be more than 10 songs on the CD + u.addQueryItem(QString::fromLatin1("results"), QString::number(50)); + u.addQueryItem(QString::fromLatin1("albumid"), albumid); + +// myDebug() << "YahooFetcher::getTracks() - url: " << u.url() << endl; + QDomDocument dom = FileHandler::readXMLFile(u, false /*no namespace*/, true /*quiet*/); + if(dom.isNull()) { + myDebug() << "YahooFetcher::getTracks() - null dom returned" << endl; + return; + } + +#if 0 + kdWarning() << "Remove debug from yahoofetcher.cpp" << endl; + QFile f(QString::fromLatin1("/tmp/test.xml")); + if(f.open(IO_WriteOnly)) { + QTextStream t(&f); + t.setEncoding(QTextStream::UnicodeUTF8); + t << dom.toString(); + } + f.close(); +#endif + + const QString track = QString::fromLatin1("track"); + + QDomNodeList nodes = dom.documentElement().childNodes(); + for(uint i = 0; i < nodes.count(); ++i) { + QDomElement e = nodes.item(i).toElement(); + if(e.isNull()) { + continue; + } + QString t = e.namedItem(QString::fromLatin1("Title")).toElement().text(); + QString n = e.namedItem(QString::fromLatin1("Track")).toElement().text(); + bool ok; + int trackNum = Tellico::toUInt(n, &ok); + // trackNum might be 0 + if(t.isEmpty() || !ok || trackNum < 1) { + continue; + } + QString a = e.namedItem(QString::fromLatin1("Artist")).toElement().text(); + QString l = e.namedItem(QString::fromLatin1("Length")).toElement().text(); + + int len = Tellico::toUInt(l, &ok); + QString value = t + "::" + a; + if(ok && len > 0) { + value += + "::" + Tellico::minutes(len); + } + entry_->setField(track, insertValue(entry_->field(track), value, trackNum)); + } +} + +// not zero-based +QString YahooFetcher::insertValue(const QString& str_, const QString& value_, uint pos_) { + QStringList list = Data::Field::split(str_, true); + for(uint i = list.count(); i < pos_; ++i) { + list += QString::null; + } + bool write = true; + if(!list[pos_-1].isNull()) { + // for some reason, some songs are repeated from yahoo, with 0 length, don't overwrite that + if(value_.contains(QString::fromLatin1("::")) < 2) { // means no length value + write = false; + } + } + if(!value_.isEmpty() && write) { + list[pos_-1] = value_; + } + return list.join(QString::fromLatin1("; ")); +} + +void YahooFetcher::updateEntry(Data::EntryPtr entry_) { +// myDebug() << "YahooFetcher::updateEntry()" << endl; + // limit to top 5 results + m_limit = 5; + + QString value; + QString title = entry_->field(QString::fromLatin1("title")); + if(!title.isEmpty()) { + value += QString::fromLatin1("album=") + title; + } + QString artist = entry_->field(QString::fromLatin1("artist")); + if(!artist.isEmpty()) { + if(!value.isEmpty()) { + value += '&'; + } + value += QString::fromLatin1("artist=") + artist; + } + if(!value.isEmpty()) { + search(Fetch::Raw, value); + return; + } + + myDebug() << "YahooFetcher::updateEntry() - insufficient info to search" << endl; + emit signalDone(this); // always need to emit this if not continuing with the search +} + +Tellico::Fetch::ConfigWidget* YahooFetcher::configWidget(QWidget* parent_) const { + return new YahooFetcher::ConfigWidget(parent_, this); +} + +YahooFetcher::ConfigWidget::ConfigWidget(QWidget* parent_, const YahooFetcher*/*=0*/) + : Fetch::ConfigWidget(parent_) { + QVBoxLayout* l = new QVBoxLayout(optionsWidget()); + l->addWidget(new QLabel(i18n("This source has no options."), optionsWidget())); + l->addStretch(); +} + +QString YahooFetcher::ConfigWidget::preferredName() const { + return YahooFetcher::defaultName(); +} + +#include "yahoofetcher.moc" |