From d307c426f0ea979a220e4cefbe7b30251dd4382e Mon Sep 17 00:00:00 2001 From: craig Date: Wed, 30 Nov 2011 17:10:02 +0000 Subject: [PATCH] Copy network-access-manager stuff from clementine --- CMakeLists.txt | 6 +- TODO | 10 +- external/libmaia/maiaXmlRpcClient.cpp | 11 +- external/libmaia/maiaXmlRpcClient.h | 3 +- gui/covers.cpp | 9 +- gui/covers.h | 4 +- lyrics/ultimatelyricsprovider.cpp | 11 +- lyrics/ultimatelyricsprovider.h | 4 +- network/networkaccessmanager.cpp | 35 ++++++ network/networkaccessmanager.h | 37 +++++++ network/networkproxyfactory.cpp | 107 ++++++++++++++++++ network/networkproxyfactory.h | 44 ++++++++ network/proxysettings.ui | 150 ++++++++++++++++++++++++++ 13 files changed, 397 insertions(+), 34 deletions(-) create mode 100644 network/networkaccessmanager.cpp create mode 100644 network/networkaccessmanager.h create mode 100644 network/networkproxyfactory.cpp create mode 100644 network/networkproxyfactory.h create mode 100644 network/proxysettings.ui diff --git a/CMakeLists.txt b/CMakeLists.txt index 92e18fe40..fe1a9a376 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,7 @@ SET( CANTATA_SRCS lyrics/ultimatelyricsprovider.cpp lyrics/ultimatelyricsreader.cpp lyrics/songinfoprovider.cpp + network/networkaccessmanager.cpp ) SET( CANTATA_MOC_HDRS @@ -89,6 +90,7 @@ SET( CANTATA_MOC_HDRS lyrics/ultimatelyricsprovider.h lyrics/ultimatelyricsreader.h lyrics/songinfoprovider.h + network/networkaccessmanager.h ) SET( CANTATA_UIS @@ -111,6 +113,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/external/libmaia ${CMAKE_SOURCE_DIR}/lib ${CMAKE_SOURCE_DIR}/widgets ${CMAKE_SOURCE_DIR}/lyrics + ${CMAKE_SOURCE_DIR}/network ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ) @@ -153,7 +156,8 @@ IF( ENABLE_KDE_SUPPORT ) ADD_SUBDIRECTORY( icons ) add_subdirectory(po) ELSE( ENABLE_KDE_SUPPORT ) - SET( CANTATA_SRCS ${CANTATA_SRCS} widgets/lineedit.cpp) + SET( CANTATA_SRCS ${CANTATA_SRCS} widgets/lineedit.cpp network/networkproxyfactory.cpp) + SET( CANTATA_MOC_HDRS ${CANTATA_MOC_HDRS} network/networkproxyfactory.h) QT4_ADD_RESOURCES( CANTATA_RC_SRCS ${CANTATA_RCS} ) QT4_WRAP_UI( CANTATA_UI_HDRS ${CANTATA_UIS} ) INCLUDE( ${QT_USE_FILE} ) diff --git a/TODO b/TODO index 7ee0ede88..f51806b52 100644 --- a/TODO +++ b/TODO @@ -16,9 +16,13 @@ Lyrics - Need to configure enabled helpers, and order!!! - Need to add config ui!! -...medium priority... +Fix Qt only build -Proxy support for Qt (read system settings, and also add config page) +Integrate Qt proxy settings - 75% there... + + + +...medium priority... Fix usage of threads - ideally writing/reading should be in thread object. @@ -39,5 +43,3 @@ When starting, config dialog is shown (because MP not started, etc) then show so Add config of MPD itself -> requires KAuth??? outputs album artist support - -Fix Qt-only build, disable in CMakeLists.txt as its broken!!! diff --git a/external/libmaia/maiaXmlRpcClient.cpp b/external/libmaia/maiaXmlRpcClient.cpp index 86f73cf86..547324174 100644 --- a/external/libmaia/maiaXmlRpcClient.cpp +++ b/external/libmaia/maiaXmlRpcClient.cpp @@ -27,9 +27,7 @@ #include "maiaXmlRpcClient.h" #include "maiaFault.h" -#ifdef ENABLE_KDE_SUPPORT -#include -#endif +#include "networkaccessmanager.h" MaiaXmlRpcClient::MaiaXmlRpcClient(QObject* parent) : QObject(parent), manager(0), request() @@ -75,11 +73,8 @@ QNetworkReply* MaiaXmlRpcClient::call(QString method, QList args, connect(call, SIGNAL(fault(int, const QString &, QNetworkReply *)), faultObject, faultSlot); if (!manager) { -#ifdef ENABLE_KDE_SUPPORT - manager = new KIO::Integration::AccessManager(this); -#else - manager=new QNetworkAccessManager(this); -#endif + manager=new NetworkAccessManager(this); + connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*))); connect(manager, SIGNAL(sslErrors(QNetworkReply *, const QList &)), diff --git a/external/libmaia/maiaXmlRpcClient.h b/external/libmaia/maiaXmlRpcClient.h index b4d52f9ff..51e92f51a 100644 --- a/external/libmaia/maiaXmlRpcClient.h +++ b/external/libmaia/maiaXmlRpcClient.h @@ -33,6 +33,7 @@ #include #include "maiaObject.h" +class NetworkAccessManager; class MaiaXmlRpcClient : public QObject { Q_OBJECT @@ -57,7 +58,7 @@ class MaiaXmlRpcClient : public QObject { private: void init(); - QNetworkAccessManager *manager; + NetworkAccessManager *manager; QNetworkRequest request; QMap callmap; }; diff --git a/gui/covers.cpp b/gui/covers.cpp index 3875530da..591ce7e1d 100644 --- a/gui/covers.cpp +++ b/gui/covers.cpp @@ -2,12 +2,11 @@ #include "musiclibrarymodel.h" #include "lib/song.h" #include "maiaXmlRpcClient.h" +#include "networkaccessmanager.h" #include -#include #include #ifdef ENABLE_KDE_SUPPORT #include -#include K_GLOBAL_STATIC(Covers, instance) #endif @@ -128,11 +127,7 @@ void Covers::get(const Song &song) } if (!manager) { -#ifdef ENABLE_KDE_SUPPORT - manager = new KIO::Integration::AccessManager(this); -#else - manager=new QNetworkAccessManager(this); -#endif + manager=new NetworkAccessManager(this); connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(jobFinished(QNetworkReply *))); } diff --git a/gui/covers.h b/gui/covers.h index e71569446..32c56921e 100644 --- a/gui/covers.h +++ b/gui/covers.h @@ -7,7 +7,7 @@ class Song; class QImage; class QString; -class QNetworkAccessManager; +class NetworkAccessManager; class QNetworkReply; class MaiaXmlRpcClient; @@ -36,7 +36,7 @@ private: private: QString mpdDir; MaiaXmlRpcClient *rpc; - QNetworkAccessManager *manager; + NetworkAccessManager *manager; QMap jobs; }; diff --git a/lyrics/ultimatelyricsprovider.cpp b/lyrics/ultimatelyricsprovider.cpp index 9ec40af6e..6b1b06ae2 100644 --- a/lyrics/ultimatelyricsprovider.cpp +++ b/lyrics/ultimatelyricsprovider.cpp @@ -17,12 +17,9 @@ //#include "songinfotextview.h" #include "ultimatelyricsprovider.h" +#include "networkaccessmanager.h" //#include "core/network.h" -#ifdef ENABLE_KDE_SUPPORT -#include -#endif -#include #include "lib/song.h" #include @@ -35,11 +32,7 @@ const int UltimateLyricsProvider::kRedirectLimit = 5; UltimateLyricsProvider::UltimateLyricsProvider() -#ifdef ENABLE_KDE_SUPPORT - : network_(new KIO::Integration::AccessManager(this)), -#else - : network_(new QNetworkAccessManager(this)), -#endif + : network_(new NetworkAccessManager(this)), relevance_(0), redirect_count_(0) { diff --git a/lyrics/ultimatelyricsprovider.h b/lyrics/ultimatelyricsprovider.h index 4e5f8df61..452cb3160 100644 --- a/lyrics/ultimatelyricsprovider.h +++ b/lyrics/ultimatelyricsprovider.h @@ -26,7 +26,7 @@ class Song; -class QNetworkAccessManager; +class NetworkAccessManager; class QNetworkReply; @@ -76,7 +76,7 @@ private: void DoUrlReplace(const QString& tag, const QString& value, QString* url) const; private: - QNetworkAccessManager* network_; + NetworkAccessManager* network_; QMap requests_; QString name_; diff --git a/network/networkaccessmanager.cpp b/network/networkaccessmanager.cpp new file mode 100644 index 000000000..96b62b28a --- /dev/null +++ b/network/networkaccessmanager.cpp @@ -0,0 +1,35 @@ +#include "networkaccessmanager.h" +#include + +NetworkAccessManager::NetworkAccessManager(QObject *parent) + : BASE_NETWORK_ACCESS_MANAGER(parent) +{ +} + +QNetworkReply * NetworkAccessManager::get(const QNetworkRequest &req, int timeout) +{ + QNetworkReply *reply=BASE_NETWORK_ACCESS_MANAGER::get(req); + + if (0!=timeout) { + connect(reply, SIGNAL(destroyed()), SLOT(replyFinished())); + connect(reply, SIGNAL(finished()), SLOT(replyFinished())); + timers[reply] = startTimer(timeout); + } + return reply; +} + +void NetworkAccessManager::replyFinished() +{ + QNetworkReply *reply = reinterpret_cast(sender()); + if (timers.contains(reply)) { + killTimer(timers.take(reply)); + } +} + +void NetworkAccessManager::timerEvent(QTimerEvent *e) +{ + QNetworkReply *reply = timers.key(e->timerId()); + if (reply) { + reply->abort(); + } +} diff --git a/network/networkaccessmanager.h b/network/networkaccessmanager.h new file mode 100644 index 000000000..578a383bf --- /dev/null +++ b/network/networkaccessmanager.h @@ -0,0 +1,37 @@ +#ifndef NETWORK_ACCESS_MANAGER_H +#define NETWORK_ACCESS_MANAGER_H + +#ifdef ENABLE_KDE_SUPPORT +#include +#define BASE_NETWORK_ACCESS_MANAGER KIO::Integration::AccessManager +#else +#include +#define BASE_NETWORK_ACCESS_MANAGER QNetworkAccessManager +#endif +#include +#include + +class QTimerEvent; + +class NetworkAccessManager : public BASE_NETWORK_ACCESS_MANAGER +{ + Q_OBJECT + +public: + NetworkAccessManager(QObject *parent); + virtual ~NetworkAccessManager() { } + + QNetworkReply * get(const QNetworkRequest &req, int timeout=0); + QNetworkReply * get(const QUrl &url, int timeout=0) { return get(QNetworkRequest(url), timeout); } + +protected: + void timerEvent(QTimerEvent *e); + +private Q_SLOTS: + void replyFinished(); + +private: + QMap timers; +}; + +#endif // NETWORK_ACCESS_MANAGER_H diff --git a/network/networkproxyfactory.cpp b/network/networkproxyfactory.cpp new file mode 100644 index 000000000..5bb7a712a --- /dev/null +++ b/network/networkproxyfactory.cpp @@ -0,0 +1,107 @@ +#include "networkproxyfactory.h" + +#include +#include +#include + +#include + +NetworkProxyFactory* NetworkProxyFactory::sInstance = NULL; +const char* NetworkProxyFactory::kSettingsGroup = "Proxy"; + +NetworkProxyFactory::NetworkProxyFactory() + : mode_(Mode_System), + type_(QNetworkProxy::HttpProxy), + port_(8080), + use_authentication_(false) +{ +#ifdef Q_OS_LINUX + // Linux uses environment variables to pass proxy configuration information, + // which systemProxyForQuery doesn't support for some reason. + + QStringList urls; + urls << QString::fromLocal8Bit(getenv("HTTP_PROXY")); + urls << QString::fromLocal8Bit(getenv("http_proxy")); + urls << QString::fromLocal8Bit(getenv("ALL_PROXY")); + urls << QString::fromLocal8Bit(getenv("all_proxy")); + + foreach (const QString& url_str, urls) { + if (url_str.isEmpty()) + continue; + + env_url_ = QUrl(url_str); + break; + } +#endif + + ReloadSettings(); +} + +NetworkProxyFactory* NetworkProxyFactory::Instance() { + if (!sInstance) { + sInstance = new NetworkProxyFactory; + } + + return sInstance; +} + +void NetworkProxyFactory::ReloadSettings() { + QMutexLocker l(&mutex_); + + QSettings s; + s.beginGroup(kSettingsGroup); + + mode_ = Mode(s.value("mode", Mode_System).toInt()); + type_ = QNetworkProxy::ProxyType(s.value("type", QNetworkProxy::HttpProxy).toInt()); + hostname_ = s.value("hostname").toString(); + port_ = s.value("port", 8080).toInt(); + use_authentication_ = s.value("use_authentication", false).toBool(); + username_ = s.value("username").toString(); + password_ = s.value("password").toString(); +} + +QList NetworkProxyFactory::queryProxy( + const QNetworkProxyQuery& query) { + QMutexLocker l(&mutex_); + + QNetworkProxy ret; + + switch (mode_) { + case Mode_System: +#ifdef Q_OS_LINUX + Q_UNUSED(query); + + if (env_url_.isEmpty()) { + ret.setType(QNetworkProxy::NoProxy); + } else { + ret.setHostName(env_url_.host()); + ret.setPort(env_url_.port()); + ret.setUser(env_url_.userName()); + ret.setPassword(env_url_.password()); + if (env_url_.scheme().startsWith("http")) + ret.setType(QNetworkProxy::HttpProxy); + else + ret.setType(QNetworkProxy::Socks5Proxy); + } + break; +#else + return systemProxyForQuery(query); +#endif + + case Mode_Direct: + ret.setType(QNetworkProxy::NoProxy); + break; + + case Mode_Manual: + ret.setType(type_); + ret.setHostName(hostname_); + ret.setPort(port_); + if (use_authentication_) { + ret.setUser(username_); + ret.setPassword(password_); + } + break; + } + + return QList() << ret; +} diff --git a/network/networkproxyfactory.h b/network/networkproxyfactory.h new file mode 100644 index 000000000..78030e772 --- /dev/null +++ b/network/networkproxyfactory.h @@ -0,0 +1,44 @@ +#ifndef NETWORKPROXYFACTORY_H +#define NETWORKPROXYFACTORY_H + +#include +#include +#include + +class NetworkProxyFactory : public QNetworkProxyFactory { +public: + // These values are persisted + enum Mode { + Mode_System = 0, + Mode_Direct = 1, + Mode_Manual = 2, + }; + + static NetworkProxyFactory* Instance(); + static const char* kSettingsGroup; + + // These methods are thread-safe + void ReloadSettings(); + QList queryProxy(const QNetworkProxyQuery& query); + +private: + NetworkProxyFactory(); + + static NetworkProxyFactory* sInstance; + + QMutex mutex_; + + Mode mode_; + QNetworkProxy::ProxyType type_; + QString hostname_; + int port_; + bool use_authentication_; + QString username_; + QString password_; + +#ifdef Q_OS_LINUX + QUrl env_url_; +#endif +}; + +#endif // NETWORKPROXYFACTORY_H diff --git a/network/proxysettings.ui b/network/proxysettings.ui new file mode 100644 index 000000000..3c284d65f --- /dev/null +++ b/network/proxysettings.ui @@ -0,0 +1,150 @@ + + + ProxySettings + + + + 0 + 0 + 360 + 204 + + + + Form + + + + 0 + + + + + Use the system proxy settings + + + true + + + + + + + Direct internet connection + + + + + + + Manual proxy configuration + + + + + + + false + + + + 24 + + + + + + + + HTTP proxy + + + + + SOCKS proxy + + + + + + + + + + + Port + + + + + + + 65535 + + + 8080 + + + + + + + + + Use authentication + + + true + + + false + + + + + + Username + + + + + + + + + + Password + + + + + + + QLineEdit::Password + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 2 + + + + + + + + +