diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e37c1fa33..f45615699 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -189,6 +189,7 @@ IF(GLOOX_FOUND) SET( tomahawkHeaders ${tomahawkHeaders} xmppbot/xmppbot.h ) SET( tomahawkSources ${tomahawkSources} xmppbot/xmppbot.cpp ) ENDIF(GLOOX_FOUND) +ADD_SUBDIRECTORY( accounts ) ADD_SUBDIRECTORY( sip ) IF(QCA2_FOUND) diff --git a/src/accounts/CMakeLists.txt b/src/accounts/CMakeLists.txt new file mode 100644 index 000000000..37e10994b --- /dev/null +++ b/src/accounts/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory( twitter ) diff --git a/src/accounts/twitter/CMakeLists.txt b/src/accounts/twitter/CMakeLists.txt new file mode 100644 index 000000000..80587ad75 --- /dev/null +++ b/src/accounts/twitter/CMakeLists.txt @@ -0,0 +1,54 @@ +project( tomahawk ) + +include( ${QT_USE_FILE} ) +add_definitions( ${QT_DEFINITIONS} ) +add_definitions( -DQT_PLUGIN ) +add_definitions( -DQT_SHARED ) +add_definitions( -DDLLEXPORT_PRO ) + +set( twitterAccountSources + twitteraccount.cpp + twitterconfigwidget.cpp + tomahawkoauthtwitter.cpp +) + +set( twitterAccountHeaders + twitteraccount.h + twitterconfigwidget.h + tomahawkoauthtwitter.h +) + +set( twitterAccountUI + twitterconfigwidget.ui +) + +include_directories( . ${CMAKE_CURRENT_BINARY_DIR} .. + ${QT_INCLUDE_DIR} + ${QTWEETLIB_INCLUDE_DIR} +) + +qt4_add_resources( RC_SRCS "resources.qrc" ) +qt4_wrap_cpp( twitterAccountMoc ${twitterAccountHeaders} ) +qt4_wrap_ui( twitterAccountUI_H ${twitterAccountUI} ) +add_library( tomahawk_account_twitter SHARED ${twitterAccountUI_H} ${twitterAccountSources} ${twitterAccountMoc} ${RC_SRCS} ) + +IF( WIN32 ) +SET( OS_SPECIFIC_LINK_LIBRARIES + ${OS_SPECIFIC_LINK_LIBRARIES} + "winmm.dll" + "iphlpapi.a" +) +ENDIF( WIN32 ) + +target_link_libraries( tomahawk_account_twitter + ${TOMAHAWK_LIBRARIES} + ${QTWEETLIB_LIBRARIES} + ${QT_LIBRARIES} + ${OS_SPECIFIC_LINK_LIBRARIES} +) + +IF( APPLE ) +# SET( CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} "-undefined dynamic_lookup" ) +ENDIF( APPLE ) + +install( TARGETS tomahawk_account_twitter DESTINATION lib${LIB_SUFFIX} ) diff --git a/src/accounts/twitter/resources.qrc b/src/accounts/twitter/resources.qrc new file mode 100644 index 000000000..fc7df302f --- /dev/null +++ b/src/accounts/twitter/resources.qrc @@ -0,0 +1,5 @@ + + +twitter-icon.png + + diff --git a/src/accounts/twitter/tomahawkoauthtwitter.cpp b/src/accounts/twitter/tomahawkoauthtwitter.cpp new file mode 100644 index 000000000..35cd98a9e --- /dev/null +++ b/src/accounts/twitter/tomahawkoauthtwitter.cpp @@ -0,0 +1,32 @@ +#include "tomahawkoauthtwitter.h" + +#include + +#include "utils/logger.h" + + +TomahawkOAuthTwitter::TomahawkOAuthTwitter( QNetworkAccessManager *nam, QObject* parent ) + : OAuthTwitter( QByteArray::fromBase64( "QzR2NFdmYTIxcmZJRGNrNEhNUjNB" ), QByteArray::fromBase64( "elhTalU2Ympydmc2VVZNSlg0SnVmcUh5amozaWV4dFkxNFNSOXVCRUFv" ), parent ) +{ + setNetworkAccessManager( nam ); +} + + +int +TomahawkOAuthTwitter::authorizationWidget() +{ + bool ok; + int i = QInputDialog::getInt(0, tr( "Twitter PIN" ), tr( "After authenticating on Twitter's web site,\nenter the displayed PIN number here:" ), 0, 0, 2147483647, 1, &ok); + if (ok) + return i; + + return 0; +} + +void +TomahawkOAuthTwitter::error() +{ + qDebug() << Q_FUNC_INFO; + setOAuthToken( QString().toLatin1() ); + setOAuthTokenSecret( QString().toLatin1() ); +} diff --git a/src/accounts/twitter/tomahawkoauthtwitter.h b/src/accounts/twitter/tomahawkoauthtwitter.h new file mode 100644 index 000000000..72cd3329c --- /dev/null +++ b/src/accounts/twitter/tomahawkoauthtwitter.h @@ -0,0 +1,25 @@ +#ifndef TOMAHAWKOAUTHTWITTERACCOUNT +#define TOMAHAWKOAUTHTWITTERACCOUNT + +#include "dllmacro.h" + +#include +#include + +class DLLEXPORT TomahawkOAuthTwitter : public OAuthTwitter +{ + Q_OBJECT + +public: + TomahawkOAuthTwitter( QNetworkAccessManager *nam, QObject *parent = 0 ); + + ~TomahawkOAuthTwitter() {} + +protected: + virtual int authorizationWidget(); + +private slots: + void error(); +}; + +#endif diff --git a/src/accounts/twitter/twitter-icon.png b/src/accounts/twitter/twitter-icon.png new file mode 100644 index 000000000..aab1fca87 Binary files /dev/null and b/src/accounts/twitter/twitter-icon.png differ diff --git a/src/accounts/twitter/twitteraccount.cpp b/src/accounts/twitter/twitteraccount.cpp new file mode 100644 index 000000000..f283da14c --- /dev/null +++ b/src/accounts/twitter/twitteraccount.cpp @@ -0,0 +1,77 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Christian Muehlhaeuser + * + * 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 "twitteraccount.h" + +#include "twitterconfigwidget.h" + +#include + +namespace Tomahawk +{ + +namespace Accounts +{ + +Account* +TwitterAccountFactory::createAccount( const QString& accountId ) +{ + return new TwitterAccount( accountId.isEmpty() ? Tomahawk::Accounts::generateId( factoryId() ) : accountId ); +} + + +TwitterAccount::TwitterAccount( const QString &accountId ) + : Account( accountId ) + , m_isAuthenticated( false ) +{ + loadFromConfig( accountId ); + + setAccountServiceName( "Twitter" ); + QSet< AccountType > types; + types << InfoType; + setTypes( types ); + + m_configWidget = QWeakPointer< TwitterConfigWidget >( new TwitterConfigWidget( this, 0 ) ); + connect( m_configWidget.data(), SIGNAL( twitterAuthed( bool ) ), SLOT( configDialogAuthedSignalSlot( bool ) ) ); +} + + +TwitterAccount::~TwitterAccount() +{ + +} + + +void +TwitterAccount::configDialogAuthedSignalSlot( bool authed ) +{ + m_isAuthenticated = authed; + if ( !credentials()[ "username" ].toString().isEmpty() ) + setAccountFriendlyName( QString( "@%1" ).arg( credentials()[ "username" ].toString() ) ); + syncConfig(); + emit configurationChanged(); +} + + +} + +} + +#ifndef GOOGLE_WRAPPER +Q_EXPORT_PLUGIN2( Tomahawk::Accounts::AccountFactory, Tomahawk::Accounts::TwitterAccountFactory ) +#endif \ No newline at end of file diff --git a/src/accounts/twitter/twitteraccount.h b/src/accounts/twitter/twitteraccount.h new file mode 100644 index 000000000..af51cee17 --- /dev/null +++ b/src/accounts/twitter/twitteraccount.h @@ -0,0 +1,87 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Christian Muehlhaeuser + * + * 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 TWITTERACCOUNT_H +#define TWITTERACCOUNT_H + +#include "dllmacro.h" + +#include "twitterconfigwidget.h" +#include "tomahawkoauthtwitter.h" + +#include "accounts/account.h" + +#define MYNAME "ACCOUNTTWITTER" + +namespace Tomahawk +{ + +namespace Accounts +{ + +class DLLEXPORT TwitterAccountFactory : public AccountFactory +{ + Q_OBJECT + Q_INTERFACES( Tomahawk::Accounts::AccountFactory ) + +public: + TwitterAccountFactory() {} + virtual ~TwitterAccountFactory() {} + + QString prettyName() const { return "Twitter"; } + QString factoryId() const { return "twitteraccount"; } + QIcon icon() const { return QIcon( ":/twitter-icon.png" ); } + Account* createAccount( const QString& pluginId = QString() ); +}; + +class DLLEXPORT TwitterAccount : public Account +{ + Q_OBJECT + +public: + TwitterAccount( const QString &accountId ); + virtual ~TwitterAccount(); + + QIcon icon() const { return QIcon( ":/twitter-icon.png" ); } + + bool canSelfAuthenticate() { return false; } + bool authenticate() { return false; } + bool isAuthenticated() { return m_isAuthenticated; } + + Tomahawk::InfoSystem::InfoPlugin* infoPlugin() { return 0; } + SipPlugin* sipPlugin() { return 0; } + + QWidget* configurationWidget() { return m_configWidget.data(); } + QWidget* aclWidget() { return 0; } + +private slots: + void configDialogAuthedSignalSlot( bool authed ); + +private: + bool m_isAuthenticated; + QWeakPointer< TwitterConfigWidget > m_configWidget; + + // for settings access + friend class TwitterConfigWidget; +}; + +}; + +}; + +#endif diff --git a/src/accounts/twitter/twitterconfigwidget.cpp b/src/accounts/twitter/twitterconfigwidget.cpp new file mode 100644 index 000000000..f308bd74f --- /dev/null +++ b/src/accounts/twitter/twitterconfigwidget.cpp @@ -0,0 +1,294 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Christian Muehlhaeuser + * + * 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 "twitterconfigwidget.h" +#include "twitteraccount.h" +#include "ui_twitterconfigwidget.h" + +#include "tomahawksettings.h" +#include "utils/tomahawkutils.h" +#include "database/database.h" + +#include "tomahawkoauthtwitter.h" +#include +#include +#include + +#include + +#include "utils/logger.h" + +namespace Tomahawk +{ + +namespace Accounts +{ + +TwitterConfigWidget::TwitterConfigWidget( TwitterAccount* account, QWidget *parent ) : + QWidget( parent ), + ui( new Ui::TwitterConfigWidget ), + m_account( account ) +{ + ui->setupUi( this ); + + connect( ui->twitterAuthenticateButton, SIGNAL( pressed() ), + this, SLOT( authDeauthTwitter() ) ); + connect( ui->twitterTweetGotTomahawkButton, SIGNAL( pressed() ), + this, SLOT( startPostGotTomahawkStatus() ) ); + connect( ui->twitterTweetComboBox, SIGNAL( currentIndexChanged( int ) ), + this, SLOT( tweetComboBoxIndexChanged( int ) ) ); + + ui->twitterTweetComboBox->setCurrentIndex( 0 ); + ui->twitterTweetGotTomahawkButton->setText( tr( "Tweet!" ) ); + + QVariantHash credentials = m_account->credentials(); + + if ( credentials[ "oauthtoken" ].toString().isEmpty() || + credentials[ "oauthtokensecret" ].toString().isEmpty() || + credentials[ "username" ].toString().isEmpty() ) + { + ui->twitterStatusLabel->setText( tr( "Status: No saved credentials" ) ); + ui->twitterAuthenticateButton->setText( tr( "Authenticate" ) ); + ui->twitterSyncGroupBox->setVisible( false ); + + emit twitterAuthed( false ); + } + else + { + ui->twitterStatusLabel->setText( tr( "Status: Credentials saved for %1" ).arg( m_account->credentials()[ "username" ].toString() ) ); + ui->twitterAuthenticateButton->setText( tr( "De-authenticate" ) ); + ui->twitterSyncGroupBox->setVisible( true ); + ui->twitterUserTweetLineEdit->setVisible( false ); + + emit twitterAuthed( true ); + } + +} + +TwitterConfigWidget::~TwitterConfigWidget() +{ + delete ui; +} + +void +TwitterConfigWidget::authDeauthTwitter() +{ + if ( ui->twitterAuthenticateButton->text() == tr( "Authenticate" ) ) //FIXME: don't rely on UI strings here! + authenticateTwitter(); + else + deauthenticateTwitter(); +} + +void +TwitterConfigWidget::authenticateTwitter() +{ + qDebug() << Q_FUNC_INFO; + TomahawkOAuthTwitter *twitAuth = new TomahawkOAuthTwitter( TomahawkUtils::nam(), this ); + twitAuth->authorizePin(); + + QVariantHash credentials = m_account->credentials(); + credentials[ "oauthtoken" ] = twitAuth->oauthToken(); + credentials[ "oauthtokensecret" ] = twitAuth->oauthTokenSecret(); + m_account->setCredentials( credentials ); + + QTweetAccountVerifyCredentials *credVerifier = new QTweetAccountVerifyCredentials( twitAuth, this ); + connect( credVerifier, SIGNAL( parsedUser( const QTweetUser & ) ), SLOT( authenticateVerifyReply( const QTweetUser & ) ) ); + connect( credVerifier, SIGNAL( error( QTweetNetBase::ErrorCode, QString ) ), SLOT( authenticateVerifyError( QTweetNetBase::ErrorCode, QString ) ) ); + credVerifier->verify(); +} + +void +TwitterConfigWidget::authenticateVerifyReply( const QTweetUser &user ) +{ + qDebug() << Q_FUNC_INFO; + if ( user.id() == 0 ) + { + QMessageBox::critical( this, tr("Tweetin' Error"), tr("The credentials could not be verified.\nYou may wish to try re-authenticating.") ); + emit twitterAuthed( false ); + return; + } + + QVariantHash credentials = m_account->credentials(); + credentials[ "username" ] = user.screenName(); + m_account->setCredentials( credentials ); + + QVariantHash configuration = m_account->configuration(); + configuration[ "sipcachedfriendssinceid" ] = 0; + configuration[ "sipcachedmentionssinceid" ] = 0; + m_account->setConfiguration( configuration ); + + ui->twitterStatusLabel->setText( tr( "Status: Credentials saved for %1" ).arg( user.screenName() ) ); + ui->twitterAuthenticateButton->setText( tr( "De-authenticate" ) ); + ui->twitterSyncGroupBox->setVisible( true ); + ui->twitterTweetComboBox->setCurrentIndex( 0 ); + ui->twitterUserTweetLineEdit->setVisible( false ); + ui->twitterTweetGotTomahawkButton->setText( tr( "Tweet!" ) ); + + emit twitterAuthed( true ); + emit sizeHintChanged(); +} + +void +TwitterConfigWidget::authenticateVerifyError( QTweetNetBase::ErrorCode code, const QString &errorMsg ) +{ + qDebug() << Q_FUNC_INFO; + qDebug() << "Error validating credentials, error code is " << code << ", error message is " << errorMsg; + ui->twitterStatusLabel->setText(tr("Status: Error validating credentials")); + emit twitterAuthed( false ); + return; +} + +void +TwitterConfigWidget::deauthenticateTwitter() +{ + qDebug() << Q_FUNC_INFO; + QVariantHash credentials = m_account->credentials(); + credentials[ "oauthtoken" ] = QString(); + credentials[ "oauthtokensecret" ] = QString(); + credentials[ "username" ] = QString(); + m_account->setCredentials( credentials ); + + ui->twitterStatusLabel->setText(tr("Status: No saved credentials")); + ui->twitterAuthenticateButton->setText( tr( "Authenticate" ) ); + ui->twitterSyncGroupBox->setVisible( false ); + + emit twitterAuthed( false ); + emit sizeHintChanged(); +} + +void +TwitterConfigWidget::tweetComboBoxIndexChanged( int index ) +{ + Q_UNUSED( index ); + if ( ui->twitterTweetComboBox->currentText() == tr( "Global Tweet" ) ) //FIXME: use data! + ui->twitterUserTweetLineEdit->setVisible( false ); + else + ui->twitterUserTweetLineEdit->setVisible( true ); + + if ( ui->twitterTweetComboBox->currentText() == tr( "Direct Message" ) ) //FIXME: use data! + ui->twitterTweetGotTomahawkButton->setText( tr( "Send Message!" ) ); + else if ( ui->twitterTweetComboBox->currentText() == tr( "@Mention" ) ) + ui->twitterTweetGotTomahawkButton->setText( tr( "Send Mention!" ) ); + else + ui->twitterTweetGotTomahawkButton->setText( tr( "Tweet!" ) ); +} + +void +TwitterConfigWidget::startPostGotTomahawkStatus() +{ + qDebug() << Q_FUNC_INFO; + m_postGTtype = ui->twitterTweetComboBox->currentText(); + + if ( m_postGTtype != "Global Tweet" && ( ui->twitterUserTweetLineEdit->text().isEmpty() || ui->twitterUserTweetLineEdit->text() == "@" ) ) + { + QMessageBox::critical( this, tr("Tweetin' Error"), tr("You must enter a user name for this type of tweet.") ); + return; + } + + qDebug() << "Posting Got Tomahawk status"; + QVariantHash credentials = m_account->credentials(); + + if ( credentials[ "oauthtoken" ].toString().isEmpty() || + credentials[ "oauthtokensecret" ].toString().isEmpty() || + credentials[ "username" ].toString().isEmpty() ) + { + QMessageBox::critical( this, tr("Tweetin' Error"), tr("Your saved credentials could not be loaded.\nYou may wish to try re-authenticating.") ); + emit twitterAuthed( false ); + return; + } + TomahawkOAuthTwitter *twitAuth = new TomahawkOAuthTwitter( TomahawkUtils::nam(), this ); + twitAuth->setOAuthToken( credentials[ "oauthtoken" ].toString().toLatin1() ); + twitAuth->setOAuthTokenSecret( credentials[ "oauthtokensecret" ].toString().toLatin1() ); + QTweetAccountVerifyCredentials *credVerifier = new QTweetAccountVerifyCredentials( twitAuth, this ); + connect( credVerifier, SIGNAL( parsedUser(const QTweetUser &) ), SLOT( postGotTomahawkStatusAuthVerifyReply(const QTweetUser &) ) ); + credVerifier->verify(); +} + +void +TwitterConfigWidget::postGotTomahawkStatusAuthVerifyReply( const QTweetUser &user ) +{ + qDebug() << Q_FUNC_INFO; + if ( user.id() == 0 ) + { + QMessageBox::critical( this, tr("Tweetin' Error"), tr("Your saved credentials could not be verified.\nYou may wish to try re-authenticating.") ); + emit twitterAuthed( false ); + return; + } + TomahawkOAuthTwitter *twitAuth = new TomahawkOAuthTwitter( TomahawkUtils::nam(), this ); + QVariantHash credentials = m_account->credentials(); + twitAuth->setOAuthToken( credentials[ "oauthtoken" ].toString().toLatin1() ); + twitAuth->setOAuthTokenSecret( credentials[ "oauthtokensecret" ].toString().toLatin1() ); + if ( m_postGTtype != "Direct Message" ) + { + QTweetStatusUpdate *statUpdate = new QTweetStatusUpdate( twitAuth, this ); + connect( statUpdate, SIGNAL( postedStatus(const QTweetStatus &) ), SLOT( postGotTomahawkStatusUpdateReply(const QTweetStatus &) ) ); + connect( statUpdate, SIGNAL( error(QTweetNetBase::ErrorCode, const QString&) ), SLOT( postGotTomahawkStatusUpdateError(QTweetNetBase::ErrorCode, const QString &) ) ); + QString uuid = QUuid::createUuid(); + QString message = QString( "Got Tomahawk? {" ) + Database::instance()->dbid() + QString( "} (" ) + uuid.mid( 1, 8 ) + QString( ")" ) + QString( " http://gettomahawk.com" ); + if ( m_postGTtype == "@Mention" ) + { + QString user = ui->twitterUserTweetLineEdit->text(); + if ( user.startsWith( "@" ) ) + user.remove( 0, 1 ); + message = QString( "@" ) + user + QString( " " ) + message; + } + statUpdate->post( message ); + } + else + { + QTweetDirectMessageNew *statUpdate = new QTweetDirectMessageNew( twitAuth, this ); + connect( statUpdate, SIGNAL( parsedDirectMessage(const QTweetDMStatus &)), SLOT( postGotTomahawkDirectMessageReply(const QTweetDMStatus &) ) ); + connect( statUpdate, SIGNAL( error(QTweetNetBase::ErrorCode, const QString&) ), SLOT( postGotTomahawkStatusUpdateError(QTweetNetBase::ErrorCode, const QString &) ) ); + QString uuid = QUuid::createUuid(); + QString message = QString( "Got Tomahawk? {" ) + Database::instance()->dbid() + QString( "} (" ) + uuid.mid( 1, 8 ) + QString( ")" ) + QString( " http://gettomahawk.com" ); + QString user = ui->twitterUserTweetLineEdit->text(); + if ( user.startsWith( "@" ) ) + user.remove( 0, 1 ); + statUpdate->post( user, message ); + } +} + +void +TwitterConfigWidget::postGotTomahawkStatusUpdateReply( const QTweetStatus& status ) +{ + if ( status.id() == 0 ) + QMessageBox::critical( this, tr("Tweetin' Error"), tr("There was an error posting your status -- sorry!") ); + else + QMessageBox::information( this, tr("Tweeted!"), tr("Your tweet has been posted!") ); +} + +void +TwitterConfigWidget::postGotTomahawkDirectMessageReply( const QTweetDMStatus& status ) +{ + if ( status.id() == 0 ) + QMessageBox::critical( this, tr("Tweetin' Error"), tr("There was an error posting your direct message -- sorry!") ); + else + QMessageBox::information( this, tr("Tweeted!"), tr("Your message has been posted!") ); +} + +void +TwitterConfigWidget::postGotTomahawkStatusUpdateError( QTweetNetBase::ErrorCode code, const QString& errorMsg ) +{ + qDebug() << Q_FUNC_INFO; + qDebug() << "Error posting Got Tomahawk message, error code is " << code << ", error message is " << errorMsg; + QMessageBox::critical( this, tr("Tweetin' Error"), tr("There was an error posting your status -- sorry!") ); +} + +} + +} \ No newline at end of file diff --git a/src/accounts/twitter/twitterconfigwidget.h b/src/accounts/twitter/twitterconfigwidget.h new file mode 100644 index 000000000..df0b60748 --- /dev/null +++ b/src/accounts/twitter/twitterconfigwidget.h @@ -0,0 +1,84 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Christian Muehlhaeuser + * + * 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 TWITTERACCOUNTCONFIGWIDGET_H +#define TWITTERACCOUNTCONFIGWIDGET_H + +#include "dllmacro.h" + +#include +#include +#include +#include + +#include + +class TwitterAccount; + +namespace Ui +{ + class TwitterConfigWidget; +} + +namespace Tomahawk +{ + +namespace Accounts +{ + +class TwitterAccount; + + +class DLLEXPORT TwitterConfigWidget : public QWidget +{ + Q_OBJECT + +public: + explicit TwitterConfigWidget( TwitterAccount* account = 0, QWidget *parent = 0 ); + virtual ~TwitterConfigWidget(); + +signals: + void twitterAuthed( bool authed ); + + void sizeHintChanged(); + +private slots: + void authDeauthTwitter(); + void startPostGotTomahawkStatus(); + void authenticateVerifyReply( const QTweetUser &user ); + void authenticateVerifyError( QTweetNetBase::ErrorCode code, const QString &errorMsg ); + void postGotTomahawkStatusAuthVerifyReply( const QTweetUser &user ); + void postGotTomahawkStatusUpdateReply( const QTweetStatus &status ); + void postGotTomahawkDirectMessageReply( const QTweetDMStatus &status ); + void postGotTomahawkStatusUpdateError( QTweetNetBase::ErrorCode, const QString &errorMsg ); + void tweetComboBoxIndexChanged( int index ); + +private: + void authenticateTwitter(); + void deauthenticateTwitter(); + + Ui::TwitterConfigWidget *ui; + TwitterAccount *m_account; + QString m_postGTtype; +}; + +} + +} + +#endif // TWITTERCONFIGWIDGET_H diff --git a/src/accounts/twitter/twitterconfigwidget.ui b/src/accounts/twitter/twitterconfigwidget.ui new file mode 100644 index 000000000..f60dbb5f8 --- /dev/null +++ b/src/accounts/twitter/twitterconfigwidget.ui @@ -0,0 +1,381 @@ + + + TwitterConfigWidget + + + + 0 + 0 + 580 + 390 + + + + + 0 + 0 + + + + + 580 + 390 + + + + + + + + + Qt::Horizontal + + + + 40 + 0 + + + + + + + + + 0 + 0 + + + + + + + :/twitter-icon.png + + + + + + + + 0 + 0 + + + + + 11 + 75 + true + + + + Configure this Twitter account + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 40 + 0 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + 0 + 0 + + + + The Twitter plugin allows you to discover and play music from your Twitter friends running Tomahawk and post messages to your account. + + + true + + + + + + + + + + 0 + 0 + + + + Status: No saved credentials + + + Qt::AutoText + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Authenticate with Twitter + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + Twitter Connections + + + + + + +If you only want to post tweets, you're done. + +If you want to connect Tomahawk to your friends using Twitter, select the type of tweet and press the button below to send a sync message. You must both be following each other as Direct Messages are used. Then be (very) patient -- it can take several minutes! + +You can re-send a sync message at any time simply by sending another tweet using the button. + + + true + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 40 + + + + + + + + QLayout::SetFixedSize + + + + + + 0 + 0 + + + + Select the kind of tweet you would like, then press the button to post it: + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 10 + + + + + + + + + + + 0 + 0 + + + + + Global Tweet + + + + + @Mention + + + + + Direct Message + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + + 0 + 0 + + + + + 250 + 0 + + + + e.g. @tomahawk + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 10 + 20 + + + + + + + + + 0 + 0 + + + + Send Message + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + + diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index 8e3a940d7..e9ed1083b 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -253,6 +253,7 @@ set( libHeaders album.h playlist.h + accounts/account.h accounts/accountmanager.h sip/SipPlugin.h diff --git a/src/libtomahawk/accounts/account.h b/src/libtomahawk/accounts/account.h index f6349e72b..8b2d680df 100644 --- a/src/libtomahawk/accounts/account.h +++ b/src/libtomahawk/accounts/account.h @@ -29,7 +29,7 @@ #include "dllmacro.h" #include "infosystem/infosystem.h" #include "sip/SipPlugin.h" -#include +#include "tomahawksettings.h" namespace Tomahawk { @@ -37,54 +37,128 @@ namespace Tomahawk namespace Accounts { -typedef QMap< QString, bool > ACLMap; - enum AccountType { InfoType, SipType }; +inline QString generateId( const QString &factoryId ) +{ + QString uniq = QUuid::createUuid().toString().mid( 1, 8 ); + return factoryId + "_" + uniq; +} + class DLLEXPORT Account : public QObject { - Q_OBJECT public: - explicit Account() + explicit Account( const QString &accountId ) : QObject() + , m_autoConnect( false ) + , m_accountId( accountId ) {} + virtual ~Account() {} + + virtual QString accountServiceName() const { return m_accountServiceName; } // e.g. "Twitter", "Last.fm" + virtual QString accountFriendlyName() const { return m_accountFriendlyName; } // e.g. screen name on the service, JID, etc. + virtual bool autoConnect() const { return m_autoConnect; } + virtual QString accountId() const { return m_accountId; } + + virtual QVariantHash configuration() const { return m_configuration; } + virtual QWidget* configurationWidget() = 0; + + virtual QVariantHash credentials() { return m_credentials; } + + virtual QVariantMap acl() const { return m_acl; } + virtual QWidget* aclWidget() = 0; + + virtual QIcon icon() const = 0; + + virtual bool authenticate() = 0; //if none needed, just return true + virtual bool isAuthenticated() = 0; + + virtual Tomahawk::InfoSystem::InfoPlugin* infoPlugin() = 0; + virtual SipPlugin* sipPlugin() = 0; + + virtual QSet< AccountType > types() const + { + QSet< AccountType > set; + foreach ( QString type, m_types ) { - m_autoConnect = false; + if ( type == "InfoType" ) + set << InfoType; + else if ( type == "SipType" ) + set << SipType; } - virtual ~Account(); + return set; + } - QString accountServiceName() const; // e.g. "Twitter", "Last.fm" - void setAccountServiceName( const QString &serviceName ); +signals: + void configurationChanged(); - QString accountFriendlyName() const; // e.g. screen name on the service, JID, etc. - void setAccountFriendlyName( const QString &friendlyName ); +protected: + virtual void setAccountServiceName( const QString &serviceName ) { m_accountServiceName = serviceName; } + virtual void setAccountFriendlyName( const QString &friendlyName ) { m_accountFriendlyName = friendlyName; } + virtual void setAutoConnect( bool autoConnect ) { m_autoConnect = autoConnect; } + virtual void setAccountId( const QString &accountId ) { m_accountId = accountId; } + virtual void setCredentials( const QVariantHash &credentialHash ) { m_credentials = credentialHash; } + + virtual void setConfiguration( const QVariantHash &configuration ) { m_configuration = configuration; } + + virtual void setAcl( const QVariantMap &acl ) { m_acl = acl; } - bool autoConnect() const { return m_autoConnect; } - void setAutoConnect( bool autoConnect ) { m_autoConnect = autoConnect; } + virtual void setTypes( const QSet< AccountType > types ) + { + m_types = QStringList(); + foreach ( AccountType type, types ) + { + switch( type ) + { + case InfoType: + m_types << "InfoType"; + case SipType: + m_types << "SipType"; + } + } + syncConfig(); + } + + virtual void loadFromConfig( const QString &accountId ) + { + m_accountId = accountId; + TomahawkSettings* s = TomahawkSettings::instance(); + s->beginGroup( "accounts/" + m_accountId ); + m_accountFriendlyName = s->value( "accountFriendlyName", QString() ).toString(); + m_autoConnect = s->value( "autoConnect", false ).toBool(); + m_credentials = s->value( "credentials", QVariantHash() ).toHash(); + m_configuration = s->value( "configuration", QVariantHash() ).toHash(); + m_acl = s->value( "acl", QVariantMap() ).toMap(); + m_types = s->value( "types", QStringList() ).toStringList(); + s->endGroup(); + s->sync(); + } - QHash< QString, QString > credentials() { return m_credentials; } - void setCredentials( const QHash< QString, QString > &credentialMap ); + virtual void syncConfig() + { + TomahawkSettings* s = TomahawkSettings::instance(); + s->beginGroup( "accounts/" + m_accountId ); + s->setValue( "accountFriendlyName", m_accountFriendlyName ); + s->setValue( "autoConnect", m_autoConnect ); + s->setValue( "credentials", m_credentials ); + s->setValue( "configuration", m_configuration ); + s->setValue( "acl", m_acl ); + s->setValue( "types", m_types ); + s->endGroup(); + s->sync(); - QIcon icon() const; + emit configurationChanged(); + } - QVariantMap configuration() const; - void setConfiguration( const QVariantMap &configuration ); - QWidget* configurationWidget(); - - ACLMap acl() const; - void setAcl( const ACLMap &acl ); - QWidget* aclWidget(); - - QSet< AccountType > types() const; - void setTypes( const QSet< AccountType > types ); - - Tomahawk::InfoSystem::InfoPlugin* infoPlugin(); - SipPlugin* sipPlugin(); - -private: + QString m_accountServiceName; + QString m_accountFriendlyName; bool m_autoConnect; - QHash< QString, QString > m_credentials; + QString m_accountId; + QVariantHash m_credentials; + QVariantHash m_configuration; + QVariantMap m_acl; + QStringList m_types; }; class DLLEXPORT AccountFactory : public QObject @@ -103,13 +177,6 @@ public: virtual bool isUnique() const { return false; } virtual Account* createAccount( const QString& pluginId = QString() ) = 0; - -protected: - QString generateId() - { - QString uniq = QUuid::createUuid().toString().mid( 1, 8 ); - return factoryId() + "_" + uniq; - } }; }; diff --git a/src/libtomahawk/accounts/accountmanager.cpp b/src/libtomahawk/accounts/accountmanager.cpp index 90e60bd04..385403908 100644 --- a/src/libtomahawk/accounts/accountmanager.cpp +++ b/src/libtomahawk/accounts/accountmanager.cpp @@ -31,9 +31,20 @@ namespace Accounts { -AccountManager::AccountManager() - : QObject() +AccountManager* AccountManager::s_instance = 0; + + +AccountManager* +AccountManager::instance() { + return s_instance; +} + + +AccountManager::AccountManager( QObject *parent ) + : QObject( parent ) +{ + s_instance = this; loadPluginFactories( findPluginFactories() ); } @@ -70,7 +81,7 @@ AccountManager::findPluginFactories() pluginDirs << appDir << libDir << lib64Dir << QDir( qApp->applicationDirPath() ); foreach ( const QDir& pluginDir, pluginDirs ) { - qDebug() << "Checking directory for plugins:" << pluginDir; + 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" ) ) @@ -94,7 +105,7 @@ AccountManager::loadPluginFactories( const QStringList& paths ) if ( !QLibrary::isLibrary( fileName ) ) continue; - qDebug() << "Trying to load plugin:" << fileName; + tDebug() << Q_FUNC_INFO << "Trying to load plugin:" << fileName; loadPluginFactory( fileName ); } } @@ -114,17 +125,17 @@ AccountManager::loadPluginFactory( const QString& path ) QObject* plugin = loader.instance(); if ( !plugin ) { - qDebug() << "Error loading plugin:" << loader.errorString(); + tDebug() << Q_FUNC_INFO << "Error loading plugin:" << loader.errorString(); } AccountFactory* accountfactory = qobject_cast( plugin ); if ( accountfactory ) { - qDebug() << "Loaded plugin factory:" << loader.fileName() << accountfactory->factoryId() << accountfactory->prettyName(); + tDebug() << Q_FUNC_INFO << "Loaded plugin factory:" << loader.fileName() << accountfactory->factoryId() << accountfactory->prettyName(); m_accountFactories[ accountfactory->factoryId() ] = accountfactory; } else { - qDebug() << "Loaded invalid plugin.." << loader.fileName(); + tDebug() << Q_FUNC_INFO << "Loaded invalid plugin.." << loader.fileName(); } } @@ -162,9 +173,11 @@ AccountManager::loadPlugin( const QString& pluginId ) void AccountManager::addAccountPlugin( Account* account ) { - m_accounts << account; + m_accounts.append( account ); - //FIXME: + foreach( AccountType type, account->types() ) + m_accountsByAccountType[ type ].append( account ); + //TODO: //emit pluginAdded( account ); } diff --git a/src/libtomahawk/accounts/accountmanager.h b/src/libtomahawk/accounts/accountmanager.h index 640dae794..9cb4d5ee7 100644 --- a/src/libtomahawk/accounts/accountmanager.h +++ b/src/libtomahawk/accounts/accountmanager.h @@ -38,7 +38,9 @@ class DLLEXPORT AccountManager : public QObject Q_OBJECT public: - explicit AccountManager(); + static AccountManager* instance(); + + explicit AccountManager( QObject *parent ); virtual ~AccountManager(); QStringList findPluginFactories(); @@ -50,12 +52,15 @@ public: Account* loadPlugin( const QString &pluginId ); QString factoryFromId( const QString& pluginId ) const; - //QSet< Account > getAccounts( Tomahawk::Accounts::AccountType type ); + QList< Account* > getAccounts() { return m_accounts; }; + QList< Account* > getAccounts( Tomahawk::Accounts::AccountType type ) { return m_accountsByAccountType[ type ]; } private: - QSet< Account* > m_accounts; + QList< Account* > m_accounts; + QHash< AccountType, QList< Account* > > m_accountsByAccountType; QHash< QString, AccountFactory* > m_accountFactories; - + + static AccountManager* s_instance; }; }; diff --git a/src/sip/twitter/twittersip.cpp b/src/sip/twitter/twittersip.cpp index 8d77d34dd..c349bf62c 100644 --- a/src/sip/twitter/twittersip.cpp +++ b/src/sip/twitter/twittersip.cpp @@ -86,9 +86,6 @@ TwitterPlugin::TwitterPlugin( const QString& pluginId ) m_connectTimer.setInterval( 180000 ); m_connectTimer.setSingleShot( false ); connect( &m_connectTimer, SIGNAL( timeout() ), SLOT( connectTimerFired() ) ); - - m_configWidget = QWeakPointer< TwitterConfigWidget >( new TwitterConfigWidget( this, 0 ) ); - connect( m_configWidget.data(), SIGNAL( twitterAuthed( bool ) ), SLOT( configDialogAuthedSignalSlot( bool ) ) ); } diff --git a/src/tomahawkapp.cpp b/src/tomahawkapp.cpp index 83ac51699..60f535ad4 100644 --- a/src/tomahawkapp.cpp +++ b/src/tomahawkapp.cpp @@ -35,6 +35,7 @@ #include "album.h" #include "collection.h" #include "infosystem/infosystem.h" +#include "accounts/accountmanager.h" #include "database/database.h" #include "database/databasecollection.h" #include "database/databasecommand_collectionstats.h" @@ -212,6 +213,10 @@ TomahawkApp::init() connect( m_shortcutHandler.data(), SIGNAL( mute() ), m_audioEngine.data(), SLOT( mute() ) ); } + tDebug() << "Init AccountManager."; + m_accountManager = QWeakPointer< Tomahawk::Accounts::AccountManager >( new Tomahawk::Accounts::AccountManager( this ) ); + Tomahawk::Accounts::AccountManager::instance()->loadFromConfig(); + tDebug() << "Init InfoSystem."; m_infoSystem = QWeakPointer( new Tomahawk::InfoSystem::InfoSystem( this ) ); @@ -499,6 +504,12 @@ TomahawkApp::initServent() void TomahawkApp::initSIP() { + foreach ( Tomahawk::Accounts::Account* account, Tomahawk::Accounts::AccountManager::instance()->getAccounts() ) + { + if ( account->configurationWidget() ) + account->configurationWidget()->show(); + } + //FIXME: jabber autoconnect is really more, now that there is sip -- should be renamed and/or split out of jabber-specific settings if ( !arguments().contains( "--nosip" ) ) { diff --git a/src/tomahawkapp.h b/src/tomahawkapp.h index 0b3a0b1a8..528127825 100644 --- a/src/tomahawkapp.h +++ b/src/tomahawkapp.h @@ -53,6 +53,11 @@ namespace Tomahawk { class InfoSystem; } + + namespace Accounts + { + class AccountManager; + } } #ifdef LIBLASTFM_FOUND @@ -119,6 +124,7 @@ private: QWeakPointer m_infoSystem; QWeakPointer m_xmppBot; QWeakPointer m_shortcutHandler; + QWeakPointer< Tomahawk::Accounts::AccountManager > m_accountManager; bool m_scrubFriendlyName; #ifdef LIBLASTFM_FOUND @@ -139,3 +145,7 @@ Q_DECLARE_METATYPE( QPersistentModelIndex ); #endif // TOMAHAWKAPP_H + +struct A; + +struct A;