Index: mythnews/mythnews/newsengine.cpp =================================================================== --- mythnews/mythnews/newsengine.cpp (revision 18874) +++ mythnews/mythnews/newsengine.cpp (working copy) @@ -8,8 +8,6 @@ // QT headers #include #include -#include -#include // Myth headers #include @@ -41,38 +39,41 @@ { } -NewsSite::NewsSite(const QString &name, - const QString &url, +NewsArticle::NewsArticle() : + m_title(QString::null), + m_desc(QString::null), + m_articleURL(QString::null), + m_thumbnail(QString::null), + m_mediaURL(QString::null), + m_enclosure(QString::null) +{ +} + +NewsSite::NewsSite(const QString &name, + const QString &url, const QDateTime &updated, - const bool &podcast) - : QObject() + const bool podcast) : + QObject(), m_name(name), m_url(url), m_urlReq(url), + m_desc(QString::null), m_updated(updated), + m_destDir(GetConfDir()+"/MythNews"), + /*m_data(),*/ + m_state(NewsSite::Success), + m_errorString(QString::null), + m_imageURL(""), + m_podcast(podcast) { - m_url = url; - m_name = name; - m_updated = updated; - m_podcast = podcast; - m_state = NewsSite::Success; +} - m_destDir = GetConfDir(); - m_destDir += "/MythNews"; - +void NewsSite::deleteLater() +{ + HttpPool::GetSingleton()->RemoveListener(this); m_articleList.clear(); - - m_data.resize(0); - m_urlOp = new Q3UrlOperator(m_url); - - connect(m_urlOp, SIGNAL(data(const QByteArray&, Q3NetworkOperation*)), - this, SLOT(slotGotData(const QByteArray&, Q3NetworkOperation*))); - connect(m_urlOp, SIGNAL(finished(Q3NetworkOperation*)), - this, SLOT(slotFinished(Q3NetworkOperation*))); + QObject::deleteLater(); } NewsSite::~NewsSite() { - m_urlOp->disconnect(this, 0, 0, 0); - m_urlOp->stop(); - m_urlOp->deleteLater(); - m_articleList.clear(); + HttpPool::GetSingleton()->RemoveListener(this); } void NewsSite::insertNewsArticle(const NewsArticle &item) @@ -131,16 +132,16 @@ void NewsSite::retrieve(void) { stop(); - m_state = NewsSite::Retrieving; m_data.resize(0); m_articleList.clear(); - m_urlOp->get(m_url); + m_urlReq = QUrl(m_url); + HttpPool::GetSingleton()->AddURLRequest(m_urlReq, this); } void NewsSite::stop(void) { - m_urlOp->stop(); + HttpPool::GetSingleton()->RemoveURLRequest(m_urlReq, this); } bool NewsSite::successful(void) const @@ -153,16 +154,34 @@ return m_errorString; } -void NewsSite::slotFinished(Q3NetworkOperation* op) +void NewsSite::Updated(QHttp::Error error, + const QUrl &url, + const QByteArray &data) { - if (op->state() == Q3NetworkProtocol::StDone && - op->errorCode() == Q3NetworkProtocol::NoError) + if (url != m_urlReq) { + return; + } - QFile xmlFile(m_destDir+QString("/")+m_name); - if (xmlFile.open( QIODevice::WriteOnly )) { - QDataStream stream( &xmlFile ); - stream.writeRawData(m_data.constData(), m_data.size()); + if (QHttp::NoError != error) + { + m_state = NewsSite::RetrieveFailed; + emit finished(this); + return; + } + + m_data = data; + + if (m_name.isEmpty()) + { + m_state = NewsSite::WriteFailed; + } + else + { + QFile xmlFile(QString("%1/%2").arg(m_destDir).arg(m_name)); + if (xmlFile.open(QIODevice::WriteOnly)) + { + xmlFile.write(m_data); xmlFile.close(); m_updated = QDateTime::currentDateTime(); m_state = NewsSite::Success; @@ -170,14 +189,12 @@ else { m_state = NewsSite::WriteFailed; - VERBOSE(VB_IMPORTANT, "MythNews: NewsEngine: Write failed"); } } - else - { - m_state = NewsSite::RetrieveFailed; - } + if (NewsSite::WriteFailed == m_state) + VERBOSE(VB_IMPORTANT, "MythNews: NewsEngine: Write failed"); + emit finished(this); } @@ -402,20 +419,6 @@ } } -void NewsSite::slotGotData(const QByteArray &data, - Q3NetworkOperation* op) -{ - if (op) - { - const char *charData = data.data(); - int len = data.count(); - - int size = m_data.size(); - m_data.resize(size + len); - memcpy(m_data.data()+size, charData, len); - } -} - void NewsSite::ReplaceHtmlChar(QString &s) { s.replace("&", "&"); Index: mythnews/mythnews/newsengine.h =================================================================== --- mythnews/mythnews/newsengine.h (revision 18874) +++ mythnews/mythnews/newsengine.h (working copy) @@ -15,6 +15,8 @@ class Q3NetworkOperation; class NewsSite; +#include "httppool.h" + class NewsArticle { public: @@ -25,6 +27,7 @@ const QString &thumbnail, const QString &mediaURL, const QString &enclosure); NewsArticle(const QString &title); + NewsArticle(); QString title(void) const { return m_title; } QString description(void) const { return m_desc; } @@ -45,7 +48,7 @@ // ------------------------------------------------------- -class NewsSite : public QObject +class NewsSite : public QObject, public HttpListener { Q_OBJECT @@ -72,8 +75,9 @@ } }; - NewsSite(const QString &name, const QString &url, - const QDateTime &updated, const bool &podcast); + NewsSite(const QString &name, const QString &url, + const QDateTime &updated, const bool podcast); + virtual void deleteLater(); QString url(void) const; QString name(void) const; @@ -96,11 +100,16 @@ bool successful(void) const; QString errorMsg(void) const; + virtual void Updated(QHttp::Error error, + const QUrl &url, + const QByteArray &data); + private: ~NewsSite(); QString m_name; QString m_url; + QUrl m_urlReq; QString m_desc; QDateTime m_updated; QString m_destDir; @@ -111,19 +120,11 @@ bool m_podcast; NewsArticle::List m_articleList; - Q3UrlOperator *m_urlOp; - void ReplaceHtmlChar( QString &s); signals: void finished(NewsSite* item); - - private slots: - - void slotFinished(Q3NetworkOperation*); - void slotGotData(const QByteArray &data, - Q3NetworkOperation* op); }; class NewsSiteItem Index: mythnews/mythnews/httppool.cpp =================================================================== --- mythnews/mythnews/httppool.cpp (revision 0) +++ mythnews/mythnews/httppool.cpp (revision 0) @@ -0,0 +1,155 @@ +#include "httppool.h" +#include "httphandler.h" + +// Myth headers +#include + +#define LOC QString("HttpPool: ") +#define LOC_WARN QString("HttpPool, Warning: ") +#define LOC_ERR QString("HttpPool, Error: ") + +HttpPool *HttpPool::singleton; + +HttpPool::HttpPool(uint max_connections) : m_maxConnections(max_connections) +{ +} + +HttpPool::~HttpPool() +{ + while (!m_hostToHandler.empty()) + { + HostToHandler::iterator it = m_hostToHandler.begin(); + HttpHandler *h = *it; + m_hostToHandler.erase(it); + h->deleteLater(); + } +} + +void HttpPool::AddURLRequest(const QUrl &url, HttpListener *listener) +{ + QMutexLocker locker(&m_lock); + + VERBOSE(VB_NETWORK, LOC + QString("AddUrlRequest(%1, 0x%2)") + .arg(url.toString()).arg((uint64_t)listener,0,16)); + + bool in_queue = m_urlToListener.find(url) != m_urlToListener.end(); + + m_urlToListener.insert(url, listener); + set::iterator lit = m_listeners.find(listener); + if (lit == m_listeners.end()) + m_listeners.insert(listener); + + if (in_queue) + return; + + HostToHandler::iterator it = m_hostToHandler.find(url.host()); + + if (it != m_hostToHandler.end()) + { + (*it)->AddURLRequest(url); + } + else if ((uint)m_hostToHandler.size() < m_maxConnections) + { + HttpHandler *hh = new HttpHandler(this); + m_hostToHandler[url.host()] = hh; + hh->AddURLRequest(url); + } + else + { + HostToHandler::iterator it = m_hostToHandler.begin(); + for (; it != m_hostToHandler.end(); ++it) + { + if (!(*it)->HasPendingRequests()) + break; + } + if (it != m_hostToHandler.end()) + { + HttpHandler *hh = *it; + m_hostToHandler.erase(it); + m_hostToHandler[url.host()] = hh; + hh->AddURLRequest(url); + } + else + { + m_httpQueue.push_back(HttpRequest(url,listener)); + } + } +} + +void HttpPool::RemoveURLRequest(const QUrl &url, HttpListener *listener) +{ + QMutexLocker locker(&m_lock); + + VERBOSE(VB_NETWORK, LOC + QString("RemoveUrlRequest(%1, 0x%2)") + .arg(url.toString()).arg((uint64_t)listener,0,16)); +} + +void HttpPool::RemoveListener(HttpListener *listener) +{ + QMutexLocker locker(&m_lock); + + VERBOSE(VB_NETWORK, LOC + QString("RemoveListener(0x%1)") + .arg((uint64_t)listener,0,16)); + set::iterator it = m_listeners.find(listener); + if (it != m_listeners.end()) + m_listeners.erase(it); +} + +void HttpPool::Update(QHttp::Error error, + const QUrl &url, + const QByteArray &data) +{ + QMutexLocker locker(&m_lock); + + UrlToListener::iterator it = m_urlToListener.find(url); + for (; (it != m_urlToListener.end()) && (it.key() == url); ++it) + { + HttpListener *listener = *it; + if (m_listeners.find(listener) != m_listeners.end()) + listener->Updated(error, url, data); + } + m_urlToListener.remove(url); +} + +void HttpPool::Done(const QString &host, HttpHandler *handler) +{ + QMutexLocker locker(&m_lock); + + VERBOSE(VB_NETWORK, LOC + QString("Done(%1, 0x%2)") + .arg(host).arg((uint64_t)handler,0,16)); + + HostToHandler::iterator it = m_hostToHandler.find(host); + if (handler != *it) + { + VERBOSE(VB_IMPORTANT, LOC_ERR + QString("Done(%1, 0x%2)") + .arg(host).arg((uint64_t)handler,0,16)); + return; + } + + while (!m_httpQueue.empty()) + { + QUrl url = m_httpQueue.front().m_url; + HttpListener *listener = m_httpQueue.front().m_listener; + m_httpQueue.pop_front(); + + if (m_listeners.find(listener) == m_listeners.end()) + continue; + + if (url.host() != host) + { + m_hostToHandler.erase(it); + m_hostToHandler[url.host()] = handler; + } + handler->AddURLRequest(url); + break; + } +} + +HttpPool *HttpPool::GetSingleton() +{ + static QMutex lock; + QMutexLocker locker(&lock); + if (!singleton) + singleton = new HttpPool(); + return singleton; +} Index: mythnews/mythnews/httphandler.cpp =================================================================== --- mythnews/mythnews/httphandler.cpp (revision 0) +++ mythnews/mythnews/httphandler.cpp (revision 0) @@ -0,0 +1,151 @@ +#include "httphandler.h" +#include "httppool.h" + +// Qt headers +#include + +// Myth headers +#include + +#define LOC QString("HttpHandler: ") +#define LOC_WARN QString("HttpHandler, Warning: ") +#define LOC_ERR QString("HttpHandler, Error: ") + +////////////////////////////////////////////////////////////////////// + +HttpHandler::HttpHandler(HttpPool *pool) : + m_pool(pool), m_qhttp(new QHttp()) +{ + connect(m_qhttp, SIGNAL(done(bool)), + this, SLOT(Done(bool))); + connect(m_qhttp, SIGNAL(requestFinished(int,bool)), + this, SLOT(RequestFinished(int,bool))); + connect(m_qhttp, SIGNAL(requestStarted(int)), + this, SLOT(RequestStarted(int))); + connect(m_qhttp, SIGNAL(stateChanged(int)), + this, SLOT(StateChanged(int))); + connect(m_qhttp, SIGNAL(responseHeaderReceived(const QHttpResponseHeader&)), + this, SLOT(ResponseHeaderReceived(const QHttpResponseHeader&))); +} + +void HttpHandler::TeardownAll(void) +{ + QMutexLocker locker(&m_lock); + + if (m_qhttp) + { + m_qhttp->abort(); + m_qhttp->disconnect(); + m_qhttp->deleteLater(); + } + m_pool = NULL; + m_qhttp = NULL; +} + +bool HttpHandler::HasPendingRequests(void) const +{ + QMutexLocker locker(&m_lock); + return m_qhttp->hasPendingRequests(); +} + +void HttpHandler::AddURLRequest(const QUrl &url) +{ + QMutexLocker locker(&m_lock); + + if (!m_qhttp->hasPendingRequests()) + Get(url); + else + m_urls.push_back(url); +} + +void HttpHandler::Get(const QUrl &url) +{ + m_cur_url = url; + m_cur_status_id = 0; + + m_qhttp->setHost(m_cur_url.host()); + + QString path = (m_cur_url.path().isEmpty()) ? "/" : m_cur_url.path(); + m_cur_get_id = m_qhttp->get(path); +} + +void HttpHandler::RemoveURLRequest(const QUrl &url) +{ + QMutexLocker locker(&m_lock); + + URLQueue urls = m_urls; + m_urls.clear(); + while (!urls.empty()) + { + QUrl item = urls.front(); + urls.pop_front(); + if (item != url) + m_urls.push_back(item); + } + + if (url == m_cur_url) + { + m_cur_url = QUrl(); + m_cur_status_id = 0; + m_cur_get_id = 0; + m_qhttp->abort(); + } +} + +void HttpHandler::Done(bool error) +{ + QMutexLocker locker(&m_lock); + + VERBOSE(VB_NETWORK, LOC + QString("Done(%1) url: %2") + .arg(error).arg(m_cur_url.toString())); + + if (m_pool) + m_pool->Done(m_cur_url.host(), this); +} + +void HttpHandler::ResponseHeaderReceived(const QHttpResponseHeader &resp) +{ + QMutexLocker locker(&m_lock); + + VERBOSE(VB_NETWORK, LOC + QString("ResponseHeaderReceived(%1,%2) url: %3") + .arg(resp.statusCode()).arg(resp.reasonPhrase()) + .arg(m_cur_url.toString())); + m_cur_status_id = resp.statusCode(); +} + +void HttpHandler::RequestFinished(int id, bool error) +{ + QMutexLocker locker(&m_lock); + + VERBOSE(VB_NETWORK, LOC + QString("RequestFinished(%1,%2) url: %3") + .arg(id).arg(error).arg(m_cur_url.toString())); + if (error && m_pool) + m_pool->Update(m_qhttp->error(), m_cur_url, QByteArray()); + else if ((id == m_cur_get_id) && m_pool) + m_pool->Update(QHttp::NoError, m_cur_url, m_qhttp->readAll()); + else + return; + + if (!m_urls.empty()) + { + Get(m_urls.front()); + m_urls.pop_front(); + } +} + +void HttpHandler::RequestStarted(int id) +{ + QMutexLocker locker(&m_lock); + + VERBOSE(VB_NETWORK, LOC + QString("RequestStarted(%1) url: %2") + .arg(id).arg(m_cur_url.toString())); +} + +void HttpHandler::StateChanged(int state) +{ + QMutexLocker locker(&m_lock); + + VERBOSE(VB_NETWORK, LOC + QString("StateChanged(%1) url: %2") + .arg(state).arg(m_cur_url.toString())); +} + Index: mythnews/mythnews/httppool.h =================================================================== --- mythnews/mythnews/httppool.h (revision 0) +++ mythnews/mythnews/httppool.h (revision 0) @@ -0,0 +1,65 @@ +#ifndef _HTTP_POOL_H_ +#define _HTTP_POOL_H_ + +// C++ headers +#include +#include +using namespace std; + +// Qt headers +#include +#include +#include +#include + +class HttpListener +{ + public: + virtual void Updated(QHttp::Error error, + const QUrl &url, + const QByteArray &data) = 0; +}; + +class HttpRequest +{ + public: + HttpRequest(const QUrl &url, HttpListener *listener) : + m_url(url), m_listener(listener) {} + + QUrl m_url; + HttpListener *m_listener; +}; + +class HttpHandler; +typedef QMap HostToHandler; +typedef QMultiMap UrlToListener; + +class HttpPool +{ + public: + HttpPool(uint max_connections = 20); + ~HttpPool(); + + void AddURLRequest(const QUrl &url, HttpListener *listener); + void RemoveURLRequest(const QUrl &url, HttpListener *listener); + void RemoveListener(HttpListener *listener); + + static HttpPool *GetSingleton(); + + void Update(QHttp::Error error, + const QUrl &url, + const QByteArray &data); + void Done(const QString &host, HttpHandler *handler); + + private: + mutable QMutex m_lock; + uint m_maxConnections; + deque m_httpQueue; + set m_listeners; + UrlToListener m_urlToListener; + HostToHandler m_hostToHandler; + + static HttpPool *singleton; +}; + +#endif // _HTTP_POOL_H_ Index: mythnews/mythnews/mythnews.cpp =================================================================== --- mythnews/mythnews/mythnews.cpp (revision 18874) +++ mythnews/mythnews/mythnews.cpp (working copy) @@ -179,35 +179,33 @@ return; NewsSite *site = NULL; - NewsArticle *article = NULL; + NewsArticle article; if (GetFocusWidget() == m_articlesList) { - article = qVariantValue(selected->GetData()); + article = m_articles[selected]; if (m_sitesList->GetItemCurrent()) site = qVariantValue - (m_sitesList->GetItemCurrent()->GetData()); + (m_sitesList->GetItemCurrent()->GetData()); } else { site = qVariantValue(selected->GetData()); if (m_articlesList->GetItemCurrent()) - article = qVariantValue - (m_articlesList->GetItemCurrent()->GetData()); + article = m_articles[m_articlesList->GetItemCurrent()]; } if (GetFocusWidget() == m_articlesList) { - - if (article) + if (!article.title().isEmpty()) { if (m_titleText) - m_titleText->SetText(article->title()); + m_titleText->SetText(article.title()); if (m_descText) { - QString artText = article->description(); + QString artText = article.description(); // Replace paragraph and break HTML with newlines if( artText.indexOf(QRegExp("")) ) { @@ -237,7 +235,7 @@ m_descText->SetText(artText); } - if (!article->thumbnail().isEmpty()) + if (!article.thumbnail().isEmpty()) { QString fileprefix = GetConfDir(); @@ -251,7 +249,7 @@ if (!dir.exists()) dir.mkdir(fileprefix); - QString url = article->thumbnail(); + QString url = article.thumbnail(); QString sFilename = QString("%1/%2") .arg(fileprefix) .arg(qChecksum(url.toLocal8Bit().constData(), @@ -309,7 +307,7 @@ } } - if (!article->enclosure().isEmpty()) + if (!article.enclosure().isEmpty()) { if (!m_downloadImage->IsVisible()) m_downloadImage->Show(); @@ -317,7 +315,7 @@ else m_downloadImage->Hide(); - if (!article->enclosure().isEmpty()) + if (!article.enclosure().isEmpty()) { if (!m_enclosureImage->IsVisible()) m_enclosureImage->Show(); @@ -547,13 +545,14 @@ return; m_articlesList->Reset(); + m_articles.clear(); NewsArticle::List::iterator it = site->articleList().begin(); for (; it != site->articleList().end(); ++it) { MythUIButtonListItem *item = new MythUIButtonListItem(m_articlesList, (*it).title()); - item->SetData(qVariantFromValue(&(*it))); + m_articles[item] = *it; } } @@ -567,13 +566,14 @@ return; m_articlesList->Reset(); + m_articles.clear(); NewsArticle::List::iterator it = site->articleList().begin(); for (; it != site->articleList().end(); ++it) { MythUIButtonListItem *item = new MythUIButtonListItem(m_articlesList, (*it).title()); - item->SetData(qVariantFromValue(&(*it))); + m_articles[item] = *it; } updateInfoView(item); @@ -689,82 +689,84 @@ void MythNews::slotViewArticle(MythUIButtonListItem *articlesListItem) { - if (articlesListItem && !articlesListItem->GetData().isNull()) - { - NewsArticle *article = qVariantValue - (articlesListItem->GetData()); - if(article) - { - if (!article->enclosure().isEmpty()) - { - QString cmdURL(article->enclosure()); - // Handle special cases for media here - // YouTube: Fetch the mediaURL page and parse out the video URL - if (cmdURL.contains("youtube.com")) - { - cmdURL = QString(article->mediaURL()); - QString mediaPage = HttpComms::getHttp(cmdURL); - if (!mediaPage.isEmpty()) - { - // If this breaks in the future, we are building the URL - // to download a video. At this time, this requires - // the video_id and the t argument - // from the source HTML of the page - int playerPos = mediaPage.indexOf("swfArgs") + 7; + QMap::const_iterator it = + m_articles.find(articlesListItem); - int tArgStart = mediaPage.indexOf("\"t\": \"", - playerPos) + 6; - int tArgEnd = mediaPage.indexOf("\"", tArgStart); - QString tArgString = mediaPage.mid(tArgStart, - tArgEnd - tArgStart); + if (it == m_articles.end()) + return; - int vidStart = mediaPage.indexOf("\"video_id\": \"", - playerPos) + 13; - int vidEnd = mediaPage.indexOf("\"", vidStart); - QString vidString = mediaPage.mid(vidStart, - vidEnd - vidStart); + if ((*it).title().isEmpty()) + return; - cmdURL = QString("http://youtube.com/get_video.php" - "?video_id=%2&t=%1") - .arg(tArgString).arg(vidString); - VERBOSE(VB_GENERAL, - QString("MythNews: VideoURL %1").arg(cmdURL)); - } - } + const NewsArticle article = *it; - QString fileprefix = GetConfDir(); + if (article.enclosure().isEmpty()) + { + QString cmdUrl(article.articleURL()); + cmdUrl.replace('\'', "%27"); - QDir dir(fileprefix); - if (!dir.exists()) - dir.mkdir(fileprefix); + QString cmd = QString("%1 %2 '%3'") + .arg(browser) + .arg(zoom) + .arg(cmdUrl); + gContext->GetMainWindow()->AllowInput(false); + myth_system(cmd, MYTH_SYSTEM_DONT_BLOCK_PARENT); + gContext->GetMainWindow()->AllowInput(true); + return; + } - fileprefix += "/MythNews"; + QString cmdURL(article.enclosure()); - dir = QDir(fileprefix); - if (!dir.exists()) - dir.mkdir(fileprefix); + // Handle special cases for media here + // YouTube: Fetch the mediaURL page and parse out the video URL + if (cmdURL.contains("youtube.com")) + { + cmdURL = QString(article.mediaURL()); + QString mediaPage = HttpComms::getHttp(cmdURL); + if (!mediaPage.isEmpty()) + { + // If this breaks in the future, we are building the URL + // to download a video. At this time, this requires + // the video_id and the t argument + // from the source HTML of the page + int playerPos = mediaPage.indexOf("swfArgs") + 7; - QString sFilename(fileprefix + "/newstempfile"); + int tArgStart = mediaPage.indexOf("\"t\": \"", + playerPos) + 6; + int tArgEnd = mediaPage.indexOf("\"", tArgStart); + QString tArgString = mediaPage.mid(tArgStart, + tArgEnd - tArgStart); - if (getHttpFile(sFilename, cmdURL)) - { - playVideo(sFilename); - } - } - else { - QString cmdUrl(article->articleURL()); - cmdUrl.replace('\'', "%27"); + int vidStart = mediaPage.indexOf("\"video_id\": \"", + playerPos) + 13; + int vidEnd = mediaPage.indexOf("\"", vidStart); + QString vidString = mediaPage.mid(vidStart, + vidEnd - vidStart); - QString cmd = QString("%1 %2 '%3'") - .arg(browser) - .arg(zoom) - .arg(cmdUrl); - gContext->GetMainWindow()->AllowInput(false); - myth_system(cmd, MYTH_SYSTEM_DONT_BLOCK_PARENT); - gContext->GetMainWindow()->AllowInput(true); - } + cmdURL = QString("http://youtube.com/get_video.php" + "?video_id=%2&t=%1") + .arg(tArgString).arg(vidString); + VERBOSE(VB_GENERAL, + QString("MythNews: VideoURL %1").arg(cmdURL)); } } + + QString fileprefix = GetConfDir(); + + QDir dir(fileprefix); + if (!dir.exists()) + dir.mkdir(fileprefix); + + fileprefix += "/MythNews"; + + dir = QDir(fileprefix); + if (!dir.exists()) + dir.mkdir(fileprefix); + + QString sFilename(fileprefix + "/newstempfile"); + + if (getHttpFile(sFilename, cmdURL)) + playVideo(sFilename); } void MythNews::ShowEditDialog(bool edit) Index: mythnews/mythnews/httphandler.h =================================================================== --- mythnews/mythnews/httphandler.h (revision 0) +++ mythnews/mythnews/httphandler.h (revision 0) @@ -0,0 +1,52 @@ +#ifndef _HTTP_HANDLER_H_ +#define _HTTP_HANDLER_H_ + +// C++ headers +#include +using namespace std; + +// Qt headers +#include +#include + +typedef deque URLQueue; + +class QHttp; +class QHttpResponseHeader; +class HttpPool; + +class HttpHandler : public QObject +{ + Q_OBJECT + public: + HttpHandler(HttpPool *pool); + virtual void deleteLater(void) { TeardownAll(); QObject::deleteLater(); } + + bool HasPendingRequests(void) const; + void AddURLRequest(const QUrl &url); + void RemoveURLRequest(const QUrl &url); + + protected slots: + void Done(bool error); + void ResponseHeaderReceived(const QHttpResponseHeader &resp); + void RequestFinished(int id, bool error); + void RequestStarted(int id); + void StateChanged(int state); + + private: + ~HttpHandler() { TeardownAll(); } + void TeardownAll(); + void Get(const QUrl &url); + + private: + mutable QMutex m_lock; + URLQueue m_urls; + QUrl m_cur_url; + uint m_cur_status_id; + int m_cur_get_id; + HttpPool *m_pool; + QHttp *m_qhttp; + +}; + +#endif // _HTTP_HANDLER_H_ Index: mythnews/mythnews/mythnews.h =================================================================== --- mythnews/mythnews/mythnews.h (revision 18874) +++ mythnews/mythnews/mythnews.h (working copy) @@ -69,6 +69,7 @@ MythUIButtonList *m_sitesList; MythUIButtonList *m_articlesList; + QMap m_articles; MythUIText *m_updatedText; MythUIText *m_titleText; Index: mythnews/mythnews/mythnews.pro =================================================================== --- mythnews/mythnews/mythnews.pro (revision 18874) +++ mythnews/mythnews/mythnews.pro (working copy) @@ -1,6 +1,8 @@ include ( ../../mythconfig.mak ) include ( ../../settings.pro ) include ( ../../programs-libs.pro ) + +QT += network sql xml TEMPLATE = lib CONFIG += plugin thread warn_on debug @@ -21,7 +23,7 @@ SOURCES += main.cpp mythnews.cpp mythnewsconfig.cpp mythnewseditor.cpp SOURCES += newsengine.cpp newsdbutil.cpp dbcheck.cpp -#The following line was inserted by qt3to4 -QT += network sql xml qt3support +HEADERS += httppool.h httphandler.h +SOURCES += httppool.cpp httphandler.cpp include ( ../../libs-targetfix.pro )