diff --git a/CMakeLists.txt b/CMakeLists.txt index 954687e20..db49e8077 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,7 @@ option(BUILD_GUI "Build Tomahawk with GUI" ON) option(BUILD_RELEASE "Generate TOMAHAWK_VERSION without GIT info" OFF) option(BUILD_TESTS "Build Tomahawk with unit tests" ON) option(BUILD_HATCHET "Build the Hatchet plugin" OFF) +option(BUILD_WITH_QT4 "Build Tomahawk with Qt4 no matter if Qt5 was found" ON) option(WITH_BREAKPAD "Build with breakpad integration" ON) option(WITH_CRASHREPORTER "Build with CrashReporter" ON) @@ -266,6 +267,11 @@ macro_log_feature(LIBLASTFM_FOUND "liblastfm" "Qt library for the Last.fm webser macro_optional_find_package(QtKeychain 0.1.0) macro_log_feature(QTKEYCHAIN_FOUND "QtKeychain" "Provides support for secure credentials storage" "https://github.com/frankosterfeld/qtkeychain" TRUE "" "") +if( UNIX AND NOT APPLE ) + macro_optional_find_package(TelepathyQt 0.9.3) + macro_log_feature(TelepathyQt4_FOUND "Telepathy-Qt" "Telepathy-Qt is a Qt high-level binding for Telepathy, a D-Bus framework for unifying real time communication." FALSE "" "Telepathy-Qt is needed for sharing Jabber/GTalk accounts with Telepathy.\n") +endif() + # we need pthreads too macro_optional_find_package(Threads) macro_log_feature(THREADS_FOUND "Threads" "Threading Library" "" TRUE "" "Platform specific library for threading") @@ -308,8 +314,8 @@ if (WITH_KDE4) endif(WITH_KDE4) # this was used before we had FindKDE4Installed, just leaving it here to keep the flags # for future kde integration +macro_log_feature(KDE4_FOUND "KDE4" "Provides support for configuring Telepathy Accounts from inside Tomahawk" "https://www.kde.org" FALSE "" "") -# macro_optional_find_package(KDE4) IF( KDE4_FOUND ) IF( CMAKE_C_FLAGS ) # KDE4 adds and removes some compiler flags that we don't like diff --git a/CMakeModules/FindTelepathyQt.cmake b/CMakeModules/FindTelepathyQt.cmake new file mode 100644 index 000000000..2b286856b --- /dev/null +++ b/CMakeModules/FindTelepathyQt.cmake @@ -0,0 +1,27 @@ +# Copyright (c) 2013, Teo Mrnjavac + +include(FindPackageHandleStandardArgs) + +if( NOT BUILD_WITH_QT4 ) + find_package(TelepathyQt5 NO_MODULE) + set(TelepathyQt_FOUND ${TelepathyQt5_FOUND}) + set(TELEPATHY_QT_VERSION ${TELEPATHY_QT5_VERSION}) + set(TELEPATHY_QT_INSTALL_DIR ${TELEPATHY_QT5_INSTALL_DIR}) + set(TELEPATHY_QT_INCLUDE_DIR ${TELEPATHY_QT5_INCLUDE_DIR}) + set(TELEPATHY_QT_LIB_DIR ${TELEPATHY_QT5_LIB_DIR}) + set(TELEPATHY_QT_SHARE_DIR ${TELEPATHY_QT5_SHARE_DIR}) + set(TELEPATHY_QT_LIBRARIES ${TELEPATHY_QT5_LIBRARIES}) +else() + find_package(TelepathyQt4 NO_MODULE) + set(TelepathyQt_FOUND ${TelepathyQt4_FOUND}) + set(TELEPATHY_QT_VERSION ${TELEPATHY_QT4_VERSION}) + set(TELEPATHY_QT_INSTALL_DIR ${TELEPATHY_QT4_INSTALL_DIR}) + set(TELEPATHY_QT_INCLUDE_DIR ${TELEPATHY_QT4_INCLUDE_DIR}) + set(TELEPATHY_QT_LIB_DIR ${TELEPATHY_QT4_LIB_DIR}) + set(TELEPATHY_QT_SHARE_DIR ${TELEPATHY_QT4_SHARE_DIR}) + set(TELEPATHY_QT_LIBRARIES ${TELEPATHY_QT4_LIBRARIES}) +endif() + +set(TELEPATHY_QT_FOUND ${TelepathyQt_FOUND}) + +find_package_handle_standard_args(TelepathyQt DEFAULT_MSG TELEPATHY_QT_INSTALL_DIR ) diff --git a/src/accounts/xmpp/XmppAccount.h b/src/accounts/xmpp/XmppAccount.h index 077cdbaf3..b0593b3c2 100644 --- a/src/accounts/xmpp/XmppAccount.h +++ b/src/accounts/xmpp/XmppAccount.h @@ -52,7 +52,7 @@ public: QString description() const { return tr( "Log on to your Jabber/XMPP account to connect to your friends" ); } QString factoryId() const { return "xmppaccount"; } QPixmap icon() const { return QPixmap( ":/xmpp-account/xmpp-icon.png" ); } - AccountTypes types() const { return AccountTypes( SipType | StatusPushType ); }; + AccountTypes types() const { return AccountTypes( SipType | StatusPushType ); } Account* createAccount( const QString& pluginId = QString() ); }; diff --git a/src/accounts/xmpp/XmppConfigWidget.cpp b/src/accounts/xmpp/XmppConfigWidget.cpp index 0df3cc9d2..021e6289b 100644 --- a/src/accounts/xmpp/XmppConfigWidget.cpp +++ b/src/accounts/xmpp/XmppConfigWidget.cpp @@ -23,7 +23,9 @@ #include "accounts/AccountManager.h" +#include "accounts/ConfigStorage.h" #include "utils/Logger.h" +#include "utils/TomahawkUtilsGui.h" #include @@ -48,9 +50,41 @@ XmppConfigWidget::XmppConfigWidget( XmppAccount* account, QWidget *parent ) m_ui->xmppPublishTracksCheckbox->setChecked( account->configuration().contains( "publishtracks" ) ? account->configuration()[ "publishtracks" ].toBool() : true); m_ui->xmppEnforceSecureCheckbox->setChecked( account->configuration().contains( "enforcesecure" ) ? account->configuration()[ "enforcesecure" ].toBool() : false); m_ui->jidExistsLabel->hide(); + m_ui->xmppConfigFrame->hide(); connect( m_ui->xmppUsername, SIGNAL( textChanged( QString ) ), SLOT( onCheckJidExists( QString ) ) ); + + if ( m_account->configuration()[ "read-only" ].toBool() ) + { + m_ui->xmppUsername->setEnabled( false ); + m_ui->xmppPassword->setEnabled( false ); + m_ui->xmppServer->setEnabled( false ); + m_ui->xmppPort->setEnabled( false ); + m_ui->xmppEnforceSecureCheckbox->setEnabled( false ); + m_ui->xmppPublishTracksCheckbox->setEnabled( false ); + } + + ConfigStorage* cs = AccountManager::instance()->configStorageForAccount( m_account->accountId() ); + if ( cs->id() != "localconfigstorage" ) + { + m_ui->xmppBlurb->hide(); + m_ui->xmppConfigFrame->show(); + m_ui->xmppConfigLabel->setText( tr( "Account provided by %1." ) + .arg( cs->prettyName() ) ); + m_ui->xmppConfigIcon->setPixmap( cs->icon().scaled( TomahawkUtils::defaultIconSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation ) ); + m_ui->xmppConfigLaunchDialog->setIcon( TomahawkUtils::defaultPixmap( TomahawkUtils::Configure ) ); + connect( m_ui->xmppConfigLaunchDialog, SIGNAL( clicked() ), + this, SLOT( launchExternalConfigDialog() ) ); + } +} + + +void +XmppConfigWidget::launchExternalConfigDialog() +{ + ConfigStorage* cs = AccountManager::instance()->configStorageForAccount( m_account->accountId() ); + cs->execConfigDialog( this ); } diff --git a/src/accounts/xmpp/XmppConfigWidget.h b/src/accounts/xmpp/XmppConfigWidget.h index 447b5fafb..bfdaa5da8 100644 --- a/src/accounts/xmpp/XmppConfigWidget.h +++ b/src/accounts/xmpp/XmppConfigWidget.h @@ -56,6 +56,7 @@ signals: private slots: void onCheckJidExists( const QString& jid ); + void launchExternalConfigDialog(); private: Ui::XmppConfigWidget *m_ui; diff --git a/src/accounts/xmpp/XmppConfigWidget.ui b/src/accounts/xmpp/XmppConfigWidget.ui index 8e16eaced..96eacb053 100644 --- a/src/accounts/xmpp/XmppConfigWidget.ui +++ b/src/accounts/xmpp/XmppConfigWidget.ui @@ -1,15 +1,21 @@ XmppConfigWidget - + 0 0 451 - 335 + 337 + + + 451 + 0 + + Xmpp Configuration @@ -35,7 +41,7 @@ - :/xmpp-account/xmpp-icon.png + :/xmpp-account/xmpp-icon.png @@ -69,15 +75,18 @@ - + Qt::Horizontal + + QSizePolicy::Expanding + - 40 + 0 20 @@ -85,9 +94,18 @@ + + + 0 + 0 + + Enter your Xmpp login to connect with your friends using Tomahawk! + + false + @@ -95,9 +113,12 @@ Qt::Horizontal + + QSizePolicy::Expanding + - 40 + 0 20 @@ -105,6 +126,85 @@ + + + + + + + 0 + 0 + + + + + 200 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + 0 + + + + 5 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + + + + + + + + + 0 + 0 + + + + + + + true + + + + + + + Configure + + + + + + + + + + + diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index 918b18270..42bd6865a 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -222,6 +222,8 @@ list(APPEND libSources accounts/AccountFactoryWrapper.cpp accounts/AccountFactoryWrapperDelegate.cpp accounts/AccountConfigWidget.cpp + accounts/ConfigStorage.cpp + accounts/LocalConfigStorage.cpp accounts/spotify/SpotifyAccount.cpp accounts/spotify/SpotifyAccountConfig.cpp @@ -361,7 +363,7 @@ list(APPEND libSources utils/TomahawkCache.cpp utils/GuiHelpers.cpp utils/WeakObjectHash.cpp - + utils/PluginLoader.cpp thirdparty/kdsingleapplicationguard/kdsingleapplicationguard.cpp thirdparty/kdsingleapplicationguard/kdsharedmemorylocker.cpp @@ -369,6 +371,8 @@ list(APPEND libSources thirdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.cpp ) +add_subdirectory( accounts/configstorage ) + IF(LIBLASTFM_FOUND) include_directories( ${LIBLASTFM_INCLUDE_DIRS} ) list(APPEND LINK_LIBRARIES ${LIBLASTFM_LIBRARIES} ) diff --git a/src/libtomahawk/accounts/Account.cpp b/src/libtomahawk/accounts/Account.cpp index 9c168c85c..4fa57d2c3 100644 --- a/src/libtomahawk/accounts/Account.cpp +++ b/src/libtomahawk/accounts/Account.cpp @@ -2,6 +2,7 @@ * * Copyright 2011, Christian Muehlhaeuser * Copyright 2011, Leo Franchi + * Copyright 2013, Teo Mrnjavac * * Tomahawk is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,9 +20,9 @@ #include "Account.h" -#include "TomahawkSettings.h" #include "AccountManager.h" #include "CredentialsManager.h" +#include "ConfigStorage.h" namespace Tomahawk { @@ -51,10 +52,11 @@ accountTypeToString( AccountType type ) Account::Account( const QString& accountId ) : QObject() - , m_enabled( false ) , m_accountId( accountId ) { - connect( this, SIGNAL( error( int, QString ) ), this, SLOT( onError( int,QString ) ) ); + m_cfg.enabled = false; + + connect( this, SIGNAL( error( int, QString ) ), this, SLOT( onError( int, QString ) ) ); connect( this, SIGNAL( connectionStateChanged( Tomahawk::Accounts::Account::ConnectionState ) ) , this, SLOT( onConnectionStateChanged( Tomahawk::Accounts::Account::ConnectionState ) ) ); loadFromConfig( accountId ); @@ -132,18 +134,7 @@ Account::onConnectionStateChanged( Account::ConnectionState ) void Account::syncConfig() { - TomahawkSettings* s = TomahawkSettings::instance(); - s->beginGroup( "accounts/" + m_accountId ); - s->setValue( "accountfriendlyname", m_accountFriendlyName ); - s->setValue( "enabled", m_enabled ); - s->setValue( "configuration", m_configuration ); - s->setValue( "acl", m_acl ); - s->setValue( "types", m_types ); - s->endGroup(); - s->sync(); - - CredentialsManager* c = AccountManager::instance()->credentialsManager(); - c->setCredentials( m_accountId, m_credentials ); + AccountManager::instance()->configStorageForAccount( m_accountId )->save( m_accountId, m_cfg ); } @@ -151,35 +142,16 @@ void Account::loadFromConfig( const QString& accountId ) { m_accountId = accountId; - TomahawkSettings* s = TomahawkSettings::instance(); - s->beginGroup( "accounts/" + m_accountId ); - m_accountFriendlyName = s->value( "accountfriendlyname", QString() ).toString(); - m_enabled = s->value( "enabled", false ).toBool(); - m_configuration = s->value( "configuration", QVariantHash() ).toHash(); - m_acl = s->value( "acl", QVariantMap() ).toMap(); - m_types = s->value( "types", QStringList() ).toStringList(); - s->endGroup(); - CredentialsManager* c = AccountManager::instance()->credentialsManager(); - m_credentials = c->credentials( m_accountId ); + if ( AccountManager::instance()->configStorageForAccount( m_accountId ) != 0 ) //could be 0 if we are installing the account right now + AccountManager::instance()->configStorageForAccount( m_accountId )->load( m_accountId, m_cfg ); } void Account::removeFromConfig() { - TomahawkSettings* s = TomahawkSettings::instance(); - s->beginGroup( "accounts/" + m_accountId ); - s->remove( "accountfriendlyname" ); - s->remove( "enabled" ); - s->remove( "configuration" ); - s->remove( "acl" ); - s->remove( "types" ); - s->endGroup(); - s->remove( "accounts/" + m_accountId ); - - CredentialsManager* c = AccountManager::instance()->credentialsManager(); - c->setCredentials( m_accountId, QVariantHash() ); + AccountManager::instance()->configStorageForAccount( m_accountId )->remove( m_accountId ); } @@ -187,15 +159,15 @@ void Account::setTypes( AccountTypes types ) { QMutexLocker locker( &m_mutex ); - m_types = QStringList(); + m_cfg.types = QStringList(); if ( types & InfoType ) - m_types << "InfoType"; + m_cfg.types << "InfoType"; if ( types & SipType ) - m_types << "SipType"; + m_cfg.types << "SipType"; if ( types & ResolverType ) - m_types << "ResolverType"; + m_cfg.types << "ResolverType"; if ( types & StatusPushType ) - m_types << "StatusPushType"; + m_cfg.types << "StatusPushType"; syncConfig(); } @@ -205,13 +177,13 @@ Account::types() const { QMutexLocker locker( &m_mutex ); AccountTypes types; - if ( m_types.contains( "InfoType" ) ) + if ( m_cfg.types.contains( "InfoType" ) ) types |= InfoType; - if ( m_types.contains( "SipType" ) ) + if ( m_cfg.types.contains( "SipType" ) ) types |= SipType; - if ( m_types.contains( "ResolverType" ) ) + if ( m_cfg.types.contains( "ResolverType" ) ) types |= ResolverType; - if ( m_types.contains( "StatusPushType" ) ) + if ( m_cfg.types.contains( "StatusPushType" ) ) types |= StatusPushType; return types; diff --git a/src/libtomahawk/accounts/Account.h b/src/libtomahawk/accounts/Account.h index d7b54d0a5..6c2eb8767 100644 --- a/src/libtomahawk/accounts/Account.h +++ b/src/libtomahawk/accounts/Account.h @@ -2,6 +2,7 @@ * * Copyright 2011, Christian Muehlhaeuser * Copyright 2011, Leo Franchi + * Copyright 2013, Teo Mrnjavac * * Tomahawk is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,6 +42,8 @@ namespace Tomahawk namespace Accounts { +class ConfigStorage; + enum AccountType { NoType = 0x00, @@ -66,18 +69,28 @@ class DLLEXPORT Account : public QObject Q_OBJECT public: + struct Configuration + { + QString accountFriendlyName; + bool enabled; + QVariantHash configuration; + QVariantMap acl; + QStringList types; + QVariantHash credentials; + }; + enum AuthErrorCode { AuthError, ConnectionError }; enum ConnectionState { Disconnected, Connecting, Connected, Disconnecting }; - explicit Account( const QString &accountId ); + explicit Account( const QString& accountId ); virtual ~Account(); QString accountServiceName() const { QMutexLocker locker( &m_mutex ); return m_accountServiceName; } // e.g. "Twitter", "Last.fm" - QString accountFriendlyName() const { QMutexLocker locker( &m_mutex ); return m_accountFriendlyName; } // e.g. screen name on the service, JID, etc. - bool enabled() const { QMutexLocker locker( &m_mutex ); return m_enabled; } + QString accountFriendlyName() const { QMutexLocker locker( &m_mutex ); return m_cfg.accountFriendlyName; } // e.g. screen name on the service, JID, etc. + bool enabled() const { QMutexLocker locker( &m_mutex ); return m_cfg.enabled; } QString accountId() const { QMutexLocker locker( &m_mutex ); return m_accountId; } - QVariantHash configuration() const { QMutexLocker locker( &m_mutex ); return m_configuration; } + QVariantHash configuration() const { QMutexLocker locker( &m_mutex ); return m_cfg.configuration; } /** * Configuration widgets can have a "dataError( bool )" signal to enable/disable the OK button in their wrapper dialogs. @@ -94,9 +107,9 @@ public: virtual void saveConfig() {} // called when the widget has been edited. save values from config widget, call sync() to write to disk account generic settings - QVariantHash credentials() const { QMutexLocker locker( &m_mutex ); return m_credentials; } + QVariantHash credentials() const { QMutexLocker locker( &m_mutex ); return m_cfg.credentials; } - QVariantMap acl() const { QMutexLocker locker( &m_mutex ); return m_acl; } + QVariantMap acl() const { QMutexLocker locker( &m_mutex ); return m_cfg.acl; } virtual ConnectionState connectionState() const = 0; virtual bool isAuthenticated() const = 0; @@ -113,15 +126,16 @@ public: AccountTypes types() const; void setAccountServiceName( const QString &serviceName ) { QMutexLocker locker( &m_mutex ); m_accountServiceName = serviceName; } - void setAccountFriendlyName( const QString &friendlyName ) { QMutexLocker locker( &m_mutex ); m_accountFriendlyName = friendlyName; } - void setEnabled( bool enabled ) { QMutexLocker locker( &m_mutex ); m_enabled = enabled; } + void setAccountFriendlyName( const QString &friendlyName ) { QMutexLocker locker( &m_mutex ); m_cfg.accountFriendlyName = friendlyName; } + void setEnabled( bool enabled ) { QMutexLocker locker( &m_mutex ); m_cfg.enabled = enabled; } void setAccountId( const QString &accountId ) { QMutexLocker locker( &m_mutex ); m_accountId = accountId; } - void setCredentials( const QVariantHash &credentialHash ) { QMutexLocker locker( &m_mutex ); m_credentials = credentialHash; } - void setConfiguration( const QVariantHash &configuration ) { QMutexLocker locker( &m_mutex ); m_configuration = configuration; } - void setAcl( const QVariantMap &acl ) { QMutexLocker locker( &m_mutex ); m_acl = acl; } + void setCredentials( const QVariantHash &credentialHash ) { QMutexLocker locker( &m_mutex ); m_cfg.credentials = credentialHash; } + void setConfiguration( const QVariantHash &configuration ) { QMutexLocker locker( &m_mutex ); m_cfg.configuration = configuration; } + void setAcl( const QVariantMap &acl ) { QMutexLocker locker( &m_mutex ); m_cfg.acl = acl; } + void setTypes( AccountTypes types ); - void sync() { QMutexLocker locker( &m_mutex ); syncConfig(); }; + void sync() { QMutexLocker locker( &m_mutex ); syncConfig(); } /** * Removes all the settings held in the config file for this account instance @@ -150,15 +164,12 @@ private slots: private: QString m_accountServiceName; - QString m_accountFriendlyName; QString m_cachedError; - bool m_enabled; QString m_accountId; - QVariantHash m_credentials; - QVariantHash m_configuration; - QVariantMap m_acl; - QStringList m_types; + mutable QMutex m_mutex; + + Account::Configuration m_cfg; }; class DLLEXPORT AccountFactory : public QObject diff --git a/src/libtomahawk/accounts/AccountManager.cpp b/src/libtomahawk/accounts/AccountManager.cpp index 8bd948eb9..95376fdb6 100644 --- a/src/libtomahawk/accounts/AccountManager.cpp +++ b/src/libtomahawk/accounts/AccountManager.cpp @@ -26,17 +26,17 @@ #include "jobview/JobStatusModel.h" #include "utils/Closure.h" #include "utils/Logger.h" +#include "utils/PluginLoader.h" #include "CredentialsManager.h" #include "config.h" #include "ResolverAccount.h" #include "SourceList.h" #include "TomahawkSettings.h" +#include "LocalConfigStorage.h" -#include -#include -#include -#include +#include +#include #include @@ -88,7 +88,7 @@ AccountManager::init() connect( TomahawkSettings::instance(), SIGNAL( changed() ), SLOT( onSettingsChanged() ) ); - loadPluginFactories( findPluginFactories() ); + loadPluginFactories(); // We include the resolver factory manually, not in a plugin ResolverAccountFactory* f = new ResolverAccountFactory(); @@ -99,58 +99,21 @@ AccountManager::init() } -QStringList -AccountManager::findPluginFactories() -{ - QStringList paths; - QList< QDir > pluginDirs; - - QDir appDir( qApp->applicationDirPath() ); -#ifdef Q_WS_MAC - if ( appDir.dirName() == "MacOS" ) - { - // Development convenience-hack - appDir.cdUp(); - appDir.cdUp(); - appDir.cdUp(); - } -#endif - - QDir libDir( CMAKE_INSTALL_PREFIX "/lib" ); - - QDir lib64Dir( appDir ); - lib64Dir.cdUp(); - lib64Dir.cd( "lib64" ); - - pluginDirs << appDir << libDir << lib64Dir << QDir( qApp->applicationDirPath() ); - foreach ( const QDir& pluginDir, pluginDirs ) - { - tDebug() << Q_FUNC_INFO << "Checking directory for plugins:" << pluginDir; - foreach ( QString fileName, pluginDir.entryList( QStringList() << "*tomahawk_account_*.so" << "*tomahawk_account_*.dylib" << "*tomahawk_account_*.dll", QDir::Files ) ) - { - if ( fileName.startsWith( "libtomahawk_account" ) ) - { - const QString path = pluginDir.absoluteFilePath( fileName ); - if ( !paths.contains( path ) ) - paths << path; - } - } - } - - return paths; -} - - void -AccountManager::loadPluginFactories( const QStringList& paths ) +AccountManager::loadPluginFactories() { - foreach ( QString fileName, paths ) + QHash< QString, QObject* > plugins = Tomahawk::Utils::PluginLoader( "account" ).loadPlugins(); + foreach ( QObject* plugin, plugins.values() ) { - if ( !QLibrary::isLibrary( fileName ) ) - continue; - - tDebug() << Q_FUNC_INFO << "Trying to load plugin:" << fileName; - loadPluginFactory( fileName ); + AccountFactory* accountfactory = qobject_cast( plugin ); + if ( accountfactory ) + { + tDebug() << Q_FUNC_INFO << "Loaded plugin factory:" << plugins.key( plugin ) << accountfactory->factoryId() << accountfactory->prettyName(); + m_accountFactories[ accountfactory->factoryId() ] = accountfactory; + } else + { + tDebug() << Q_FUNC_INFO << "Loaded invalid plugin.." << plugins.key( plugin ); + } } } @@ -183,29 +146,6 @@ AccountManager::factoryForAccount( Account* account ) const } -void -AccountManager::loadPluginFactory( const QString& path ) -{ - QPluginLoader loader( path ); - QObject* plugin = loader.instance(); - if ( !plugin ) - { - tDebug() << Q_FUNC_INFO << "Error loading plugin:" << loader.errorString(); - } - - AccountFactory* accountfactory = qobject_cast( plugin ); - if ( accountfactory ) - { - tDebug() << Q_FUNC_INFO << "Loaded plugin factory:" << loader.fileName() << accountfactory->factoryId() << accountfactory->prettyName(); - m_accountFactories[ accountfactory->factoryId() ] = accountfactory; - } else - { - tDebug() << Q_FUNC_INFO << "Loaded invalid plugin.." << loader.fileName(); - } -} - - - void AccountManager::enableAccount( Account* account ) { @@ -284,32 +224,57 @@ AccountManager::toggleAccountsConnected() void AccountManager::loadFromConfig() { - QStringList accountIds = TomahawkSettings::instance()->accounts(); - - qDebug() << "LOADING ALL CREDENTIALS" << accountIds; - m_creds = new CredentialsManager( this ); - NewClosure( m_creds, SIGNAL( ready() ), - this, SLOT( finishLoadingFromConfig( QStringList ) ), accountIds ); - m_creds->loadCredentials( accountIds ); + + ConfigStorage* localCS = new LocalConfigStorage( this ); + m_configStorageById.insert( localCS->id(), localCS ); + + QList< QObject* > configStoragePlugins = Tomahawk::Utils::PluginLoader( "configstorage" ).loadPlugins().values(); + foreach( QObject* plugin, configStoragePlugins ) + { + ConfigStorage* cs = qobject_cast< ConfigStorage* >( plugin ); + if ( !cs ) + continue; + + m_configStorageById.insert( cs->id(), cs ); + } + + foreach ( ConfigStorage* cs, m_configStorageById ) + { + m_configStorageLoading.insert( cs->id() ); + NewClosure( cs, SIGNAL( ready() ), + this, SLOT( finishLoadingFromConfig( QString ) ), cs->id() ); + cs->init(); + } } void -AccountManager::finishLoadingFromConfig( const QStringList& accountIds ) +AccountManager::finishLoadingFromConfig( const QString& csid ) { - qDebug() << "LOADING ALL ACCOUNTS" << accountIds; + if ( m_configStorageLoading.contains( csid ) ) + m_configStorageLoading.remove( csid ); - foreach ( const QString& accountId, accountIds ) + if ( !m_configStorageLoading.isEmpty() ) + return; + + foreach ( const ConfigStorage* cs, m_configStorageById ) { - QString pluginFactory = factoryFromId( accountId ); - if ( m_accountFactories.contains( pluginFactory ) ) + QStringList accountIds = cs->accountIds(); + + qDebug() << "LOADING ALL ACCOUNTS FOR STORAGE" << cs->metaObject()->className() + << ":" << accountIds; + + foreach ( const QString& accountId, accountIds ) { - Account* account = loadPlugin( accountId ); - addAccount( account ); + QString pluginFactory = factoryFromId( accountId ); + if ( m_accountFactories.contains( pluginFactory ) ) + { + Account* account = loadPlugin( accountId ); + addAccount( account ); + } } } - m_readyForSip = true; emit readyForSip(); //we have to yield to TomahawkApp because we don't know if Servent is ready } @@ -346,7 +311,25 @@ AccountManager::loadPlugin( const QString& accountId ) void AccountManager::addAccount( Account* account ) { - tDebug() << Q_FUNC_INFO << "adding account plugin"; + tDebug() << Q_FUNC_INFO << "adding account plugin" << account->accountId(); + foreach ( Account* a, m_accounts ) + { + if ( a->credentials()["username"] == account->credentials()["username"] ) + { + ConfigStorage* configStorageForA = configStorageForAccount( a->accountId() ); + ConfigStorage* configStorageForNewAccount = configStorageForAccount( account->accountId() ); + + if ( !configStorageForA || !configStorageForNewAccount || configStorageForA->priority() > configStorageForNewAccount->priority() ) + { + removeAccount( a ); + break; + } + else + { + return; + } + } + } m_accounts.append( account ); if ( account->types() & Accounts::SipType ) @@ -447,6 +430,26 @@ AccountManager::zeroconfAccount() const } +ConfigStorage* +AccountManager::configStorageForAccount( const QString& accountId ) +{ + foreach ( ConfigStorage* cs, m_configStorageById ) + { + if ( cs->accountIds().contains( accountId ) ) + return cs; + } + tLog() << "Warning: defaulting to LocalConfigStorage for account" << accountId; + return localConfigStorage(); +} + + +ConfigStorage* +AccountManager::localConfigStorage() +{ + return m_configStorageById.value( "localconfigstorage" ); +} + + void AccountManager::hookupAccount( Account* account ) const { diff --git a/src/libtomahawk/accounts/AccountManager.h b/src/libtomahawk/accounts/AccountManager.h index 3e74802cc..29ca2766d 100644 --- a/src/libtomahawk/accounts/AccountManager.h +++ b/src/libtomahawk/accounts/AccountManager.h @@ -95,6 +95,8 @@ public: bool isReady() const { return m_completelyReady; } CredentialsManager* credentialsManager() const { return m_creds; } + ConfigStorage* configStorageForAccount( const QString& accountId ); + ConfigStorage* localConfigStorage(); public slots: void connectAll(); @@ -119,17 +121,15 @@ private slots: void init(); void onStateChanged( Tomahawk::Accounts::Account::ConnectionState state ); void onError( int code, const QString& msg ); - void finishLoadingFromConfig( const QStringList& accountIds ); + void finishLoadingFromConfig( const QString& cs ); void onSettingsChanged(); private: - QStringList findPluginFactories(); - void loadPluginFactories( const QStringList &paths ); - void loadPluginFactory( const QString &path ); + void loadPluginFactories(); QString factoryFromId( const QString& accountId ) const; - Account* loadPlugin( const QString &accountId ); + Account* loadPlugin( const QString& accountId ); void hookupAccount( Account* ) const; CredentialsManager* m_creds; @@ -145,11 +145,14 @@ private: QHash< QString, AccountFactory* > m_accountFactories; QList< AccountFactory* > m_factoriesForFilesytem; + QHash< QString, ConfigStorage* > m_configStorageById; + QSet< QString > m_configStorageLoading; + static AccountManager* s_instance; }; -}; +} -}; +} #endif diff --git a/src/libtomahawk/accounts/ConfigStorage.cpp b/src/libtomahawk/accounts/ConfigStorage.cpp new file mode 100644 index 000000000..2208420d6 --- /dev/null +++ b/src/libtomahawk/accounts/ConfigStorage.cpp @@ -0,0 +1,62 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2013, Teo Mrnjavac + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#include "ConfigStorage.h" + + + +namespace Tomahawk +{ + +namespace Accounts +{ + +ConfigStorage::ConfigStorage( QObject* parent ) + : QObject( parent ) +{ +} + + +ConfigStorage::~ConfigStorage() +{ +} + + +QString +ConfigStorage::prettyName() const +{ + return QString(); +} + + +QPixmap +ConfigStorage::icon() const +{ + return QPixmap(); +} + + +bool +ConfigStorage::execConfigDialog( QWidget* parent ) +{ + return false; +} + + +} //ns +} //ns diff --git a/src/libtomahawk/accounts/ConfigStorage.h b/src/libtomahawk/accounts/ConfigStorage.h new file mode 100644 index 000000000..734bc3a4b --- /dev/null +++ b/src/libtomahawk/accounts/ConfigStorage.h @@ -0,0 +1,67 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2013, Teo Mrnjavac + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#ifndef CONFIGSTORAGE_H +#define CONFIGSTORAGE_H + +#include "TomahawkSettings.h" +#include "Account.h" + +#include + +namespace Tomahawk +{ + +namespace Accounts +{ + +class DLLEXPORT ConfigStorage : public QObject +{ + Q_OBJECT +public: + explicit ConfigStorage( QObject* parent = 0 ); + + virtual ~ConfigStorage(); + + virtual void init() = 0; + + virtual QString id() const = 0; + virtual QString prettyName() const; + + virtual QPixmap icon() const; + + virtual bool execConfigDialog( QWidget* parent ); + + virtual QStringList accountIds() const = 0; + + virtual unsigned int priority() const = 0; //LocalConfigStorage has 0, everything else comes later + + virtual void save( const QString& accountId, const Account::Configuration& cfg ) = 0; + virtual void load( const QString& accountId, Account::Configuration& cfg ) = 0; + virtual void remove( const QString& accountId ) = 0; + +signals: + void ready(); //emit this when done with whatever it is that needs to be initialized +}; + +} //namespace Accounts +} //namespace Tomahawk + +Q_DECLARE_INTERFACE( Tomahawk::Accounts::ConfigStorage, "tomahawk.ConfigStorage/1.0" ) + +#endif // CONFIGSTORAGE_H diff --git a/src/libtomahawk/accounts/ConfigStorageDllMacro.h b/src/libtomahawk/accounts/ConfigStorageDllMacro.h new file mode 100644 index 000000000..4a1db7294 --- /dev/null +++ b/src/libtomahawk/accounts/ConfigStorageDllMacro.h @@ -0,0 +1,32 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2013, Teo Mrnjavac + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#ifndef CONFIGSTORAGEDLLMACRO_H +#define CONFIGSTORAGEDLLMACRO_H + +#include + +#ifndef CONFIGSTORAGEDLLEXPORT +# if defined (CONFIGSTORAGEDLLEXPORT_PRO) +# define CONFIGSTORAGEDLLEXPORT Q_DECL_EXPORT +# else +# define CONFIGSTORAGEDLLEXPORT Q_DECL_IMPORT +# endif +#endif + +#endif // CONFIGSTORAGEDLLMACRO_H diff --git a/src/libtomahawk/accounts/CredentialsManager.cpp b/src/libtomahawk/accounts/CredentialsManager.cpp index 38ee1f6df..d0f4802ed 100644 --- a/src/libtomahawk/accounts/CredentialsManager.cpp +++ b/src/libtomahawk/accounts/CredentialsManager.cpp @@ -24,7 +24,6 @@ #include -#define TOMAHAWK_KEYCHAINSVC QLatin1String("Tomahawk") namespace Tomahawk { @@ -32,6 +31,32 @@ namespace Tomahawk namespace Accounts { +CredentialsStorageKey::CredentialsStorageKey( const QString& service, const QString& key ) + : m_service( service ) + , m_key( key ) +{} + +bool +CredentialsStorageKey::operator ==( const CredentialsStorageKey& other ) const +{ + return ( m_key == other.m_key ) && ( m_service == other.m_service ); +} + + +bool +CredentialsStorageKey::operator !=( const CredentialsStorageKey& other ) const +{ + return !operator ==( other ); +} + +uint +qHash( const Tomahawk::Accounts::CredentialsStorageKey& key ) +{ + return qHash( key.service() + key.key() ); +} + + +// CredentialsManager CredentialsManager::CredentialsManager( QObject* parent ) : QObject( parent ) @@ -41,75 +66,118 @@ CredentialsManager::CredentialsManager( QObject* parent ) void -CredentialsManager::loadCredentials( QStringList keys ) +CredentialsManager::addService( const QString& service , const QStringList& accountIds ) { - tDebug() << Q_FUNC_INFO << "keys:" << keys; - foreach ( QString key, keys ) + if ( m_services.contains( service ) ) + m_services.remove( service ); + m_services.insert( service, accountIds ); + loadCredentials( service ); +} + + +void +CredentialsManager::loadCredentials( const QString &service ) +{ + + const QStringList& accountIds = m_services.value( service ); + tDebug() << Q_FUNC_INFO << "keys for service" << service << ":" << accountIds; + foreach ( QString key, accountIds ) { - QKeychain::ReadPasswordJob* j = new QKeychain::ReadPasswordJob( TOMAHAWK_KEYCHAINSVC, this ); + QKeychain::ReadPasswordJob* j = new QKeychain::ReadPasswordJob( service, this ); j->setKey( key ); j->setAutoDelete( false ); #if defined( Q_OS_UNIX ) && !defined( Q_OS_MAC ) j->setInsecureFallback( true ); #endif connect( j, SIGNAL( finished( QKeychain::Job* ) ), - SLOT( keychainJobFinished( QKeychain::Job* ) ) ); - m_readJobs << j; + SLOT( keychainJobFinished( QKeychain::Job* ) ) ); + m_readJobs[ service ] << j; j->start(); tDebug() << "Launching QtKeychain readJob for" << key; } - } QStringList -CredentialsManager::keys() const +CredentialsManager::keys( const QString& service ) const { - QStringList keys = m_credentials.keys(); + QStringList keys; + foreach ( const CredentialsStorageKey& k, m_credentials.keys() ) + { + if ( k.service() == service ) + keys << k.key(); + } return keys; } -QVariantHash -CredentialsManager::credentials( const QString& key ) const +QStringList +CredentialsManager::services() const +{ + return m_services.keys(); +} + + +QVariant +CredentialsManager::credentials( const CredentialsStorageKey& key ) const { return m_credentials.value( key ); } +QVariant +CredentialsManager::credentials( const QString& serviceName, const QString& key ) const +{ + return credentials( CredentialsStorageKey( serviceName, key ) ); +} + + void -CredentialsManager::setCredentials( const QString& key, const QVariantHash& value ) +CredentialsManager::setCredentials( const CredentialsStorageKey& csKey, const QVariant& value, bool tryToWriteAsString ) { QMutexLocker locker( &m_mutex ); QKeychain::Job* j; - if ( value.isEmpty() ) + if ( value.isNull() || + ( value.type() == QVariant::Hash && value.toHash().isEmpty() ) || + ( value.type() == QVariant::String && value.toString().isEmpty() ) ) { - if ( !m_credentials.contains( key ) ) //if we don't have any credentials for this key, we bail + if ( !m_credentials.contains( csKey ) ) //if we don't have any credentials for this key, we bail return; - m_credentials.remove( key ); + m_credentials.remove( csKey ); - QKeychain::DeletePasswordJob* dj = new QKeychain::DeletePasswordJob( TOMAHAWK_KEYCHAINSVC, this ); - dj->setKey( key ); + QKeychain::DeletePasswordJob* dj = new QKeychain::DeletePasswordJob( csKey.service(), this ); + dj->setKey( csKey.key() ); j = dj; } else { - if ( value == m_credentials.value( key ) ) //if the credentials haven't actually changed, we bail + if ( value == m_credentials.value( csKey ) ) //if the credentials haven't actually changed, we bail return; - m_credentials.insert( key, value ); + m_credentials.insert( csKey, value ); - QByteArray data; + QKeychain::WritePasswordJob* wj = new QKeychain::WritePasswordJob( csKey.service(), this ); + wj->setKey( csKey.key() ); + + Q_ASSERT( value.type() == QVariant::String || value.type() == QVariant::Hash ); + + if ( tryToWriteAsString && value.type() == QVariant::String ) { - QDataStream ds( &data, QIODevice::WriteOnly ); - ds << value; + wj->setTextData( value.toString() ); + } + else if ( value.type() == QVariant::Hash ) + { + QByteArray data; + { + QDataStream ds( &data, QIODevice::WriteOnly ); + ds << value.toHash(); + } + + wj->setBinaryData( data ); } - QKeychain::WritePasswordJob* wj = new QKeychain::WritePasswordJob( TOMAHAWK_KEYCHAINSVC, this ); - wj->setKey( key ); - wj->setBinaryData( data ); j = wj; } @@ -123,6 +191,20 @@ CredentialsManager::setCredentials( const QString& key, const QVariantHash& valu } +void +CredentialsManager::setCredentials( const QString& serviceName, const QString& key, const QVariantHash& value ) +{ + setCredentials( CredentialsStorageKey( serviceName, key ), QVariant( value ) ); +} + + +void +CredentialsManager::setCredentials( const QString& serviceName, const QString& key, const QString& value ) +{ + setCredentials( CredentialsStorageKey( serviceName, key ), QVariant( value ), true ); +} + + void CredentialsManager::keychainJobFinished( QKeychain::Job* j ) { @@ -133,22 +215,31 @@ CredentialsManager::keychainJobFinished( QKeychain::Job* j ) { tDebug() << "QtKeychain readJob for" << readJob->key() << "finished without errors"; - QVariantHash creds; - QDataStream dataStream( readJob->binaryData() ); - dataStream >> creds; + QVariant creds; + if ( !readJob->textData().isEmpty() ) + { + creds = QVariant( readJob->textData() ); + } + else //must be a QVH + { + QDataStream dataStream( readJob->binaryData() ); + QVariantHash hash; + dataStream >> hash; + creds = QVariant( hash ); + } - m_credentials.insert( readJob->key(), creds ); + m_credentials.insert( CredentialsStorageKey( readJob->service(), readJob->key() ), creds ); } else { tDebug() << "QtKeychain readJob for" << readJob->key() << "finished with error:" << j->error() << j->errorString(); } - m_readJobs.removeOne( readJob ); + m_readJobs[ readJob->service() ].removeOne( readJob ); - if ( m_readJobs.isEmpty() ) + if ( m_readJobs[ readJob->service() ].isEmpty() ) { - emit ready(); + emit serviceReady( readJob->service() ); } } else if ( QKeychain::WritePasswordJob* writeJob = qobject_cast< QKeychain::WritePasswordJob* >( j ) ) @@ -164,7 +255,6 @@ CredentialsManager::keychainJobFinished( QKeychain::Job* j ) j->deleteLater(); } - } //namespace Accounts } //namespace Tomahawk diff --git a/src/libtomahawk/accounts/CredentialsManager.h b/src/libtomahawk/accounts/CredentialsManager.h index ec751fa6a..851e8d9b6 100644 --- a/src/libtomahawk/accounts/CredentialsManager.h +++ b/src/libtomahawk/accounts/CredentialsManager.h @@ -19,9 +19,12 @@ #ifndef CREDENTIALSMANAGER_H #define CREDENTIALSMANAGER_H +#include "DllMacro.h" + #include #include #include +#include namespace QKeychain @@ -30,49 +33,69 @@ class Job; class ReadPasswordJob; } - namespace Tomahawk { namespace Accounts { +class CredentialsStorageKey +{ +public: + explicit CredentialsStorageKey( const QString &service, const QString &key ); + bool operator ==( const CredentialsStorageKey& other ) const; + bool operator !=( const CredentialsStorageKey& other ) const; + QString service() const { return m_service; } + QString key() const { return m_key; } +private: + QString m_service; + QString m_key; +}; + /** * @brief The CredentialsManager class holds an in-memory cache of whatever credentials are stored * in the system's QtKeychain-accessible credentials storage. - * After instantiating the class, loadCredentials should be called, and this is the only time a read - * operation from QtKeychain is performed. When CredentialsManager emits ready(), it can be used for - * all other operations. The only QtKeychain operations performed at any time after startup are - * write and delete. * This ensures an illusion of synchronous operations for Tomahawk's Account classes, even though all * QtKeychain jobs are async. */ -class CredentialsManager : public QObject +class DLLEXPORT CredentialsManager : public QObject { Q_OBJECT public: explicit CredentialsManager( QObject* parent = 0 ); - void loadCredentials( QStringList keys ); + void addService( const QString& service, const QStringList& accountIds ); - QStringList keys() const; + QStringList keys( const QString& service ) const; + QStringList services() const; - QVariantHash credentials( const QString& key ) const; - void setCredentials( const QString& key, const QVariantHash& value ); + QVariant credentials( const QString& serviceName, const QString& key ) const; //returns QString or QVH + void setCredentials( const QString& serviceName, const QString& key, const QVariantHash& value ); + void setCredentials( const QString& serviceName, const QString& key, const QString& value ); signals: - void ready(); + void serviceReady( const QString& service ); private slots: + void loadCredentials( const QString& service ); + void keychainJobFinished( QKeychain::Job* ); +protected: + QVariant credentials( const CredentialsStorageKey& key ) const; + void setCredentials( const CredentialsStorageKey& key, const QVariant& value, bool tryToWriteAsString = false ); + private: - QHash< QString, QVariantHash > m_credentials; - QList< QKeychain::ReadPasswordJob* > m_readJobs; + QHash< QString, QStringList > m_services; + QHash< CredentialsStorageKey, QVariant > m_credentials; + QHash< QString, QList< QKeychain::ReadPasswordJob* > > m_readJobs; QMutex m_mutex; }; +uint qHash( const Tomahawk::Accounts::CredentialsStorageKey& key ); + } //namespace Accounts } //namespace Tomahawk + #endif // CREDENTIALSMANAGER_H diff --git a/src/libtomahawk/accounts/LocalConfigStorage.cpp b/src/libtomahawk/accounts/LocalConfigStorage.cpp new file mode 100644 index 000000000..aaf490761 --- /dev/null +++ b/src/libtomahawk/accounts/LocalConfigStorage.cpp @@ -0,0 +1,148 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2013, Teo Mrnjavac + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#include "LocalConfigStorage.h" + +#include "Account.h" +#include "AccountManager.h" +#include "CredentialsManager.h" +#include "utils/Logger.h" + +namespace Tomahawk +{ + +namespace Accounts +{ + + +LocalConfigStorage::LocalConfigStorage( QObject* parent ) + : ConfigStorage( parent ) + , m_credentialsServiceName( "Tomahawk" ) +{ + m_accountIds = TomahawkSettings::instance()->accounts(); +} + + +void +LocalConfigStorage::init() +{ + // tell CredentialsManager which account ids it will be writing credentials for and in which svc + + CredentialsManager* cm = AccountManager::instance()->credentialsManager(); + connect( cm, SIGNAL( serviceReady( QString ) ), + this, SLOT( onCredentialsManagerReady( QString ) ) ); + AccountManager::instance()->credentialsManager()->addService( m_credentialsServiceName, + m_accountIds ); + + tDebug() << Q_FUNC_INFO << "LOADING ALL CREDENTIALS FOR SERVICE" << m_credentialsServiceName << m_accountIds; +} + + +QString +LocalConfigStorage::id() const +{ + return "localconfigstorage"; +} + + +void +LocalConfigStorage::onCredentialsManagerReady( const QString& service ) +{ + if ( service != m_credentialsServiceName ) + return; + + //no need to listen for it any more + disconnect( this, SLOT( onCredentialsManagerReady( QString ) ) ); + + emit ready(); +} + + +QStringList +LocalConfigStorage::accountIds() const +{ + return m_accountIds; +} + + +unsigned int +LocalConfigStorage::priority() const +{ + return 0; +} + + +void +LocalConfigStorage::save( const QString& accountId, const Account::Configuration& cfg ) +{ + TomahawkSettings* s = TomahawkSettings::instance(); + s->beginGroup( "accounts/" + accountId ); + s->setValue( "accountfriendlyname", cfg.accountFriendlyName ); + s->setValue( "enabled", cfg.enabled ); + s->setValue( "configuration", cfg.configuration ); + s->setValue( "acl", cfg.acl ); + s->setValue( "types", cfg.types ); + s->endGroup(); + s->sync(); + + CredentialsManager* c = AccountManager::instance()->credentialsManager(); + c->setCredentials( m_credentialsServiceName, accountId, cfg.credentials ); + + if ( !m_accountIds.contains( accountId ) ) + m_accountIds.append( accountId ); +} + + +void +LocalConfigStorage::load( const QString& accountId, Account::Configuration& cfg ) +{ + TomahawkSettings* s = TomahawkSettings::instance(); + s->beginGroup( "accounts/" + accountId ); + cfg.accountFriendlyName = s->value( "accountfriendlyname", QString() ).toString(); + cfg.enabled = s->value( "enabled", false ).toBool(); + cfg.configuration = s->value( "configuration", QVariantHash() ).toHash(); + cfg.acl = s->value( "acl", QVariantMap() ).toMap(); + cfg.types = s->value( "types", QStringList() ).toStringList(); + s->endGroup(); + + CredentialsManager* c = AccountManager::instance()->credentialsManager(); + QVariant credentials = c->credentials( m_credentialsServiceName, accountId ); + if ( credentials.type() == QVariant::Hash ) + cfg.credentials = credentials.toHash(); +} + + +void +LocalConfigStorage::remove( const QString& accountId ) +{ + TomahawkSettings* s = TomahawkSettings::instance(); + s->beginGroup( "accounts/" + accountId ); + s->remove( "accountfriendlyname" ); + s->remove( "enabled" ); + s->remove( "configuration" ); + s->remove( "acl" ); + s->remove( "types" ); + s->endGroup(); + s->remove( "accounts/" + accountId ); + + CredentialsManager* c = AccountManager::instance()->credentialsManager(); + c->setCredentials( m_credentialsServiceName, accountId, QVariantHash() ); +} + +} +} diff --git a/src/libtomahawk/accounts/LocalConfigStorage.h b/src/libtomahawk/accounts/LocalConfigStorage.h new file mode 100644 index 000000000..55347ea13 --- /dev/null +++ b/src/libtomahawk/accounts/LocalConfigStorage.h @@ -0,0 +1,63 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2013, Teo Mrnjavac + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#ifndef LOCALCONFIGSTORAGE_H +#define LOCALCONFIGSTORAGE_H + +#include "ConfigStorage.h" + +namespace Tomahawk +{ + +namespace Accounts +{ + +class LocalConfigStorage : public ConfigStorage +{ + Q_OBJECT +public: + explicit LocalConfigStorage( QObject* parent = 0 ); + + virtual void init(); + + QString id() const; + + QStringList accountIds() const; + + unsigned int priority() const; + + virtual void save( const QString& accountId, const Account::Configuration& cfg ); + virtual void load( const QString& accountId, Account::Configuration& cfg ); + virtual void remove( const QString& accountId ); + + +private slots: + void onCredentialsManagerReady( const QString& service ); + +private: + const QString m_credentialsServiceName; + QStringList m_accountIds; + + static LocalConfigStorage* s_instance; +}; + +} //namespace Accounts + +} //namespace Tomahawk + +#endif // LOCALCONFIGSTORAGE_H diff --git a/src/libtomahawk/accounts/ResolverAccount.cpp b/src/libtomahawk/accounts/ResolverAccount.cpp index 90a93a171..3d884f504 100644 --- a/src/libtomahawk/accounts/ResolverAccount.cpp +++ b/src/libtomahawk/accounts/ResolverAccount.cpp @@ -22,6 +22,9 @@ #include "jobview/JobStatusView.h" #include "jobview/JobStatusModel.h" #include "jobview/ErrorStatusMessage.h" +#include "AccountManager.h" +#include "AtticaManager.h" +#include "ConfigStorage.h" #include "resolvers/ExternalResolver.h" #include "resolvers/ExternalResolverGui.h" #include "utils/Logger.h" @@ -302,6 +305,10 @@ ResolverAccount::ResolverAccount( const QString& accountId, const QString& path, setConfiguration( configuration ); + //just init so this account is tracked by LCS, we'll sync later + if ( !AccountManager::instance()->configStorageForAccount( accountId ) ) + AccountManager::instance()->localConfigStorage()->save( accountId, Account::Configuration() ); + init( path ); sync(); diff --git a/src/libtomahawk/accounts/configstorage/CMakeLists.txt b/src/libtomahawk/accounts/configstorage/CMakeLists.txt new file mode 100644 index 000000000..88ac22f2d --- /dev/null +++ b/src/libtomahawk/accounts/configstorage/CMakeLists.txt @@ -0,0 +1,14 @@ +include( ${CMAKE_CURRENT_LIST_DIR}/../../../../TomahawkAddPlugin.cmake ) + +file(GLOB SUBDIRECTORIES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*") +foreach(SUBDIRECTORY ${SUBDIRECTORIES}) + if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY}" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIRECTORY}/CMakeLists.txt") + if(SUBDIRECTORY STREQUAL "telepathy") + if( TelepathyQt_FOUND ) + add_subdirectory( telepathy ) + endif() + else() + add_subdirectory(${SUBDIRECTORY}) + endif() + endif() +endforeach() diff --git a/src/libtomahawk/accounts/configstorage/telepathy/CMakeLists.txt b/src/libtomahawk/accounts/configstorage/telepathy/CMakeLists.txt new file mode 100644 index 000000000..c303b9c4e --- /dev/null +++ b/src/libtomahawk/accounts/configstorage/telepathy/CMakeLists.txt @@ -0,0 +1,26 @@ +include_directories(${TELEPATHY_QT_INCLUDE_DIR}) + +tomahawk_add_plugin(telepathy + TYPE configstorage + EXPORT_MACRO CONFIGSTORAGEDLLEXPORT_PRO + SOURCES + TelepathyConfigStorage.cpp + TelepathyConfigStorageConfigWidgetPlugin.cpp + LINK_LIBRARIES + ${TOMAHAWK_LIBRARIES} + ${TELEPATHY_QT_LIBRARIES} + SHARED_LIB +) + +if( KDE4_FOUND ) + include_directories( ${KDE4_INCLUDES} ) + tomahawk_add_plugin(kde + TYPE configstorage_telepathy + EXPORT_MACRO CONFIGSTORAGETELEPATHYDLLEXPORT_PRO + SOURCES + KdeTelepathyConfigWidget.cpp + LINK_LIBRARIES + tomahawk_configstorage_telepathy + ${KDE4_KCMUTILS_LIBS} + ) +endif() diff --git a/src/libtomahawk/accounts/configstorage/telepathy/KdeTelepathyConfigWidget.cpp b/src/libtomahawk/accounts/configstorage/telepathy/KdeTelepathyConfigWidget.cpp new file mode 100644 index 000000000..a91683eca --- /dev/null +++ b/src/libtomahawk/accounts/configstorage/telepathy/KdeTelepathyConfigWidget.cpp @@ -0,0 +1,46 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2013, Dominik Schmidt + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#include "KdeTelepathyConfigWidget.h" + +#include "utils/Logger.h" + +#include + +#include + +QWidget* +KdeTelepathyConfigWidget::configWidget() +{ + KCModuleProxy* proxy = new KCModuleProxy( "kcm_ktp_accounts" ); + + if ( !proxy->aboutData() ) + { + qWarning() << "Could not load kcm_ktp_accounts... "; + + delete proxy; + + return 0; + } + + return proxy; +} + +Q_EXPORT_PLUGIN2( TelepathyConfigStorageConfigWidgetPlugin, KdeTelepathyConfigWidget ) + + diff --git a/src/libtomahawk/accounts/configstorage/telepathy/KdeTelepathyConfigWidget.h b/src/libtomahawk/accounts/configstorage/telepathy/KdeTelepathyConfigWidget.h new file mode 100644 index 000000000..61acdbbf2 --- /dev/null +++ b/src/libtomahawk/accounts/configstorage/telepathy/KdeTelepathyConfigWidget.h @@ -0,0 +1,36 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2013, Dominik Schmidt + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#ifndef KDETELEPATHYCONFIGWIDGET_H +#define KDETELEPATHYCONFIGWIDGET_H + +#include "TelepathyConfigStorageConfigWidgetPlugin.h" + +#include "TelepathyConfigStorageConfigWidgetDllMacro.h" + +class CONFIGSTORAGETELEPATHYDLLEXPORT KdeTelepathyConfigWidget : public TelepathyConfigStorageConfigWidgetPlugin +{ + Q_OBJECT + Q_INTERFACES( TelepathyConfigStorageConfigWidgetPlugin ) + +public: + virtual QWidget* configWidget(); +}; + + +#endif // KDETELEPATHYCONFIGWIDGET_H diff --git a/src/libtomahawk/accounts/configstorage/telepathy/TelepathyConfigStorage.cpp b/src/libtomahawk/accounts/configstorage/telepathy/TelepathyConfigStorage.cpp new file mode 100644 index 000000000..6f5ececa5 --- /dev/null +++ b/src/libtomahawk/accounts/configstorage/telepathy/TelepathyConfigStorage.cpp @@ -0,0 +1,291 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2013, Teo Mrnjavac + * Copyright 2013, Dominik Schmidt + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#include "TelepathyConfigStorage.h" + +#include "TelepathyConfigStorageConfigWidgetPlugin.h" + + +#include "accounts/Account.h" +#include "accounts/AccountManager.h" +#include "accounts/CredentialsManager.h" +#include "utils/Logger.h" +#include "utils/PluginLoader.h" +#include "utils/TomahawkUtilsGui.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + + +//NOTE: Both Tomahawk::Accounts and Tp have class names Account and AccountManager. + + +Tomahawk::Accounts::TelepathyConfigStorage::TelepathyConfigStorage( QObject* parent ) + : Tomahawk::Accounts::ConfigStorage( parent ) + , m_credentialsServiceName( "telepathy-kde" ) +{ + tDebug() << Q_FUNC_INFO; + loadConfigWidgetPlugins(); +} + + +void +Tomahawk::Accounts::TelepathyConfigStorage::init() +{ + + m_tpam = Tp::AccountManager::create(); + connect( m_tpam->becomeReady(), SIGNAL( finished( Tp::PendingOperation* ) ), + this, SLOT( onTpAccountManagerReady( Tp::PendingOperation* ) ) ); +} + + +QString +Tomahawk::Accounts::TelepathyConfigStorage::id() const +{ + return "telepathyconfigstorage"; +} + + +QString +Tomahawk::Accounts::TelepathyConfigStorage::prettyName() const +{ + return tr( "the KDE instant messaging framework" ); +} + + +QPixmap +Tomahawk::Accounts::TelepathyConfigStorage::icon() const +{ + return QPixmap( ":/telepathy/kde.png" ); +} + + +bool +Tomahawk::Accounts::TelepathyConfigStorage::execConfigDialog( QWidget* parent ) +{ + if ( !m_configWidgetPlugins.isEmpty() ) + { + QDialog dialog( parent ); + dialog.setWindowTitle( tr( "KDE Instant Messaging Accounts" ) ); + dialog.resize( parent->logicalDpiX() * 3.0, parent->logicalDpiY() * 2.2 ); + dialog.setLayout( new QVBoxLayout ); + dialog.layout()->addWidget( m_configWidgetPlugins.first()->configWidget() ); + + QDialogButtonBox* box = new QDialogButtonBox( QDialogButtonBox::Close, Qt::Horizontal ); + dialog.layout()->addWidget( box ); + connect( box, SIGNAL( clicked( QAbstractButton* ) ), &dialog, SLOT( accept() ) ); + return dialog.exec(); + } + + return false; +} + + +void +Tomahawk::Accounts::TelepathyConfigStorage::onTpAccountManagerReady( Tp::PendingOperation* op ) +{ + if ( op->isError() ) + { + tDebug() << "Telepathy AccountManager cannot become ready:" + << op->errorName() << "-" << op->errorMessage(); + emit ready(); //we bail, this CS is ready to provide 0 accounts + return; + } + + QStringList keychainIds; + foreach ( const Tp::AccountPtr& acc, m_tpam->validAccounts()->accounts() ) + { + if ( acc->protocolName() == "jabber" ) + { + m_accountIds << telepathyPathToAccountId( acc->objectPath(), acc->serviceName() ); + keychainIds << acc->uniqueIdentifier(); + } + } + + // tell CredentialsManager which account ids it will be writing credentials for and in which svc + + CredentialsManager* cm = AccountManager::instance()->credentialsManager(); + connect( cm, SIGNAL( serviceReady( QString ) ), + this, SLOT( onCredentialsManagerReady( QString ) ) ); + Tomahawk::Accounts::AccountManager::instance()->credentialsManager()->addService( m_credentialsServiceName, + keychainIds ); + tDebug() << Q_FUNC_INFO << "LOADING ALL CREDENTIALS FOR SERVICE" << m_credentialsServiceName << m_accountIds << keychainIds; +} + + +void +Tomahawk::Accounts::TelepathyConfigStorage::onCredentialsManagerReady( const QString& service ) +{ + if ( service != m_credentialsServiceName ) + return; + + //no need to listen for it any more + disconnect( this, SLOT( onCredentialsManagerReady( QString ) ) ); + + emit ready(); +} + + +void +Tomahawk::Accounts::TelepathyConfigStorage::loadConfigWidgetPlugins() +{ + tDebug() << Q_FUNC_INFO; + foreach( QObject* plugin, Tomahawk::Utils::PluginLoader( "configstorage_telepathy" ).loadPlugins().values() ) + { + TelepathyConfigStorageConfigWidgetPlugin* configWidgetPlugin = qobject_cast< TelepathyConfigStorageConfigWidgetPlugin* >( plugin ); + if( !configWidgetPlugin ) + { + tLog() << "Tried to load invalid TelepathyConfigStorageConfigWidgetPlugin"; + continue; + } + + m_configWidgetPlugins << configWidgetPlugin; + } +} + + +QString +Tomahawk::Accounts::TelepathyConfigStorage::telepathyPathToAccountId( const QString& objectPath, const QString& telepathyServiceName ) +{ + if ( telepathyServiceName == "google-talk" ) + return QString( "googleaccount_" ) + objectPath; + return QString( "xmppaccount_" ) + objectPath; +} + + +QString +Tomahawk::Accounts::TelepathyConfigStorage::accountIdToTelepathyPath( const QString& accountId ) +{ + QStringList allowedPrefixes; + allowedPrefixes << "xmppaccount_" + << "googleaccount_"; + QString r = accountId; + foreach ( QString prefix, allowedPrefixes ) + { + if ( r.startsWith( prefix ) ) + r.remove( 0, prefix.length() ); + } + return r; +} + + +QStringList +Tomahawk::Accounts::TelepathyConfigStorage::accountIds() const +{ + return m_accountIds; +} + + +unsigned int +Tomahawk::Accounts::TelepathyConfigStorage::priority() const +{ + return 30; +} + + +void +Tomahawk::Accounts::TelepathyConfigStorage::save( const QString& accountId, const Account::Configuration& cfg ) +{ + TomahawkSettings* s = TomahawkSettings::instance(); + s->beginGroup( "externalaccounts/" + accountId ); + s->setValue( "enabled", cfg.enabled ); + s->setValue( "acl", cfg.acl ); + s->endGroup(); + s->sync(); + + if ( !m_accountIds.contains( accountId ) ) + m_accountIds.append( accountId ); +} + + +void +Tomahawk::Accounts::TelepathyConfigStorage::load( const QString& accountId, Account::Configuration& cfg ) +{ + TomahawkSettings* s = TomahawkSettings::instance(); + s->beginGroup( "externalaccounts/" + accountId ); + cfg.enabled = s->value( "enabled", true ).toBool(); + cfg.acl = s->value( "acl", QVariantMap() ).toMap(); + s->endGroup(); + + + Tp::AccountPtr account = m_tpam->accountForObjectPath( accountIdToTelepathyPath( accountId ) ); + + if ( !account->normalizedName().isEmpty() ) + cfg.accountFriendlyName = account->normalizedName(); + else if ( !account->parameters()[ "account" ].isNull() ) + cfg.accountFriendlyName = account->parameters()[ "account" ].toString(); + + if ( cfg.accountFriendlyName.isEmpty() ) //this should never happen + cfg.accountFriendlyName = accountId; + + QStringList types; + types << "SipType"; + cfg.types = types; + + if ( account->serviceName() == "google-talk" || + account->parameters()[ "port" ].isNull() ) + cfg.configuration[ "port" ] = "5222"; + else + cfg.configuration[ "port" ] = account->parameters()[ "port" ].toString(); + + if ( !account->parameters()[ "server" ].isNull() ) + cfg.configuration[ "server" ] = account->parameters()[ "server" ].toString(); + + if ( !account->parameters()[ "require-encryption" ].isNull() ) + cfg.configuration[ "enforcesecure" ] = account->parameters()[ "require-encryption" ].toBool(); + + cfg.configuration[ "publishtracks" ] = true; + + Tomahawk::Accounts::CredentialsManager* c = Tomahawk::Accounts::AccountManager::instance()->credentialsManager(); + cfg.credentials = QVariantHash(); + + if ( !account->parameters()[ "account" ].isNull() ) + cfg.credentials[ "username" ] = account->parameters()[ "account" ].toString(); + else + cfg.credentials[ "username" ] = account->normalizedName(); + + QVariant credentials = c->credentials( m_credentialsServiceName, account->uniqueIdentifier() ); + if ( credentials.type() == QVariant::String ) + cfg.credentials[ "password" ] = credentials.toString(); + + cfg.configuration[ "read-only" ] = true; +} + + +void +Tomahawk::Accounts::TelepathyConfigStorage::remove( const QString& accountId ) +{ + TomahawkSettings* s = TomahawkSettings::instance(); + s->beginGroup( "externalaccounts/" + accountId ); + s->remove( "enabled" ); + s->remove( "acl" ); + s->endGroup(); + s->remove( "externalaccounts/" + accountId ); +} + +Q_EXPORT_PLUGIN2( Tomahawk::Accounts::ConfigStorage, Tomahawk::Accounts::TelepathyConfigStorage ) diff --git a/src/libtomahawk/accounts/configstorage/telepathy/TelepathyConfigStorage.h b/src/libtomahawk/accounts/configstorage/telepathy/TelepathyConfigStorage.h new file mode 100644 index 000000000..d21265fa7 --- /dev/null +++ b/src/libtomahawk/accounts/configstorage/telepathy/TelepathyConfigStorage.h @@ -0,0 +1,86 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2013, Teo Mrnjavac + * Copyright 2013, Dominik Schmidt + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#ifndef TELEPATHYCONFIGSTORAGE_H +#define TELEPATHYCONFIGSTORAGE_H + +#include "accounts/ConfigStorageDllMacro.h" +#include "accounts/ConfigStorage.h" + +#include + +namespace Tp +{ +class PendingOperation; +} + +class TelepathyConfigStorageConfigWidgetPlugin; + +namespace Tomahawk +{ + +namespace Accounts +{ + +class CONFIGSTORAGEDLLEXPORT TelepathyConfigStorage : public ConfigStorage +{ + Q_OBJECT + Q_INTERFACES( Tomahawk::Accounts::ConfigStorage ) +public: + explicit TelepathyConfigStorage( QObject* parent = 0 ); + + void init(); + + QString id() const; + QString prettyName() const; + QPixmap icon() const; + + bool execConfigDialog( QWidget* parent ); + + QStringList accountIds() const; + + unsigned int priority() const; + + virtual void save( const QString& accountId, const Account::Configuration& cfg ); + virtual void load( const QString& accountId, Account::Configuration& cfg ); + virtual void remove( const QString& accountId ); + +private slots: + void onTpAccountManagerReady( Tp::PendingOperation* op ); + void onCredentialsManagerReady( const QString& service ); + +private: + void loadConfigWidgetPlugins(); + + QString telepathyPathToAccountId( const QString& objectPath, const QString& telepathyServiceName ); + QString accountIdToTelepathyPath( const QString& accountId ); + + const QString m_credentialsServiceName; + QStringList m_accountIds; + Tp::AccountManagerPtr m_tpam; + QList< TelepathyConfigStorageConfigWidgetPlugin* > m_configWidgetPlugins; + + static TelepathyConfigStorage* s_instance; +}; + +} //namespace Accounts + +} //namespace Tomahawk + +#endif // TELEPATHYCONFIGSTORAGE_H diff --git a/src/libtomahawk/accounts/configstorage/telepathy/TelepathyConfigStorageConfigWidgetDllMacro.h b/src/libtomahawk/accounts/configstorage/telepathy/TelepathyConfigStorageConfigWidgetDllMacro.h new file mode 100644 index 000000000..5e72f192f --- /dev/null +++ b/src/libtomahawk/accounts/configstorage/telepathy/TelepathyConfigStorageConfigWidgetDllMacro.h @@ -0,0 +1,32 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2013, Teo Mrnjavac + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#ifndef TELEPATHYCONFIGSTORAGECONFIGWIDGETDLLMACRO_H +#define TELEPATHYCONFIGSTORAGECONFIGWIDGETDLLMACRO_H + +#include + +#ifndef CONFIGSTORAGETELEPATHYDLLEXPORT +# if defined (CONFIGSTORAGETELEPATHYDLLEXPORT_PRO) +# define CONFIGSTORAGETELEPATHYDLLEXPORT Q_DECL_EXPORT +# else +# define CONFIGSTORAGETELEPATHYDLLEXPORT Q_DECL_IMPORT +# endif +#endif + +#endif // TELEPATHYCONFIGSTORAGECONFIGWIDGETDLLMACRO_H diff --git a/src/libtomahawk/accounts/configstorage/telepathy/TelepathyConfigStorageConfigWidgetPlugin.cpp b/src/libtomahawk/accounts/configstorage/telepathy/TelepathyConfigStorageConfigWidgetPlugin.cpp new file mode 100644 index 000000000..860632542 --- /dev/null +++ b/src/libtomahawk/accounts/configstorage/telepathy/TelepathyConfigStorageConfigWidgetPlugin.cpp @@ -0,0 +1,23 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2013, Dominik Schmidt + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#include "TelepathyConfigStorageConfigWidgetPlugin.h" + +TelepathyConfigStorageConfigWidgetPlugin::~TelepathyConfigStorageConfigWidgetPlugin() +{ +} diff --git a/src/libtomahawk/accounts/configstorage/telepathy/TelepathyConfigStorageConfigWidgetPlugin.h b/src/libtomahawk/accounts/configstorage/telepathy/TelepathyConfigStorageConfigWidgetPlugin.h new file mode 100644 index 000000000..06a665da8 --- /dev/null +++ b/src/libtomahawk/accounts/configstorage/telepathy/TelepathyConfigStorageConfigWidgetPlugin.h @@ -0,0 +1,38 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2013, Teo Mrnjavac + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#ifndef TELEPATHYCONFIGSTORAGECONFIGWIDGETPLUGIN_H +#define TELEPATHYCONFIGSTORAGECONFIGWIDGETPLUGIN_H + +#include + +#include "accounts/ConfigStorageDllMacro.h" + +class CONFIGSTORAGEDLLEXPORT TelepathyConfigStorageConfigWidgetPlugin : public QObject +{ +Q_OBJECT + +public: + virtual ~TelepathyConfigStorageConfigWidgetPlugin(); + + virtual QWidget* configWidget() = 0; +}; + +Q_DECLARE_INTERFACE( TelepathyConfigStorageConfigWidgetPlugin, "tomahawk.TelepathyConfigStorageConfigWidget/1.0" ) + +#endif // TELEPATHYCONFIGSTORAGE_H diff --git a/src/libtomahawk/accounts/configstorage/telepathy/kde.png b/src/libtomahawk/accounts/configstorage/telepathy/kde.png new file mode 100644 index 000000000..3efaaf808 Binary files /dev/null and b/src/libtomahawk/accounts/configstorage/telepathy/kde.png differ diff --git a/src/libtomahawk/accounts/configstorage/telepathy/resources.qrc b/src/libtomahawk/accounts/configstorage/telepathy/resources.qrc new file mode 100644 index 000000000..2dd0f273e --- /dev/null +++ b/src/libtomahawk/accounts/configstorage/telepathy/resources.qrc @@ -0,0 +1,5 @@ + + + kde.png + + diff --git a/src/libtomahawk/infosystem/InfoSystemWorker.cpp b/src/libtomahawk/infosystem/InfoSystemWorker.cpp index fbe974f2e..3ca764bfb 100644 --- a/src/libtomahawk/infosystem/InfoSystemWorker.cpp +++ b/src/libtomahawk/infosystem/InfoSystemWorker.cpp @@ -27,15 +27,14 @@ #include "GlobalActionManager.h" #include "InfoSystemCache.h" #include "PlaylistEntry.h" +#include "utils/TomahawkUtils.h" +#include "utils/Logger.h" +#include "utils/PluginLoader.h" #include "Source.h" - #include -#include -#include #include #include -#include namespace Tomahawk { @@ -82,7 +81,7 @@ InfoSystemWorker::init( Tomahawk::InfoSystem::InfoSystemCache* cache ) m_shortLinksWaiting = 0; m_cache = cache; - loadInfoPlugins( findInfoPlugins() ); + loadInfoPlugins(); } @@ -165,80 +164,23 @@ InfoSystemWorker::removeInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin ) } -QStringList -InfoSystemWorker::findInfoPlugins() -{ - QStringList paths; - QList< QDir > pluginDirs; - - QDir appDir( qApp->applicationDirPath() ); -#ifdef Q_WS_MAC - if ( appDir.dirName() == "MacOS" ) - { - // Development convenience-hack - appDir.cdUp(); - appDir.cdUp(); - appDir.cdUp(); - } -#endif - - QDir libDir( CMAKE_INSTALL_PREFIX "/lib" ); - - QDir lib64Dir( appDir ); - lib64Dir.cdUp(); - lib64Dir.cd( "lib64" ); - - pluginDirs << appDir << libDir << lib64Dir << QDir( qApp->applicationDirPath() ); - foreach ( const QDir& pluginDir, pluginDirs ) - { - tDebug() << Q_FUNC_INFO << "Checking directory for plugins:" << pluginDir; - foreach ( QString fileName, pluginDir.entryList( QStringList() << "*tomahawk_infoplugin_*.so" << "*tomahawk_infoplugin_*.dylib" << "*tomahawk_infoplugin_*.dll", QDir::Files ) ) - { - if ( fileName.startsWith( "libtomahawk_infoplugin" ) ) - { - const QString path = pluginDir.absoluteFilePath( fileName ); - if ( !paths.contains( path ) ) - paths << path; - } - } - } - - return paths; -} - - void -InfoSystemWorker::loadInfoPlugins( const QStringList& pluginPaths ) +InfoSystemWorker::loadInfoPlugins() { - tDebug() << Q_FUNC_INFO << "Attempting to load the following plugin paths:" << pluginPaths; - - if ( pluginPaths.isEmpty() ) - return; - - foreach ( const QString fileName, pluginPaths ) + QHash< QString, QObject* > plugins = Tomahawk::Utils::PluginLoader( "infoplugin" ).loadPlugins(); + foreach ( QObject* plugin, plugins.values() ) { - if ( !QLibrary::isLibrary( fileName ) ) - continue; - - tDebug() << Q_FUNC_INFO << "Trying to load plugin:" << fileName; - - QPluginLoader loader( fileName ); - QObject* plugin = loader.instance(); - if ( !plugin ) - { - tDebug() << Q_FUNC_INFO << "Error loading plugin:" << loader.errorString(); - continue; - } - InfoPlugin* infoPlugin = qobject_cast< InfoPlugin* >( plugin ); if ( infoPlugin ) { - tDebug() << Q_FUNC_INFO << "Loaded info plugin:" << loader.fileName(); - infoPlugin->setFriendlyName( loader.fileName() ); + tDebug() << Q_FUNC_INFO << "Loaded info plugin:" << plugins.key( plugin ); + infoPlugin->setFriendlyName( plugins.key( plugin ) ); addInfoPlugin( InfoPluginPtr( infoPlugin ) ); } else - tDebug() << Q_FUNC_INFO << "Loaded invalid plugin:" << loader.fileName(); + { + tDebug() << Q_FUNC_INFO << "Loaded invalid plugin:" << plugins.key( plugin ); + } } } diff --git a/src/libtomahawk/infosystem/InfoSystemWorker.h b/src/libtomahawk/infosystem/InfoSystemWorker.h index 96a0ddb8f..df966e064 100644 --- a/src/libtomahawk/infosystem/InfoSystemWorker.h +++ b/src/libtomahawk/infosystem/InfoSystemWorker.h @@ -68,8 +68,7 @@ public slots: void addInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin ); void removeInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin ); - QStringList findInfoPlugins(); - void loadInfoPlugins( const QStringList &pluginPaths ); + void loadInfoPlugins(); void getShortUrl( Tomahawk::InfoSystem::InfoPushData data ); void shortLinkReady( QUrl longUrl, QUrl shortUrl, QVariant callbackObj ); diff --git a/src/libtomahawk/utils/PluginLoader.cpp b/src/libtomahawk/utils/PluginLoader.cpp new file mode 100644 index 000000000..f1a056f99 --- /dev/null +++ b/src/libtomahawk/utils/PluginLoader.cpp @@ -0,0 +1,172 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Christian Muehlhaeuser + * Copyright 2010-2012, Leo Franchi + * Copyright 2010-2011, Jeff Mitchell + * Copyright 2013, Teo Mrnjavac + * Copyright 2013, Dominik Schmidt + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#include "PluginLoader.h" +#include "PluginLoader_p.h" + +#include "config.h" + +#include "utils/Logger.h" + +#include +#include +#include +#include + +#include "DllMacro.h" + + +namespace Tomahawk +{ + +namespace Utils +{ + + +PluginLoader::PluginLoader( const QString& type ) + : d_ptr( new PluginLoaderPrivate( this ) ) +{ + Q_D( PluginLoader ); + + d->type = type; +} + + +PluginLoader::~PluginLoader() +{ + delete d_ptr; +} + + +const QHash< QString, QObject* > PluginLoader::loadPlugins() const +{ + tLog() << "Load plugins of type" << d_ptr->type; + + const QString errorMessage("Error loading plugin: %1: %2"); + + QHash< QString, QObject* > plugins; + + foreach( const QString& pluginPath, pluginPaths() ) + { +// tDebug() << Q_FUNC_INFO << "Trying to load plugin:" << pluginPath; + + if ( !QLibrary::isLibrary( pluginPath ) ) + { + tLog() << Q_FUNC_INFO << errorMessage.arg( pluginPath, "Not a library" ); + continue; + } + + QPluginLoader loader( pluginPath ); + + QObject* plugin = loader.instance(); + if ( !plugin ) + { + tLog() << Q_FUNC_INFO << errorMessage.arg( pluginPath, loader.errorString() ); + continue; + } + + plugins.insert( loader.fileName(), plugin ); + } + + return plugins; +} + + +const QList< QDir > +PluginLoader::pluginDirs() +{ + QList< QDir > pluginDirs; + + QDir appDir( QCoreApplication::instance()->applicationDirPath() ); +#ifdef Q_WS_MAC + if ( appDir.dirName() == "MacOS" ) + { + // Development convenience-hack + appDir.cdUp(); + appDir.cdUp(); + appDir.cdUp(); + } +#endif + + QDir libDir( CMAKE_INSTALL_PREFIX "/lib" ); + + QDir lib64Dir( appDir ); + lib64Dir.cdUp(); + lib64Dir.cd( "lib64" ); + + pluginDirs << appDir << libDir << lib64Dir << QDir( qApp->applicationDirPath() ); + return pluginDirs; +} + + +const QStringList +PluginLoader::pluginFilenames( const QString& name ) const +{ + //TODO: ifdef! + const QStringList extensions = QStringList() + << "so" + << "dll" + << "dylib"; + + + QStringList fileNames; + foreach( const QString& extension, extensions ) + { + fileNames << QString("libtomahawk_%1_%2.%3") + .arg( d_ptr->type ) + .arg( name ) + .arg( extension ); + } + + return fileNames; +} + + +const QStringList +PluginLoader::pluginPaths( const QString& name ) const +{ + const QString type = d_ptr->type; + + QSet< QString > paths; + foreach ( const QDir& pluginDir, pluginDirs() ) + { + tDebug() << Q_FUNC_INFO << "Checking directory for" << type << "plugins:" << pluginDir; + foreach ( QString fileName, pluginDir.entryList( pluginFilenames( name ), QDir::Files ) ) + { + //TODO: do we really need to check this?! + if ( fileName.startsWith( QString( "libtomahawk_%1" ).arg( type ) ) ) + { + const QString path = pluginDir.absoluteFilePath( fileName ); + paths << path; + } + } + } + + tDebug() << Q_FUNC_INFO << type << "plugin file paths:" << paths; + + return paths.toList(); +} + + +} // ns utils + +} // ns Tomahawk diff --git a/src/libtomahawk/utils/PluginLoader.h b/src/libtomahawk/utils/PluginLoader.h new file mode 100644 index 000000000..2cc495eb0 --- /dev/null +++ b/src/libtomahawk/utils/PluginLoader.h @@ -0,0 +1,57 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2013, Dominik Schmidt + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#ifndef LIBTOMAHAWK_UTILS_PLUGINLOADER_H +#define LIBTOMAHAWK_UTILS_PLUGINLOADER_H + +#include + +#include "DllMacro.h" + +class QDir; +class PluginLoaderPrivate; + +namespace Tomahawk +{ + +namespace Utils +{ + +class DLLEXPORT PluginLoader +{ +public: + PluginLoader( const QString& type ); + virtual ~PluginLoader(); + + const QHash< QString, QObject* > loadPlugins() const; + +private: + const QStringList pluginFilenames( const QString& name = "*" ) const; + const QStringList pluginPaths( const QString& name = "*" ) const; + + static const QList< QDir > pluginDirs(); + + Q_DECLARE_PRIVATE( PluginLoader ); + PluginLoaderPrivate* d_ptr; +}; + +} + +} + +#endif // LIBTOMAHAWK_UTILS_PLUGINLOADER_H diff --git a/src/libtomahawk/utils/PluginLoader_p.h b/src/libtomahawk/utils/PluginLoader_p.h new file mode 100644 index 000000000..ed34790f7 --- /dev/null +++ b/src/libtomahawk/utils/PluginLoader_p.h @@ -0,0 +1,41 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2013, Dominik Schmidt + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#include + +namespace Tomahawk +{ + namespace Utils + { + class PluginLoader; + } +} + +class PluginLoaderPrivate +{ +public: + PluginLoaderPrivate( Tomahawk::Utils::PluginLoader* q ) + : q_ptr ( q ) + { + } + + Tomahawk::Utils::PluginLoader* q_ptr; + Q_DECLARE_PUBLIC ( Tomahawk::Utils::PluginLoader ) + + QString type; +}; diff --git a/src/tomahawk/Config.h.in b/src/tomahawk/Config.h.in index 60e0c37ec..e1d5aedbf 100644 --- a/src/tomahawk/Config.h.in +++ b/src/tomahawk/Config.h.in @@ -19,7 +19,6 @@ #cmakedefine WITH_UPOWER #cmakedefine WITH_GNOMESHORTCUTHANDLER - #cmakedefine LIBLASTFM_FOUND #cmakedefine QCA2_FOUND diff --git a/src/tomahawk/TomahawkApp.cpp b/src/tomahawk/TomahawkApp.cpp index dbb07c2e8..eae770e91 100644 --- a/src/tomahawk/TomahawkApp.cpp +++ b/src/tomahawk/TomahawkApp.cpp @@ -104,7 +104,6 @@ #include #endif -#include #include #include #include