1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-09-07 04:30:43 +02:00

Compare commits

...

1 Commits

Author SHA1 Message Date
Jeff Mitchell
c950ae0b2e Reformat code. Incantation was 'astyle --style=allman -S -xG -Y -k1 -j -c -p -D -j' 2014-04-04 12:02:47 -04:00
877 changed files with 20376 additions and 11071 deletions

View File

@@ -67,7 +67,9 @@ GoogleWrapperSip::showAddFriendDialog()
QString id = QInputDialog::getText( TomahawkUtils::tomahawkWindow(), tr( "Add Friend" ),
tr( "Enter Google Address:" ), QLineEdit::Normal, "", &ok );
if ( !ok )
{
return;
}
qDebug() << "Attempting to add google contact to roster:" << id;
addContact( id, SendInvite );
@@ -111,7 +113,9 @@ GoogleWrapper::sipPlugin( bool create )
if ( m_xmppSipPlugin.isNull() )
{
if ( !create )
{
return 0;
}
m_xmppSipPlugin = QPointer< XmppSipPlugin >( new GoogleWrapperSip( const_cast< GoogleWrapper* >( this ) ) );

View File

@@ -35,13 +35,22 @@ class ACCOUNTDLLEXPORT GoogleWrapperFactory : public XmppAccountFactory
Q_INTERFACES( Tomahawk::Accounts::AccountFactory )
Q_PLUGIN_METADATA( IID "org.tomahawk-player.Player.AccountFactory" )
public:
public:
GoogleWrapperFactory() {}
virtual ~GoogleWrapperFactory() {}
virtual QString prettyName() const { return "Google"; }
virtual QString factoryId() const { return "googleaccount"; }
QString description() const { return tr( "Connect to Google Talk to find your friends" ); }
virtual QString prettyName() const
{
return "Google";
}
virtual QString factoryId() const
{
return "googleaccount";
}
QString description() const
{
return tr( "Connect to Google Talk to find your friends" );
}
virtual QPixmap icon() const;
virtual Account* createAccount( const QString& pluginId );
};
@@ -49,32 +58,38 @@ public:
class ACCOUNTDLLEXPORT GoogleWrapperSip : public XmppSipPlugin
{
Q_OBJECT
public:
public:
GoogleWrapperSip( Tomahawk::Accounts::Account* account );
virtual ~GoogleWrapperSip();
virtual QString inviteString() const;
public slots:
public slots:
void showAddFriendDialog();
protected:
protected:
QString defaultSuffix() const;
};
class ACCOUNTDLLEXPORT GoogleWrapper : public XmppAccount
{
Q_OBJECT
public:
public:
GoogleWrapper( const QString& pluginID );
virtual ~GoogleWrapper();
virtual const QString name() const { return QString( "Google" ); }
virtual const QString friendlyName() const { return "Google"; }
virtual const QString name() const
{
return QString( "Google" );
}
virtual const QString friendlyName() const
{
return "Google";
}
virtual SipPlugin* sipPlugin( bool create = true );
private:
private:
QPointer< GoogleWrapperSip > m_sipPlugin;
};

View File

@@ -43,14 +43,16 @@ using namespace Accounts;
static QPixmap* s_icon = 0;
HatchetAccount* HatchetAccount::s_instance = 0;
const QString c_loginServer("https://auth.hatchet.is/v1");
const QString c_accessTokenServer("https://auth.hatchet.is/v1");
const QString c_loginServer( "https://auth.hatchet.is/v1" );
const QString c_accessTokenServer( "https://auth.hatchet.is/v1" );
HatchetAccountFactory::HatchetAccountFactory()
{
#ifndef ENABLE_HEADLESS
if ( s_icon == 0 )
{
s_icon = new QPixmap( ":/hatchet-account/hatchet-icon-512x512.png" );
}
#endif
}
@@ -86,21 +88,21 @@ HatchetAccount::HatchetAccount( const QString& accountId )
setAccountServiceName( "Hatchet" );
// We're connecting peers.
setTypes( SipType );
/*
QFile pemFile( ":/hatchet-account/mandella.pem" );
pemFile.open( QIODevice::ReadOnly );
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "certs/mandella.pem: " << pemFile.readAll();
pemFile.close();
pemFile.open( QIODevice::ReadOnly );
QCA::ConvertResult conversionResult;
QCA::PublicKey publicKey = QCA::PublicKey::fromPEM(pemFile.readAll(), &conversionResult);
if ( QCA::ConvertGood != conversionResult )
{
tLog() << Q_FUNC_INFO << "INVALID PUBKEY READ";
return;
}
m_publicKey = new QCA::PublicKey( publicKey );
*/
/*
QFile pemFile( ":/hatchet-account/mandella.pem" );
pemFile.open( QIODevice::ReadOnly );
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "certs/mandella.pem: " << pemFile.readAll();
pemFile.close();
pemFile.open( QIODevice::ReadOnly );
QCA::ConvertResult conversionResult;
QCA::PublicKey publicKey = QCA::PublicKey::fromPEM(pemFile.readAll(), &conversionResult);
if ( QCA::ConvertGood != conversionResult )
{
tLog() << Q_FUNC_INFO << "INVALID PUBKEY READ";
return;
}
m_publicKey = new QCA::PublicKey( publicKey );
*/
}
@@ -121,7 +123,9 @@ AccountConfigWidget*
HatchetAccount::configurationWidget()
{
if ( m_configWidget.isNull() )
{
m_configWidget = QPointer<HatchetAccountConfig>( new HatchetAccountConfig( this ) );
}
return m_configWidget.data();
}
@@ -131,13 +135,17 @@ void
HatchetAccount::authenticate()
{
if ( connectionState() == Connected )
{
return;
}
if ( !refreshToken().isEmpty() )
{
qDebug() << "Have saved credentials with refresh token:" << refreshToken();
if ( sipPlugin() )
{
sipPlugin()->connectPlugin();
}
setAccountFriendlyName( username() );
}
else if ( !username().isEmpty() )
@@ -152,7 +160,9 @@ void
HatchetAccount::deauthenticate()
{
if ( !m_tomahawkSipPlugin.isNull() )
{
m_tomahawkSipPlugin->disconnectPlugin();
}
emit deauthenticated();
}
@@ -179,7 +189,9 @@ HatchetAccount::sipPlugin( bool create )
if ( m_tomahawkSipPlugin.isNull() )
{
if ( !create )
{
return 0;
}
tLog() << Q_FUNC_INFO;
m_tomahawkSipPlugin = QPointer< HatchetSipPlugin >( new HatchetSipPlugin( this ) );
@@ -249,7 +261,7 @@ HatchetAccount::mandellaTokenType() const
void
HatchetAccount::loginWithPassword( const QString& username, const QString& password, const QString &otp )
HatchetAccount::loginWithPassword( const QString& username, const QString& password, const QString& otp )
{
//if ( username.isEmpty() || password.isEmpty() || !m_publicKey )
if ( username.isEmpty() || password.isEmpty() )
@@ -265,7 +277,7 @@ HatchetAccount::loginWithPassword( const QString& username, const QString& passw
params[ "nonce" ] = QString( result.toByteArray().toBase64() );
*/
QNetworkRequest req( QUrl( c_loginServer + "/authentication/password") );
QNetworkRequest req( QUrl( c_loginServer + "/authentication/password" ) );
req.setHeader( QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded" );
QUrl params;
@@ -273,7 +285,9 @@ HatchetAccount::loginWithPassword( const QString& username, const QString& passw
TomahawkUtils::urlAddQueryItem( params, "password", password );
TomahawkUtils::urlAddQueryItem( params, "grant_type", "password" );
if ( !otp.isEmpty() )
{
TomahawkUtils::urlAddQueryItem( params, "otp", otp );
}
QByteArray data = TomahawkUtils::encodedQuery( params );
@@ -292,9 +306,9 @@ HatchetAccount::fetchAccessToken( const QString& type )
return;
}
if ( mandellaAccessToken().isEmpty() ||
(mandellaAccessTokenExpiration() < QDateTime::currentDateTime().toTime_t() &&
(refreshToken().isEmpty() ||
(refreshTokenExpiration() != 0 && refreshTokenExpiration() < QDateTime::currentDateTime().toTime_t()))) )
( mandellaAccessTokenExpiration() < QDateTime::currentDateTime().toTime_t() &&
( refreshToken().isEmpty() ||
( refreshTokenExpiration() != 0 && refreshTokenExpiration() < QDateTime::currentDateTime().toTime_t() ) ) ) )
{
tLog() << "No valid combination of access/refresh tokens, not logging in";
tLog() << "Mandella access token expiration:" << mandellaAccessTokenExpiration() << ", refresh token expiration:" << refreshTokenExpiration();
@@ -315,7 +329,7 @@ HatchetAccount::fetchAccessToken( const QString& type )
tLog() << "Fetching access tokens of type" << type;
}
QNetworkRequest req( QUrl( c_accessTokenServer + "/tokens/" + (interceptionNeeded ? "refresh/" + QString::fromUtf8(mandellaTokenType()).toLower() : "fetch/" + type) ) );
QNetworkRequest req( QUrl( c_accessTokenServer + "/tokens/" + ( interceptionNeeded ? "refresh/" + QString::fromUtf8( mandellaTokenType() ).toLower() : "fetch/" + type ) ) );
QNetworkReply* reply;
if ( interceptionNeeded )
@@ -332,9 +346,9 @@ HatchetAccount::fetchAccessToken( const QString& type )
else
{
tLog() << "Fetching token of type" << type;
req.setRawHeader( "Authorization", QString( mandellaTokenType() + " " + mandellaAccessToken()).toUtf8() );
req.setRawHeader( "Authorization", QString( mandellaTokenType() + " " + mandellaAccessToken() ).toUtf8() );
reply = Tomahawk::Utils::nam()->get( req );
}
}
NewClosure( reply, SIGNAL( finished() ), this, SLOT( onFetchAccessTokenFinished( QNetworkReply*, const QString& ) ), reply, type );
}
@@ -419,7 +433,9 @@ HatchetAccount::onPasswordLoginFinished( QNetworkReply* reply, const QString& us
syncConfig();
if ( sipPlugin() )
{
sipPlugin()->connectPlugin();
}
}

View File

@@ -42,16 +42,31 @@ class ACCOUNTDLLEXPORT HatchetAccountFactory : public AccountFactory
Q_INTERFACES( Tomahawk::Accounts::AccountFactory )
Q_PLUGIN_METADATA( IID "org.tomahawk-player.Player.AccountFactory" )
public:
public:
HatchetAccountFactory();
virtual ~HatchetAccountFactory();
virtual QString factoryId() const { return "hatchetaccount"; }
virtual QString prettyName() const { return "Hatchet"; }
virtual QString description() const { return tr( "Connect to your Hatchet account" ); }
virtual bool isUnique() const { return true; }
AccountTypes types() const { return AccountTypes( SipType ); }
// virtual bool allowUserCreation() const { return false; }
virtual QString factoryId() const
{
return "hatchetaccount";
}
virtual QString prettyName() const
{
return "Hatchet";
}
virtual QString description() const
{
return tr( "Connect to your Hatchet account" );
}
virtual bool isUnique() const
{
return true;
}
AccountTypes types() const
{
return AccountTypes( SipType );
}
// virtual bool allowUserCreation() const { return false; }
virtual QPixmap icon() const;
virtual Account* createAccount ( const QString& pluginId = QString() );
@@ -60,12 +75,13 @@ public:
class ACCOUNTDLLEXPORT HatchetAccount : public Account
{
Q_OBJECT
public:
enum Service {
public:
enum Service
{
Facebook = 0
};
HatchetAccount( const QString &accountId );
HatchetAccount( const QString& accountId );
virtual ~HatchetAccount();
static HatchetAccount* instance();
@@ -79,26 +95,32 @@ public:
void setConnectionState( Account::ConnectionState connectionState );
ConnectionState connectionState() const;
virtual Tomahawk::InfoSystem::InfoPluginPtr infoPlugin() { return Tomahawk::InfoSystem::InfoPluginPtr(); }
virtual Tomahawk::InfoSystem::InfoPluginPtr infoPlugin()
{
return Tomahawk::InfoSystem::InfoPluginPtr();
}
SipPlugin* sipPlugin( bool create = true );
AccountConfigWidget* configurationWidget();
QWidget* aclWidget() { return 0; }
QWidget* aclWidget()
{
return 0;
}
QString username() const;
void fetchAccessToken( const QString& type = "dreamcatcher" );
signals:
signals:
void authError( QString error, int statusCode, const QVariantMap );
void deauthenticated();
void accessTokenFetched();
private slots:
private slots:
void onPasswordLoginFinished( QNetworkReply*, const QString& username );
void onFetchAccessTokenFinished( QNetworkReply*, const QString& type );
private:
private:
QByteArray refreshToken() const;
uint refreshTokenExpiration() const;
@@ -107,7 +129,7 @@ private:
QByteArray mandellaTokenType() const;
void loginWithPassword( const QString& username, const QString& password, const QString &otp );
void loginWithPassword( const QString& username, const QString& password, const QString& otp );
QVariantMap parseReply( QNetworkReply* reply, bool& ok ) const;

View File

@@ -28,12 +28,14 @@
using namespace Tomahawk;
using namespace Accounts;
namespace {
enum ButtonAction {
Login,
Register,
Logout
};
namespace
{
enum ButtonAction
{
Login,
Register,
Logout
};
}
HatchetAccountConfig::HatchetAccountConfig( HatchetAccount* account )
@@ -59,7 +61,9 @@ HatchetAccountConfig::HatchetAccountConfig( HatchetAccount* account )
connect( m_account, SIGNAL( accessTokenFetched() ), this, SLOT( accountInfoUpdated() ) );
if ( !m_account->refreshToken().isEmpty() )
{
accountInfoUpdated();
}
else
{
m_ui->usernameEdit->setText( m_account->username() );
@@ -131,7 +135,7 @@ HatchetAccountConfig::showLoggedIn()
m_ui->errorLabel->clear();
m_ui->errorLabel->hide();
m_ui->loginButton->setText( tr("Log out") );
m_ui->loginButton->setText( tr( "Log out" ) );
m_ui->loginButton->setProperty( "action", Logout );
m_ui->loginButton->setDefault( true );
}
@@ -153,7 +157,7 @@ HatchetAccountConfig::showLoggedOut()
m_ui->errorLabel->clear();
m_ui->loginButton->setText( tr("Log in") );
m_ui->loginButton->setText( tr( "Log in" ) );
m_ui->loginButton->setProperty( "action", Login );
m_ui->loginButton->setDefault( true );
}
@@ -168,7 +172,7 @@ HatchetAccountConfig::accountInfoUpdated()
void
HatchetAccountConfig::authError( const QString &error, int statusCode, const QVariantMap& resp )
HatchetAccountConfig::authError( const QString& error, int statusCode, const QVariantMap& resp )
{
if ( statusCode == 400 && error == "otp_needed" )
{
@@ -178,17 +182,19 @@ HatchetAccountConfig::authError( const QString &error, int statusCode, const QVa
m_ui->otpEdit->show();
m_ui->passwordLabel->hide();
m_ui->passwordEdit->hide();
m_ui->loginButton->setText( tr("Continue") );
m_ui->loginButton->setText( tr( "Continue" ) );
return;
}
if ( statusCode == 401 )
{
m_account->deauthenticate();
}
QMessageBox::critical( this, "An error was encountered:", error );
}
void
HatchetAccountConfig::showEvent( QShowEvent *event )
HatchetAccountConfig::showEvent( QShowEvent* event )
{
AccountConfigWidget::showEvent( event );
m_ui->loginButton->setDefault( true );

View File

@@ -26,23 +26,26 @@
class QNetworkReply;
namespace Ui {
class HatchetAccountConfig;
namespace Ui
{
class HatchetAccountConfig;
}
namespace Tomahawk {
namespace Accounts {
namespace Tomahawk
{
namespace Accounts
{
class HatchetAccount;
class HatchetAccountConfig : public AccountConfigWidget
{
Q_OBJECT
public:
public:
explicit HatchetAccountConfig( HatchetAccount* account );
virtual ~HatchetAccountConfig();
private slots:
private slots:
void login();
void fieldsChanged();
@@ -54,11 +57,11 @@ private slots:
void authError( const QString& error, int statusCode, const QVariantMap& resp );
protected:
protected:
//virtual void changeEvent( QEvent* event );
virtual void showEvent( QShowEvent* event );
private:
private:
Ui::HatchetAccountConfig* m_ui;
HatchetAccount* m_account;
};

View File

@@ -39,7 +39,7 @@
#include <QHostInfo>
#include <QUuid>
HatchetSipPlugin::HatchetSipPlugin( Tomahawk::Accounts::Account *account )
HatchetSipPlugin::HatchetSipPlugin( Tomahawk::Accounts::Account* account )
: SipPlugin( account )
, m_sipState( Closed )
, m_version( 0 )
@@ -49,7 +49,7 @@ HatchetSipPlugin::HatchetSipPlugin( Tomahawk::Accounts::Account *account )
tLog() << Q_FUNC_INFO;
connect( m_account, SIGNAL( accessTokenFetched() ), this, SLOT( connectWebSocket() ) );
connect( Servent::instance(), SIGNAL( dbSyncTriggered() ), this, SLOT( dbSyncTriggered() ));
connect( Servent::instance(), SIGNAL( dbSyncTriggered() ), this, SLOT( dbSyncTriggered() ) );
/*
QFile pemFile( ":/hatchet-account/dreamcatcher.pem" );
@@ -125,9 +125,13 @@ HatchetSipPlugin::disconnectPlugin()
{
tLog() << Q_FUNC_INFO;
if ( m_webSocketThreadController && m_webSocketThreadController->isRunning() )
{
emit disconnectWebSocket();
}
else
{
webSocketDisconnected();
}
}
@@ -155,8 +159,8 @@ HatchetSipPlugin::connectWebSocket()
if ( !isValid() )
{
tLog() << Q_FUNC_INFO << "Invalid state, not continuing with connection";
return;
tLog() << Q_FUNC_INFO << "Invalid state, not continuing with connection";
return;
}
m_token = m_account->credentials()[ "dreamcatcher_access_token" ].toString();
@@ -164,7 +168,7 @@ HatchetSipPlugin::connectWebSocket()
if ( m_token.isEmpty() )
{
tLog() << Q_FUNC_INFO << "Unable to find an access token";
tLog() << Q_FUNC_INFO << "Unable to find an access token";
disconnectPlugin();
return;
}
@@ -263,7 +267,7 @@ HatchetSipPlugin::sendBytes( const QVariantMap& jsonMap ) const
void
HatchetSipPlugin::messageReceived( const QByteArray &msg )
HatchetSipPlugin::messageReceived( const QByteArray& msg )
{
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "WebSocket message: " << msg;
@@ -344,7 +348,7 @@ HatchetSipPlugin::messageReceived( const QByteArray &msg )
m_sipState = Connected;
hatchetAccount()->setConnectionState( Tomahawk::Accounts::Account::Connected );
m_reconnectTimer.setInterval( 0 );
QTimer::singleShot(0, this, SLOT( dbSyncTriggered() ) );
QTimer::singleShot( 0, this, SLOT( dbSyncTriggered() ) );
return;
}
else
@@ -361,7 +365,7 @@ HatchetSipPlugin::messageReceived( const QByteArray &msg )
return;
}
else if ( !retMap.contains( "command" ) ||
!retMap[ "command" ].canConvert< QString >() )
!retMap[ "command" ].canConvert< QString >() )
{
tDebug() << Q_FUNC_INFO << "Unable to convert and/or interepret command from server";
return;
@@ -370,11 +374,17 @@ HatchetSipPlugin::messageReceived( const QByteArray &msg )
QString command = retMap[ "command" ].toString();
if ( command == "new-peer" )
{
newPeer( retMap );
}
else if ( command == "peer-authorization" )
{
peerAuthorization( retMap );
}
else if ( command == "synclastseen" )
{
sendOplog( retMap );
}
}
@@ -407,7 +417,9 @@ HatchetSipPlugin::newPeer( const QVariantMap& valMap )
QStringList keys( QStringList() << "command" << "username" << "hostinfo" << "dbid" );
if ( !checkKeys( keys, valMap ) )
{
return;
}
Tomahawk::peerinfo_ptr peerInfo = Tomahawk::PeerInfo::get( this, dbid, Tomahawk::PeerInfo::AutoCreate );
peerInfo->setContactId( username );
@@ -421,18 +433,24 @@ HatchetSipPlugin::newPeer( const QVariantMap& valMap )
foreach ( const QVariant listItem, hostinfo )
{
if ( !listItem.canConvert< QVariantMap >() )
{
continue;
}
QVariantMap hostpair = listItem.toMap();
if ( !hostpair.contains( "host" ) || !hostpair.contains( "port" ) )
{
continue;
}
const QString host = hostpair[ "host" ].toString();
unsigned int port = hostpair[ "port" ].toUInt();
if ( host.isEmpty() || port == 0 )
{
continue;
}
SipInfo sipInfo;
sipInfo.setNodeId( dbid );
@@ -449,7 +467,7 @@ HatchetSipPlugin::newPeer( const QVariantMap& valMap )
void
HatchetSipPlugin::sendSipInfos(const Tomahawk::peerinfo_ptr& receiver, const QList< SipInfo >& infos)
HatchetSipPlugin::sendSipInfos( const Tomahawk::peerinfo_ptr& receiver, const QList< SipInfo >& infos )
{
if ( infos.size() == 0 )
{
@@ -466,7 +484,9 @@ HatchetSipPlugin::sendSipInfos(const Tomahawk::peerinfo_ptr& receiver, const QLi
sendMap[ "offerkey" ] = infos[ 0 ].key();
if ( !sendBytes( sendMap ) )
{
tLog() << Q_FUNC_INFO << "Failed sending message";
}
}
@@ -477,7 +497,9 @@ HatchetSipPlugin::peerAuthorization( const QVariantMap& valMap )
QStringList keys( QStringList() << "command" << "dbid" << "offerkey" );
if ( !checkKeys( keys, valMap ) )
{
return;
}
QString dbid = valMap[ "dbid" ].toString();
@@ -489,8 +511,10 @@ HatchetSipPlugin::peerAuthorization( const QVariantMap& valMap )
}
QList< SipInfo > sipInfos = m_sipInfoHash[ dbid ];
for (int i = 0; i < sipInfos.size(); i++)
for ( int i = 0; i < sipInfos.size(); i++ )
{
sipInfos[i].setKey( valMap[ "offerkey" ].toString() );
}
peerInfo->setSipInfos( sipInfos );
m_sipInfoHash.remove( dbid );
}
@@ -502,10 +526,14 @@ void
HatchetSipPlugin::dbSyncTriggered()
{
if ( m_sipState != Connected )
{
return;
}
if ( !SourceList::instance() || SourceList::instance()->getLocal().isNull() )
{
return;
}
QVariantMap sourceMap;
sourceMap[ "command" ] = "synctrigger";
@@ -567,10 +595,14 @@ HatchetSipPlugin::oplogFetched( const QString& sinceguid, const QString& /* last
revMap[ "payload" ] = op->payload;
currBytes += op->payload.length();
}
if ( currBytes >= (int)(byteMax - 1000000) ) // tack on an extra 1M for safety as it seems qjson puts in spaces
if ( currBytes >= ( int )( byteMax - 1000000 ) ) // tack on an extra 1M for safety as it seems qjson puts in spaces
{
break;
}
else
revisions << revMap;
{
revisions << revMap;
}
}
tDebug() << Q_FUNC_INFO << "Sending" << revisions.size() << "revisions";
commandMap[ "revisions" ] = revisions;

View File

@@ -36,15 +36,16 @@ class ACCOUNTDLLEXPORT HatchetSipPlugin : public SipPlugin
{
Q_OBJECT
enum SipState {
enum SipState
{
AcquiringVersion,
Registering,
Connected,
Closed
};
public:
HatchetSipPlugin( Tomahawk::Accounts::Account *account );
public:
HatchetSipPlugin( Tomahawk::Accounts::Account* account );
virtual ~HatchetSipPlugin();
@@ -52,28 +53,31 @@ public:
virtual void sendSipInfos( const Tomahawk::peerinfo_ptr& receiver, const QList< SipInfo >& infos );
public slots:
public slots:
virtual void connectPlugin();
void disconnectPlugin();
void checkSettings() {}
void configurationChanged() {}
bool addContact( const QString&, AddContactOptions, const QString& ) { return false; }
bool addContact( const QString&, AddContactOptions, const QString& )
{
return false;
}
void sendMsg( const QString&, const SipInfo& ) {}
void webSocketConnected();
void webSocketDisconnected();
signals:
signals:
void connectWebSocket() const;
void disconnectWebSocket() const;
void rawBytes( QByteArray bytes ) const;
private slots:
private slots:
void dbSyncTriggered();
void messageReceived( const QByteArray& msg );
void connectWebSocket();
void oplogFetched( const QString& sinceguid, const QString& lastguid, const QList< dbop_ptr > ops );
private:
private:
bool sendBytes( const QVariantMap& jsonMap ) const;
bool checkKeys( QStringList keys, const QVariantMap& map ) const;
void newPeer( const QVariantMap& valMap );

View File

@@ -34,8 +34,8 @@ WebSocket::WebSocket( const QString& url, const QString& authorizationHeader )
{
tLog() << Q_FUNC_INFO << "WebSocket constructing";
m_client = std::unique_ptr< hatchet_client >( new hatchet_client() );
m_client->set_message_handler( std::bind(&onMessage, this, std::placeholders::_1, std::placeholders::_2 ) );
m_client->set_close_handler( std::bind(&onClose, this, std::placeholders::_1 ) );
m_client->set_message_handler( std::bind( &onMessage, this, std::placeholders::_1, std::placeholders::_2 ) );
m_client->set_close_handler( std::bind( &onClose, this, std::placeholders::_1 ) );
m_client->register_ostream( &m_outputStream );
m_connectionTimer.setSingleShot( true );
@@ -61,7 +61,7 @@ WebSocket::~WebSocket()
void
WebSocket::setUrl( const QString &url )
WebSocket::setUrl( const QString& url )
{
tLog() << Q_FUNC_INFO << "Setting url to" << url;
if ( m_url == url )
@@ -78,7 +78,7 @@ WebSocket::setUrl( const QString &url )
void
WebSocket::setAuthorizationHeader( const QString &authorizationHeader )
WebSocket::setAuthorizationHeader( const QString& authorizationHeader )
{
tLog() << Q_FUNC_INFO << "Setting authorization header";
if ( m_authorizationHeader == authorizationHeader )
@@ -116,7 +116,7 @@ WebSocket::connectWs()
tLog() << Q_FUNC_INFO << "Establishing new connection";
m_socket = QPointer< QSslSocket >( new QSslSocket( nullptr ) );
m_socket->addCaCertificate( QSslCertificate::fromPath( ":/hatchet-account/startcomroot.pem").first() );
m_socket->addCaCertificate( QSslCertificate::fromPath( ":/hatchet-account/startcomroot.pem" ).first() );
QObject::connect( m_socket, SIGNAL( stateChanged( QAbstractSocket::SocketState ) ), SLOT( socketStateChanged( QAbstractSocket::SocketState ) ) );
QObject::connect( m_socket, SIGNAL( sslErrors( const QList< QSslError >& ) ), SLOT( sslErrors( const QList< QSslError >& ) ) );
QObject::connect( m_socket, SIGNAL( encrypted() ), SLOT( encrypted() ) );
@@ -127,7 +127,7 @@ WebSocket::connectWs()
void
WebSocket::disconnectWs( websocketpp::close::status::value status, const QString &reason )
WebSocket::disconnectWs( websocketpp::close::status::value status, const QString& reason )
{
tLog() << Q_FUNC_INFO << "Disconnecting";
m_disconnecting = true;
@@ -169,7 +169,9 @@ WebSocket::cleanup()
m_outputStream.seekp( std::ios_base::end );
m_queuedMessagesToSend.empty();
if ( m_connection )
{
m_connection.reset();
}
emit disconnected();
}
@@ -194,7 +196,9 @@ WebSocket::socketStateChanged( QAbstractSocket::SocketState state )
break;
case QAbstractSocket::UnconnectedState:
if ( m_lastSocketState == QAbstractSocket::UnconnectedState )
{
return;
}
tLog() << Q_FUNC_INFO << "Socket now unconnected, cleaning up and emitting disconnected";
m_socket->deleteLater();
m_lastSocketState = QAbstractSocket::UnconnectedState;
@@ -225,8 +229,8 @@ WebSocket::encrypted()
tLog() << Q_FUNC_INFO << "Encrypted connection to Dreamcatcher established";
error_code ec;
QUrl url(m_url);
websocketpp::uri_ptr uri(new websocketpp::uri(false, url.host().toStdString(), url.port(), "/"));
QUrl url( m_url );
websocketpp::uri_ptr uri( new websocketpp::uri( false, url.host().toStdString(), url.port(), "/" ) );
m_connection = m_client->get_connection( uri, ec );
if ( !m_connection || ec.value() != 0 )
@@ -249,12 +253,14 @@ void
WebSocket::readOutput()
{
if ( !m_connection )
{
return;
}
std::string outputString = m_outputStream.str();
if ( outputString.size() > 0 )
{
m_outputStream.str("");
m_outputStream.str( "" );
qint64 sizeWritten = m_socket->write( outputString.data(), outputString.size() );
tDebug() << Q_FUNC_INFO << "Got " << outputString.size() << "from outstream, wrote" << sizeWritten << "bytes to the socket";
@@ -327,7 +333,7 @@ WebSocket::socketReadyRead()
void
WebSocket::encodeMessage( const QByteArray &bytes )
WebSocket::encodeMessage( const QByteArray& bytes )
{
if ( !m_connection )
{
@@ -358,7 +364,7 @@ onMessage( WebSocket* ws, websocketpp::connection_hdl, hatchet_client::message_p
}
void
onClose( WebSocket *ws, websocketpp::connection_hdl )
onClose( WebSocket* ws, websocketpp::connection_hdl )
{
tDebug() << Q_FUNC_INFO << "Handling message";
QMetaObject::invokeMethod( ws, "disconnectSocket", Qt::QueuedConnection );

View File

@@ -38,23 +38,23 @@ void onClose( WebSocket* ws, websocketpp::connection_hdl );
class WebSocket : public QObject
{
Q_OBJECT
public:
public:
explicit WebSocket( const QString& url, const QString& authorizationHeader = QString() );
virtual ~WebSocket();
signals:
signals:
void connected();
void disconnected();
void decodedMessage( QByteArray bytes );
public slots:
public slots:
void setUrl( const QString& url );
void setAuthorizationHeader( const QString& authorizationHeader );
void connectWs();
void disconnectWs( websocketpp::close::status::value status = websocketpp::close::status::normal, const QString& reason = QString( "Disconnecting" ) );
void encodeMessage( const QByteArray& bytes );
private slots:
private slots:
void socketStateChanged( QAbstractSocket::SocketState state );
void sslErrors( const QList< QSslError >& errors );
void disconnectSocket();
@@ -63,11 +63,11 @@ private slots:
void readOutput();
void socketReadyRead();
private:
private:
Q_DISABLE_COPY( WebSocket )
friend void onMessage( WebSocket *ws, websocketpp::connection_hdl, hatchet_client::message_ptr msg );
friend void onClose( WebSocket *ws, websocketpp::connection_hdl );
friend void onMessage( WebSocket* ws, websocketpp::connection_hdl, hatchet_client::message_ptr msg );
friend void onClose( WebSocket* ws, websocketpp::connection_hdl );
bool m_disconnecting;
QUrl m_url;

View File

@@ -39,23 +39,23 @@ WebSocketThreadController::~WebSocketThreadController()
void
WebSocketThreadController::setUrl( const QString &url )
WebSocketThreadController::setUrl( const QString& url )
{
m_url = url;
if ( m_webSocket )
{
QMetaObject::invokeMethod( m_webSocket, "setUrl", Qt::QueuedConnection, Q_ARG( QString, url ));
QMetaObject::invokeMethod( m_webSocket, "setUrl", Qt::QueuedConnection, Q_ARG( QString, url ) );
}
}
void
WebSocketThreadController::setAuthorizationHeader( const QString &authorizationHeader )
WebSocketThreadController::setAuthorizationHeader( const QString& authorizationHeader )
{
m_authorizationHeader = authorizationHeader;
if ( m_webSocket )
{
QMetaObject::invokeMethod( m_webSocket, "setAuthorizationHeader", Qt::QueuedConnection, Q_ARG( QString, authorizationHeader ));
QMetaObject::invokeMethod( m_webSocket, "setAuthorizationHeader", Qt::QueuedConnection, Q_ARG( QString, authorizationHeader ) );
}
}

View File

@@ -27,17 +27,17 @@ class WebSocketThreadController : public QThread
{
Q_OBJECT
public:
public:
explicit WebSocketThreadController( QObject* sip );
virtual ~WebSocketThreadController();
void setUrl( const QString &url );
void setAuthorizationHeader( const QString &authorizationHeader );
void setUrl( const QString& url );
void setAuthorizationHeader( const QString& authorizationHeader );
protected:
protected:
void run();
private:
private:
Q_DISABLE_COPY( WebSocketThreadController )
QPointer< WebSocket > m_webSocket;

View File

@@ -25,7 +25,7 @@
#include <QInputDialog>
TomahawkOAuthTwitter::TomahawkOAuthTwitter( QNetworkAccessManager *nam, QObject* parent )
TomahawkOAuthTwitter::TomahawkOAuthTwitter( QNetworkAccessManager* nam, QObject* parent )
: OAuthTwitter( QByteArray::fromBase64( "QzR2NFdmYTIxcmZJRGNrNEhNUjNB" ), QByteArray::fromBase64( "elhTalU2Ympydmc2VVZNSlg0SnVmcUh5amozaWV4dFkxNFNSOXVCRUFv" ), parent )
{
setNetworkAccessManager( nam );
@@ -36,9 +36,11 @@ const QString
TomahawkOAuthTwitter::authorizationWidget()
{
bool ok;
const QString str = QInputDialog::getText(0, tr( "Twitter PIN" ), tr( "After authenticating on Twitter's web site,\nenter the displayed PIN number here:" ), QLineEdit::Normal, QString(), &ok);
const QString str = QInputDialog::getText( 0, tr( "Twitter PIN" ), tr( "After authenticating on Twitter's web site,\nenter the displayed PIN number here:" ), QLineEdit::Normal, QString(), &ok );
if ( ok && !str.isEmpty() )
{
return str;
}
return QString();
}

View File

@@ -30,15 +30,15 @@ class ACCOUNTDLLEXPORT TomahawkOAuthTwitter : public OAuthTwitter
{
Q_OBJECT
public:
TomahawkOAuthTwitter( QNetworkAccessManager *nam = TomahawkUtils::nam() , QObject *parent = 0 );
public:
TomahawkOAuthTwitter( QNetworkAccessManager* nam = TomahawkUtils::nam() , QObject* parent = 0 );
~TomahawkOAuthTwitter() {}
protected:
protected:
virtual const QString authorizationWidget();
private slots:
private slots:
void error();
};

View File

@@ -46,7 +46,7 @@ TwitterAccountFactory::createAccount( const QString& accountId )
}
TwitterAccount::TwitterAccount( const QString &accountId )
TwitterAccount::TwitterAccount( const QString& accountId )
: Account( accountId )
, m_isAuthenticated( false )
, m_isAuthenticating( false )
@@ -78,7 +78,9 @@ TwitterAccount::configDialogAuthedSignalSlot( bool authed )
tDebug() << Q_FUNC_INFO;
m_isAuthenticated = authed;
if ( !credentials()[ "username" ].toString().isEmpty() )
{
setAccountFriendlyName( QString( "@%1" ).arg( credentials()[ "username" ].toString() ) );
}
syncConfig();
emit configurationChanged();
}
@@ -87,24 +89,24 @@ TwitterAccount::configDialogAuthedSignalSlot( bool authed )
Account::ConnectionState
TwitterAccount::connectionState() const
{
// if ( m_twitterSipPlugin.isNull() )
return Account::Disconnected;
// if ( m_twitterSipPlugin.isNull() )
return Account::Disconnected;
// return m_twitterSipPlugin.data()->connectionState();
// return m_twitterSipPlugin.data()->connectionState();
}
SipPlugin*
TwitterAccount::sipPlugin()
{
// if ( m_twitterSipPlugin.isNull() )
// {
// qDebug() << "CHECKING:" << configuration() << configuration()[ "cachedpeers" ];
// m_twitterSipPlugin = QPointer< TwitterSipPlugin >( new TwitterSipPlugin( this ) );
// if ( m_twitterSipPlugin.isNull() )
// {
// qDebug() << "CHECKING:" << configuration() << configuration()[ "cachedpeers" ];
// m_twitterSipPlugin = QPointer< TwitterSipPlugin >( new TwitterSipPlugin( this ) );
// connect( m_twitterSipPlugin.data(), SIGNAL( stateChanged( Tomahawk::Accounts::Account::ConnectionState ) ), this, SIGNAL( connectionStateChanged( Tomahawk::Accounts::Account::ConnectionState ) ) );
// return m_twitterSipPlugin.data();
// }
// return m_twitterSipPlugin.data();
// connect( m_twitterSipPlugin.data(), SIGNAL( stateChanged( Tomahawk::Accounts::Account::ConnectionState ) ), this, SIGNAL( connectionStateChanged( Tomahawk::Accounts::Account::ConnectionState ) ) );
// return m_twitterSipPlugin.data();
// }
// return m_twitterSipPlugin.data();
return 0;
}
@@ -113,7 +115,9 @@ Tomahawk::InfoSystem::InfoPluginPtr
TwitterAccount::infoPlugin()
{
if ( m_twitterInfoPlugin.isNull() )
{
m_twitterInfoPlugin = QPointer< Tomahawk::InfoSystem::TwitterInfoPlugin >( new Tomahawk::InfoSystem::TwitterInfoPlugin( this ) );
}
return Tomahawk::InfoSystem::InfoPluginPtr( m_twitterInfoPlugin.data() );
}
@@ -159,8 +163,8 @@ TwitterAccount::authenticateSlot()
{
m_isAuthenticating = true;
tDebug() << Q_FUNC_INFO << "Verifying credentials";
QTweetAccountVerifyCredentials *credVerifier = new QTweetAccountVerifyCredentials( m_twitterAuth.data(), this );
connect( credVerifier, SIGNAL( parsedUser( const QTweetUser & ) ), SLOT( connectAuthVerifyReply( const QTweetUser & ) ) );
QTweetAccountVerifyCredentials* credVerifier = new QTweetAccountVerifyCredentials( m_twitterAuth.data(), this );
connect( credVerifier, SIGNAL( parsedUser( const QTweetUser& ) ), SLOT( connectAuthVerifyReply( const QTweetUser& ) ) );
credVerifier->verify();
}
}
@@ -171,11 +175,13 @@ TwitterAccount::deauthenticate()
{
tDebug() << Q_FUNC_INFO;
// if ( m_twitterSipPlugin )
// sipPlugin()->disconnectPlugin();
// if ( m_twitterSipPlugin )
// sipPlugin()->disconnectPlugin();
if ( m_twitterInfoPlugin )
{
Tomahawk::InfoSystem::InfoSystem::instance()->removeInfoPlugin( m_twitterInfoPlugin.data() );
}
m_isAuthenticated = false;
m_isAuthenticating = false;
@@ -190,14 +196,18 @@ TwitterAccount::refreshTwitterAuth()
{
qDebug() << Q_FUNC_INFO << " begin";
if( !m_twitterAuth.isNull() )
{
delete m_twitterAuth.data();
}
Q_ASSERT( TomahawkUtils::nam() != 0 );
tDebug() << Q_FUNC_INFO << " with nam " << TomahawkUtils::nam();
m_twitterAuth = QPointer< TomahawkOAuthTwitter >( new TomahawkOAuthTwitter( TomahawkUtils::nam(), this ) );
if( m_twitterAuth.isNull() )
return false;
{
return false;
}
m_twitterAuth.data()->setOAuthToken( credentials()[ "oauthtoken" ].toString().toLatin1() );
m_twitterAuth.data()->setOAuthTokenSecret( credentials()[ "oauthtokensecret" ].toString().toLatin1() );
@@ -207,7 +217,7 @@ TwitterAccount::refreshTwitterAuth()
void
TwitterAccount::connectAuthVerifyReply( const QTweetUser &user )
TwitterAccount::connectAuthVerifyReply( const QTweetUser& user )
{
m_isAuthenticating = false;
if ( user.id() == 0 )
@@ -223,7 +233,7 @@ TwitterAccount::connectAuthVerifyReply( const QTweetUser &user )
setConfiguration( config );
sync();
// sipPlugin()->connectPlugin();
// sipPlugin()->connectPlugin();
m_isAuthenticated = true;
emit nowAuthenticated( m_twitterAuth, user );
@@ -235,7 +245,9 @@ QPixmap
TwitterAccount::icon() const
{
if ( connectionState() == Connected )
{
return m_onlinePixmap;
}
return m_offlinePixmap;
}

View File

@@ -42,15 +42,30 @@ class ACCOUNTDLLEXPORT TwitterAccountFactory : public AccountFactory
Q_OBJECT
Q_INTERFACES( Tomahawk::Accounts::AccountFactory )
public:
public:
TwitterAccountFactory() {}
virtual ~TwitterAccountFactory() {}
QString prettyName() const { return "Twitter"; }
QString factoryId() const { return "twitteraccount"; }
QString description() const { return tr( "Send tweets from Tomahawk." ); }
QPixmap icon() const { return QPixmap( ":/twitter-account/twitter-icon.png" ); }
AccountTypes types() const { return AccountTypes( StatusPushType ); };
QString prettyName() const
{
return "Twitter";
}
QString factoryId() const
{
return "twitteraccount";
}
QString description() const
{
return tr( "Send tweets from Tomahawk." );
}
QPixmap icon() const
{
return QPixmap( ":/twitter-account/twitter-icon.png" );
}
AccountTypes types() const
{
return AccountTypes( StatusPushType );
};
Account* createAccount( const QString& pluginId = QString() );
};
@@ -58,43 +73,55 @@ class ACCOUNTDLLEXPORT TwitterAccount : public Account
{
Q_OBJECT
public:
TwitterAccount( const QString &accountId );
public:
TwitterAccount( const QString& accountId );
virtual ~TwitterAccount();
QPixmap icon() const;
void authenticate();
void deauthenticate();
bool isAuthenticated() const { return m_isAuthenticated; }
bool isAuthenticated() const
{
return m_isAuthenticated;
}
ConnectionState connectionState() const;
Tomahawk::InfoSystem::InfoPluginPtr infoPlugin();
SipPlugin* sipPlugin();
AccountConfigWidget* configurationWidget() { return m_configWidget.data(); }
QWidget* aclWidget() { return 0; }
AccountConfigWidget* configurationWidget()
{
return m_configWidget.data();
}
QWidget* aclWidget()
{
return 0;
}
bool refreshTwitterAuth();
TomahawkOAuthTwitter* twitterAuth() const { return m_twitterAuth.data(); }
TomahawkOAuthTwitter* twitterAuth() const
{
return m_twitterAuth.data();
}
signals:
void nowAuthenticated( const QPointer< TomahawkOAuthTwitter >&, const QTweetUser &user );
signals:
void nowAuthenticated( const QPointer< TomahawkOAuthTwitter >&, const QTweetUser& user );
void nowDeauthenticated();
private slots:
private slots:
void authenticateSlot();
void configDialogAuthedSignalSlot( bool authed );
void connectAuthVerifyReply( const QTweetUser &user );
void connectAuthVerifyReply( const QTweetUser& user );
private:
private:
QIcon m_icon;
bool m_isAuthenticated;
bool m_isAuthenticating;
QPointer< TomahawkOAuthTwitter > m_twitterAuth;
QPointer< TwitterConfigWidget > m_configWidget;
// QPointer< TwitterSipPlugin > m_twitterSipPlugin;
// QPointer< TwitterSipPlugin > m_twitterSipPlugin;
QPointer< Tomahawk::InfoSystem::TwitterInfoPlugin > m_twitterInfoPlugin;
// for settings access

View File

@@ -42,7 +42,7 @@ namespace Tomahawk
namespace Accounts
{
TwitterConfigWidget::TwitterConfigWidget( TwitterAccount* account, QWidget *parent ) :
TwitterConfigWidget::TwitterConfigWidget( TwitterAccount* account, QWidget* parent ) :
AccountConfigWidget( parent ),
m_ui( new Ui::TwitterConfigWidget ),
m_account( account )
@@ -50,11 +50,11 @@ TwitterConfigWidget::TwitterConfigWidget( TwitterAccount* account, QWidget *pare
m_ui->setupUi( this );
connect( m_ui->twitterAuthenticateButton, SIGNAL( pressed() ),
this, SLOT( authDeauthTwitter() ) );
this, SLOT( authDeauthTwitter() ) );
connect( m_ui->twitterTweetGotTomahawkButton, SIGNAL( pressed() ),
this, SLOT( startPostGotTomahawkStatus() ) );
this, SLOT( startPostGotTomahawkStatus() ) );
connect( m_ui->twitterTweetComboBox, SIGNAL( currentIndexChanged( int ) ),
this, SLOT( tweetComboBoxIndexChanged( int ) ) );
this, SLOT( tweetComboBoxIndexChanged( int ) ) );
m_ui->twitterTweetComboBox->setCurrentIndex( 0 );
m_ui->twitterTweetGotTomahawkButton->setText( tr( "Tweet!" ) );
@@ -62,8 +62,8 @@ TwitterConfigWidget::TwitterConfigWidget( TwitterAccount* account, QWidget *pare
QVariantHash credentials = m_account->credentials();
if ( credentials[ "oauthtoken" ].toString().isEmpty() ||
credentials[ "oauthtokensecret" ].toString().isEmpty() ||
credentials[ "username" ].toString().isEmpty() )
credentials[ "oauthtokensecret" ].toString().isEmpty() ||
credentials[ "username" ].toString().isEmpty() )
{
m_ui->twitterStatusLabel->setText( tr( "Status: No saved credentials" ) );
m_ui->twitterAuthenticateButton->setText( tr( "Authenticate" ) );
@@ -93,16 +93,20 @@ void
TwitterConfigWidget::authDeauthTwitter()
{
if ( m_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 );
TomahawkOAuthTwitter* twitAuth = new TomahawkOAuthTwitter( TomahawkUtils::nam(), this );
twitAuth->authorizePin();
QVariantHash credentials = m_account->credentials();
@@ -110,19 +114,19 @@ TwitterConfigWidget::authenticateTwitter()
credentials[ "oauthtokensecret" ] = twitAuth->oauthTokenSecret();
m_account->setCredentials( credentials );
QTweetAccountVerifyCredentials *credVerifier = new QTweetAccountVerifyCredentials( twitAuth, this );
connect( credVerifier, SIGNAL( parsedUser( const QTweetUser & ) ), SLOT( authenticateVerifyReply( const QTweetUser & ) ) );
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 )
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.") );
QMessageBox::critical( this, tr( "Tweetin' Error" ), tr( "The credentials could not be verified.\nYou may wish to try re-authenticating." ) );
emit twitterAuthed( false );
return;
}
@@ -148,11 +152,11 @@ TwitterConfigWidget::authenticateVerifyReply( const QTweetUser &user )
}
void
TwitterConfigWidget::authenticateVerifyError( QTweetNetBase::ErrorCode code, const QString &errorMsg )
TwitterConfigWidget::authenticateVerifyError( QTweetNetBase::ErrorCode code, const QString& errorMsg )
{
qDebug() << Q_FUNC_INFO;
qDebug() << "Error validating credentials, error code is " << code << ", error message is " << errorMsg;
m_ui->twitterStatusLabel->setText(tr("Status: Error validating credentials"));
m_ui->twitterStatusLabel->setText( tr( "Status: Error validating credentials" ) );
emit twitterAuthed( false );
return;
}
@@ -167,7 +171,7 @@ TwitterConfigWidget::deauthenticateTwitter()
credentials[ "username" ] = QString();
m_account->setCredentials( credentials );
m_ui->twitterStatusLabel->setText(tr("Status: No saved credentials"));
m_ui->twitterStatusLabel->setText( tr( "Status: No saved credentials" ) );
m_ui->twitterAuthenticateButton->setText( tr( "Authenticate" ) );
m_ui->twitterSyncGroupBox->setVisible( false );
@@ -180,16 +184,26 @@ TwitterConfigWidget::tweetComboBoxIndexChanged( int index )
{
Q_UNUSED( index );
if ( m_ui->twitterTweetComboBox->currentText() == tr( "Global Tweet" ) ) //FIXME: use data!
{
m_ui->twitterUserTweetLineEdit->setVisible( false );
}
else
{
m_ui->twitterUserTweetLineEdit->setVisible( true );
}
if ( m_ui->twitterTweetComboBox->currentText() == tr( "Direct Message" ) ) //FIXME: use data!
{
m_ui->twitterTweetGotTomahawkButton->setText( tr( "Send Message!" ) );
}
else if ( m_ui->twitterTweetComboBox->currentText() == tr( "@Mention" ) )
{
m_ui->twitterTweetGotTomahawkButton->setText( tr( "Send Mention!" ) );
}
else
{
m_ui->twitterTweetGotTomahawkButton->setText( tr( "Tweet!" ) );
}
}
void
@@ -200,7 +214,7 @@ TwitterConfigWidget::startPostGotTomahawkStatus()
if ( m_postGTtype != "Global Tweet" && ( m_ui->twitterUserTweetLineEdit->text().isEmpty() || m_ui->twitterUserTweetLineEdit->text() == "@" ) )
{
QMessageBox::critical( this, tr("Tweetin' Error"), tr("You must enter a user name for this type of tweet.") );
QMessageBox::critical( this, tr( "Tweetin' Error" ), tr( "You must enter a user name for this type of tweet." ) );
return;
}
@@ -208,61 +222,65 @@ TwitterConfigWidget::startPostGotTomahawkStatus()
QVariantHash credentials = m_account->credentials();
if ( credentials[ "oauthtoken" ].toString().isEmpty() ||
credentials[ "oauthtokensecret" ].toString().isEmpty() ||
credentials[ "username" ].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.") );
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 );
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 &) ) );
QTweetAccountVerifyCredentials* credVerifier = new QTweetAccountVerifyCredentials( twitAuth, this );
connect( credVerifier, SIGNAL( parsedUser( const QTweetUser& ) ), SLOT( postGotTomahawkStatusAuthVerifyReply( const QTweetUser& ) ) );
credVerifier->verify();
}
void
TwitterConfigWidget::postGotTomahawkStatusAuthVerifyReply( const QTweetUser &user )
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.") );
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 );
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 &) ) );
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()->impl()->dbid() + QString( "} (" ) + uuid.mid( 1, 8 ) + QString( ")" ) + QString( " http://gettomahawk.com" );
if ( m_postGTtype == "@Mention" )
{
QString user = m_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 &) ) );
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()->impl()->dbid() + QString( "} (" ) + uuid.mid( 1, 8 ) + QString( ")" ) + QString( " http://gettomahawk.com" );
QString user = m_ui->twitterUserTweetLineEdit->text();
if ( user.startsWith( "@" ) )
{
user.remove( 0, 1 );
}
statUpdate->post( user, message );
}
}
@@ -271,18 +289,26 @@ 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!") );
{
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!") );
{
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!") );
{
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!") );
{
QMessageBox::information( this, tr( "Tweeted!" ), tr( "Your message has been posted!" ) );
}
}
void
@@ -290,7 +316,7 @@ TwitterConfigWidget::postGotTomahawkStatusUpdateError( QTweetNetBase::ErrorCode
{
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!") );
QMessageBox::critical( this, tr( "Tweetin' Error" ), tr( "There was an error posting your status -- sorry!" ) );
}
}

View File

@@ -2,7 +2,7 @@
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
*
*
* 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
@@ -31,7 +31,7 @@
namespace Ui
{
class TwitterConfigWidget;
class TwitterConfigWidget;
}
namespace Tomahawk
@@ -47,32 +47,32 @@ class ACCOUNTDLLEXPORT TwitterConfigWidget : public AccountConfigWidget
{
Q_OBJECT
public:
explicit TwitterConfigWidget( TwitterAccount* account = 0, QWidget *parent = 0 );
public:
explicit TwitterConfigWidget( TwitterAccount* account = 0, QWidget* parent = 0 );
virtual ~TwitterConfigWidget();
signals:
signals:
void twitterAuthed( bool authed );
void sizeHintChanged();
private slots:
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 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:
private:
void authenticateTwitter();
void deauthenticateTwitter();
Ui::TwitterConfigWidget *m_ui;
TwitterAccount *m_account;
Ui::TwitterConfigWidget* m_ui;
TwitterAccount* m_account;
QString m_postGTtype;
};

View File

@@ -60,8 +60,8 @@ TwitterInfoPlugin::init()
if ( refreshTwitterAuth() )
{
QTweetAccountVerifyCredentials *credVerifier = new QTweetAccountVerifyCredentials( m_twitterAuth.data(), this );
connect( credVerifier, SIGNAL( parsedUser( const QTweetUser & ) ), SLOT( connectAuthVerifyReply( const QTweetUser & ) ) );
QTweetAccountVerifyCredentials* credVerifier = new QTweetAccountVerifyCredentials( m_twitterAuth.data(), this );
connect( credVerifier, SIGNAL( parsedUser( const QTweetUser& ) ), SLOT( connectAuthVerifyReply( const QTweetUser& ) ) );
credVerifier->verify();
}
}
@@ -78,14 +78,18 @@ TwitterInfoPlugin::refreshTwitterAuth()
{
tDebug() << Q_FUNC_INFO << "begin" << this;
if ( !m_twitterAuth.isNull() )
{
delete m_twitterAuth.data();
}
Q_ASSERT( TomahawkUtils::nam() != 0 );
tDebug() << Q_FUNC_INFO << "with nam" << TomahawkUtils::nam() << this;
m_twitterAuth = QPointer< TomahawkOAuthTwitter >( new TomahawkOAuthTwitter( TomahawkUtils::nam(), this ) );
if ( m_twitterAuth.isNull() )
return false;
{
return false;
}
m_twitterAuth.data()->setOAuthToken( m_account->credentials()[ "oauthtoken" ].toString().toLatin1() );
m_twitterAuth.data()->setOAuthTokenSecret( m_account->credentials()[ "oauthtokensecret" ].toString().toLatin1() );
@@ -95,7 +99,7 @@ TwitterInfoPlugin::refreshTwitterAuth()
void
TwitterInfoPlugin::connectAuthVerifyReply( const QTweetUser &user )
TwitterInfoPlugin::connectAuthVerifyReply( const QTweetUser& user )
{
if ( user.id() == 0 )
{
@@ -157,18 +161,20 @@ TwitterInfoPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
{
info = map[ "trackinfo" ].value< Tomahawk::InfoSystem::InfoStringHash >();
msg = tr( "Listening to \"%1\" by %2 and loving it! %3" )
.arg( info[ "title" ] )
.arg( info[ "artist" ] )
.arg( pushInfoPair.first.contains( "shorturl" ) ?
pushInfoPair.first[ "shorturl" ].toUrl().toString() :
GlobalActionManager::instance()->openLink( info[ "title" ], info[ "artist" ], info[ "album" ] ).toString() );
.arg( info[ "title" ] )
.arg( info[ "artist" ] )
.arg( pushInfoPair.first.contains( "shorturl" ) ?
pushInfoPair.first[ "shorturl" ].toUrl().toString() :
GlobalActionManager::instance()->openLink( info[ "title" ], info[ "artist" ], info[ "album" ] ).toString() );
}
else
{
msg = map[ "message" ].toString();
}
QTweetStatusUpdate *statUpdate = new QTweetStatusUpdate( m_twitterAuth.data(), this );
connect( statUpdate, SIGNAL( postedStatus(const QTweetStatus &) ), SLOT( postLovedStatusUpdateReply(const QTweetStatus &) ) );
connect( statUpdate, SIGNAL( error(QTweetNetBase::ErrorCode, const QString&) ), SLOT( postLovedStatusUpdateError(QTweetNetBase::ErrorCode, const QString &) ) );
QTweetStatusUpdate* statUpdate = new QTweetStatusUpdate( m_twitterAuth.data(), this );
connect( statUpdate, SIGNAL( postedStatus( const QTweetStatus& ) ), SLOT( postLovedStatusUpdateReply( const QTweetStatus& ) ) );
connect( statUpdate, SIGNAL( error( QTweetNetBase::ErrorCode, const QString& ) ), SLOT( postLovedStatusUpdateError( QTweetNetBase::ErrorCode, const QString& ) ) );
tDebug() << Q_FUNC_INFO << "Posting message:" << msg;
statUpdate->post( msg );
}
@@ -178,9 +184,13 @@ void
TwitterInfoPlugin::postLovedStatusUpdateReply( const QTweetStatus& status )
{
if ( status.id() == 0 )
{
tDebug() << Q_FUNC_INFO << "Failed to post loved status";
}
else
{
tDebug() << Q_FUNC_INFO << "Successfully posted loved status";
}
}

View File

@@ -27,52 +27,55 @@
#include <QTweetLib/qtweetstatus.h>
#include <QTweetLib/qtweetnetbase.h>
namespace Tomahawk {
namespace Tomahawk
{
namespace Accounts {
class TwitterAccount;
namespace Accounts
{
class TwitterAccount;
}
namespace InfoSystem
{
class TwitterInfoPlugin : public InfoPlugin
{
Q_OBJECT
public:
TwitterInfoPlugin( Tomahawk::Accounts::TwitterAccount* account );
virtual ~TwitterInfoPlugin();
public slots:
void notInCacheSlot( const Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
{
Q_UNUSED( criteria );
Q_UNUSED( requestData );
}
namespace InfoSystem {
class TwitterInfoPlugin : public InfoPlugin
{
Q_OBJECT
public:
TwitterInfoPlugin( Tomahawk::Accounts::TwitterAccount* account );
virtual ~TwitterInfoPlugin();
public slots:
void notInCacheSlot( const Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
{
Q_UNUSED( criteria );
Q_UNUSED( requestData );
}
protected slots:
void init();
void pushInfo( Tomahawk::InfoSystem::InfoPushData pushData );
void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
{
Q_UNUSED( requestData );
}
private slots:
void connectAuthVerifyReply( const QTweetUser &user );
void postLovedStatusUpdateReply( const QTweetStatus& status );
void postLovedStatusUpdateError( QTweetNetBase::ErrorCode code, const QString& errorMsg );
private:
bool refreshTwitterAuth();
bool isValid() const;
Tomahawk::Accounts::TwitterAccount* m_account;
QPointer< TomahawkOAuthTwitter > m_twitterAuth;
};
protected slots:
void init();
void pushInfo( Tomahawk::InfoSystem::InfoPushData pushData );
void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
{
Q_UNUSED( requestData );
}
private slots:
void connectAuthVerifyReply( const QTweetUser& user );
void postLovedStatusUpdateReply( const QTweetStatus& status );
void postLovedStatusUpdateError( QTweetNetBase::ErrorCode code, const QString& errorMsg );
private:
bool refreshTwitterAuth();
bool isValid() const;
Tomahawk::Accounts::TwitterAccount* m_account;
QPointer< TomahawkOAuthTwitter > m_twitterAuth;
};
}
}
#endif // TWITTERINFOPLUGIN_H

View File

@@ -60,7 +60,7 @@ TwitterSipPlugin::TwitterSipPlugin( Tomahawk::Accounts::Account* account )
{
qDebug() << Q_FUNC_INFO;
connect( account, SIGNAL( nowAuthenticated( const QPointer< TomahawkOAuthTwitter > &, const QTweetUser & ) ), SLOT( accountAuthenticated( const QPointer< TomahawkOAuthTwitter > &, const QTweetUser & ) ) );
connect( account, SIGNAL( nowAuthenticated( const QPointer< TomahawkOAuthTwitter >&, const QTweetUser& ) ), SLOT( accountAuthenticated( const QPointer< TomahawkOAuthTwitter >&, const QTweetUser& ) ) );
m_configuration = account->configuration();
qDebug() << "SIP configuration:" << m_configuration << m_configuration[ "cachedpeers" ];
@@ -145,15 +145,25 @@ TwitterSipPlugin::disconnectPlugin()
m_connectTimer.stop();
m_dmPollTimer.stop();
if( !m_friendsTimeline.isNull() )
{
delete m_friendsTimeline.data();
}
if( !m_mentions.isNull() )
{
delete m_mentions.data();
}
if( !m_directMessages.isNull() )
{
delete m_directMessages.data();
}
if( !m_directMessageNew.isNull() )
{
delete m_directMessageNew.data();
}
if( !m_directMessageDestroy.isNull() )
{
delete m_directMessageDestroy.data();
}
m_cachedTwitterAuth = 0;
@@ -165,12 +175,14 @@ TwitterSipPlugin::disconnectPlugin()
}
void
TwitterSipPlugin::accountAuthenticated( const QPointer< TomahawkOAuthTwitter > &twitterAuth, const QTweetUser &user )
TwitterSipPlugin::accountAuthenticated( const QPointer< TomahawkOAuthTwitter >& twitterAuth, const QTweetUser& user )
{
Q_UNUSED( user );
if ( !m_account->enabled() || !m_account->isAuthenticated() )
{
return;
}
m_cachedTwitterAuth = twitterAuth;
@@ -179,12 +191,12 @@ TwitterSipPlugin::accountAuthenticated( const QPointer< TomahawkOAuthTwitter > &
m_directMessages = QPointer<QTweetDirectMessages>( new QTweetDirectMessages( m_cachedTwitterAuth.data(), this ) );
m_directMessageNew = QPointer<QTweetDirectMessageNew>( new QTweetDirectMessageNew( m_cachedTwitterAuth.data(), this ) );
m_directMessageDestroy = QPointer<QTweetDirectMessageDestroy>( new QTweetDirectMessageDestroy( m_cachedTwitterAuth.data(), this ) );
connect( m_friendsTimeline.data(), SIGNAL( parsedStatuses(const QList< QTweetStatus > &) ), SLOT( friendsTimelineStatuses(const QList<QTweetStatus> &) ) );
connect( m_mentions.data(), SIGNAL( parsedStatuses(const QList< QTweetStatus > &) ), SLOT( mentionsStatuses(const QList<QTweetStatus> &) ) );
connect( m_directMessages.data(), SIGNAL( parsedDirectMessages(const QList<QTweetDMStatus> &)), SLOT( directMessages(const QList<QTweetDMStatus> &) ) );
connect( m_directMessageNew.data(), SIGNAL( parsedDirectMessage(const QTweetDMStatus &)), SLOT( directMessagePosted(const QTweetDMStatus &) ) );
connect( m_directMessageNew.data(), SIGNAL( error(QTweetNetBase::ErrorCode, const QString &) ), SLOT( directMessagePostError(QTweetNetBase::ErrorCode, const QString &) ) );
connect( m_directMessageDestroy.data(), SIGNAL( parsedDirectMessage(const QTweetDMStatus &) ), SLOT( directMessageDestroyed(const QTweetDMStatus &) ) );
connect( m_friendsTimeline.data(), SIGNAL( parsedStatuses( const QList< QTweetStatus >& ) ), SLOT( friendsTimelineStatuses( const QList<QTweetStatus>& ) ) );
connect( m_mentions.data(), SIGNAL( parsedStatuses( const QList< QTweetStatus >& ) ), SLOT( mentionsStatuses( const QList<QTweetStatus>& ) ) );
connect( m_directMessages.data(), SIGNAL( parsedDirectMessages( const QList<QTweetDMStatus>& ) ), SLOT( directMessages( const QList<QTweetDMStatus>& ) ) );
connect( m_directMessageNew.data(), SIGNAL( parsedDirectMessage( const QTweetDMStatus& ) ), SLOT( directMessagePosted( const QTweetDMStatus& ) ) );
connect( m_directMessageNew.data(), SIGNAL( error( QTweetNetBase::ErrorCode, const QString& ) ), SLOT( directMessagePostError( QTweetNetBase::ErrorCode, const QString& ) ) );
connect( m_directMessageDestroy.data(), SIGNAL( parsedDirectMessage( const QTweetDMStatus& ) ), SLOT( directMessageDestroyed( const QTweetDMStatus& ) ) );
m_state = Tomahawk::Accounts::Account::Connected;
emit stateChanged( m_state );
QStringList peerList = m_cachedPeers.keys();
@@ -203,31 +215,43 @@ void
TwitterSipPlugin::checkTimerFired()
{
if ( !isValid() )
{
return;
}
if ( m_cachedFriendsSinceId == 0 )
{
m_cachedFriendsSinceId = m_configuration[ "cachedfriendssinceid" ].toLongLong();
}
qDebug() << "TwitterSipPlugin looking at friends timeline since id " << m_cachedFriendsSinceId;
if ( !m_friendsTimeline.isNull() )
{
m_friendsTimeline.data()->fetch( m_cachedFriendsSinceId, 0, 800 );
}
if ( m_cachedMentionsSinceId == 0 )
{
m_cachedMentionsSinceId = m_configuration[ "cachedmentionssinceid" ].toLongLong();
}
qDebug() << "TwitterSipPlugin looking at mentions timeline since id " << m_cachedMentionsSinceId;
if ( !m_mentions.isNull() )
{
m_mentions.data()->fetch( m_cachedMentionsSinceId, 0, 800 );
}
}
void
TwitterSipPlugin::registerOffers( const QStringList &peerList )
TwitterSipPlugin::registerOffers( const QStringList& peerList )
{
if ( !isValid() )
{
return;
}
foreach( QString screenName, peerList )
{
@@ -277,9 +301,13 @@ TwitterSipPlugin::connectTimerFired()
if ( !isValid() || m_cachedPeers.isEmpty() )
{
if ( !isValid() )
{
tDebug() << Q_FUNC_INFO << " is not valid";
}
if ( m_cachedPeers.isEmpty() )
{
tDebug() << Q_FUNC_INFO << " has empty cached peers";
}
return;
}
@@ -291,7 +319,7 @@ TwitterSipPlugin::connectTimerFired()
}
void
TwitterSipPlugin::parseGotTomahawk( const QRegExp &regex, const QString &screenName, const QString &text )
TwitterSipPlugin::parseGotTomahawk( const QRegExp& regex, const QString& screenName, const QString& text )
{
QString myScreenName = m_configuration[ "screenname" ].toString();
qDebug() << "TwitterSipPlugin found an exact matching Got Tomahawk? mention or direct message from user " << screenName << ", now parsing";
@@ -318,7 +346,9 @@ TwitterSipPlugin::parseGotTomahawk( const QRegExp &regex, const QString &screenN
return;
}
else
{
qDebug() << "TwitterSipPlugin parsed node " << node << " out of the tweet";
}
if ( node == Database::instance()->impl()->dbid() )
{
@@ -333,14 +363,16 @@ TwitterSipPlugin::parseGotTomahawk( const QRegExp &regex, const QString &screenN
//force a re-send of info but no need to re-register
peerData["resend"] = QVariant::fromValue< bool >( true );
if ( peerData["node"].toString() != node )
{
peerData["rekey"] = QVariant::fromValue< bool >( true );
}
}
peerData["node"] = QVariant::fromValue< QString >( node );
QMetaObject::invokeMethod( this, "registerOffer", Q_ARG( QString, screenName ), Q_ARG( QVariantHash, peerData ) );
}
void
TwitterSipPlugin::friendsTimelineStatuses( const QList< QTweetStatus > &statuses )
TwitterSipPlugin::friendsTimelineStatuses( const QList< QTweetStatus >& statuses )
{
tDebug() << Q_FUNC_INFO;
QRegExp regex( s_gotTomahawkRegex, Qt::CaseSensitive, QRegExp::RegExp2 );
@@ -349,21 +381,29 @@ TwitterSipPlugin::friendsTimelineStatuses( const QList< QTweetStatus > &statuses
foreach ( QTweetStatus status, statuses )
{
if ( !regex.exactMatch( status.text() ) )
{
continue;
}
if ( !latestHash.contains( status.user().screenName() ) )
{
latestHash[status.user().screenName()] = status;
}
else
{
if ( status.id() > latestHash[status.user().screenName()].id() )
{
latestHash[status.user().screenName()] = status;
}
}
}
foreach( QTweetStatus status, latestHash.values() )
{
if ( status.id() > m_cachedFriendsSinceId )
{
m_cachedFriendsSinceId = status.id();
}
tDebug() << "TwitterSipPlugin checking mention from " << status.user().screenName() << " with content " << status.text();
parseGotTomahawk( regex, status.user().screenName(), status.text() );
@@ -374,7 +414,7 @@ TwitterSipPlugin::friendsTimelineStatuses( const QList< QTweetStatus > &statuses
}
void
TwitterSipPlugin::mentionsStatuses( const QList< QTweetStatus > &statuses )
TwitterSipPlugin::mentionsStatuses( const QList< QTweetStatus >& statuses )
{
tDebug() << Q_FUNC_INFO;
QRegExp regex( s_gotTomahawkRegex, Qt::CaseSensitive, QRegExp::RegExp2 );
@@ -383,21 +423,29 @@ TwitterSipPlugin::mentionsStatuses( const QList< QTweetStatus > &statuses )
foreach ( QTweetStatus status, statuses )
{
if ( !regex.exactMatch( status.text() ) )
{
continue;
}
if ( !latestHash.contains( status.user().screenName() ) )
{
latestHash[status.user().screenName()] = status;
}
else
{
if ( status.id() > latestHash[status.user().screenName()].id() )
{
latestHash[status.user().screenName()] = status;
}
}
}
foreach( QTweetStatus status, latestHash.values() )
{
if ( status.id() > m_cachedMentionsSinceId )
{
m_cachedMentionsSinceId = status.id();
}
tDebug() << "TwitterSipPlugin checking mention from " << status.user().screenName() << " with content " << status.text();
parseGotTomahawk( regex, status.user().screenName(), status.text() );
@@ -411,19 +459,25 @@ void
TwitterSipPlugin::pollDirectMessages()
{
if ( !isValid() )
{
return;
}
if ( m_cachedDirectMessagesSinceId == 0 )
{
m_cachedDirectMessagesSinceId = m_configuration[ "cacheddirectmessagessinceid" ].toLongLong();
}
tDebug() << "TwitterSipPlugin looking for direct messages since id " << m_cachedDirectMessagesSinceId;
if ( !m_directMessages.isNull() )
{
m_directMessages.data()->fetch( m_cachedDirectMessagesSinceId, 0, 800 );
}
}
void
TwitterSipPlugin::directMessages( const QList< QTweetDMStatus > &messages )
TwitterSipPlugin::directMessages( const QList< QTweetDMStatus >& messages )
{
tDebug() << Q_FUNC_INFO;
@@ -435,24 +489,36 @@ TwitterSipPlugin::directMessages( const QList< QTweetDMStatus > &messages )
{
if ( !regex.exactMatch( status.text() ) )
{
QStringList splitList = status.text().split(':');
QStringList splitList = status.text().split( ':' );
if ( splitList.length() != 5 )
{
continue;
}
if ( splitList[0] != "TOMAHAWKPEER" )
{
continue;
}
if ( !splitList[1].startsWith( "Host=" ) || !splitList[2].startsWith( "Port=" ) || !splitList[3].startsWith( "Node=" ) || !splitList[4].startsWith( "PKey=" ) )
{
continue;
}
int port = splitList[2].mid( 5 ).toInt();
if ( port == 0 )
{
continue;
}
}
if ( !latestHash.contains( status.senderScreenName() ) )
{
latestHash[status.senderScreenName()] = status;
}
else
{
if ( status.id() > latestHash[status.senderScreenName()].id() )
{
latestHash[status.senderScreenName()] = status;
}
}
}
@@ -460,22 +526,26 @@ TwitterSipPlugin::directMessages( const QList< QTweetDMStatus > &messages )
{
qDebug() << "TwitterSipPlugin checking direct message from " << status.senderScreenName() << " with content " << status.text();
if ( status.id() > m_cachedDirectMessagesSinceId )
{
m_cachedDirectMessagesSinceId = status.id();
}
if ( regex.exactMatch( status.text() ) )
{
parseGotTomahawk( regex, status.sender().screenName(), status.text() );
}
else
{
QStringList splitList = status.text().split(':');
QStringList splitList = status.text().split( ':' );
qDebug() << "TwitterSipPlugin found " << splitList.length() << " parts to the message; the parts are:";
foreach( QString part, splitList )
qDebug() << part;
qDebug() << part;
//validity is checked above
int port = splitList[2].mid( 5 ).toInt();
QString host = splitList[1].mid( 5 );
QString node = splitList[3].mid( 5 );
QString pkey = splitList[4].mid( 5 );
QStringList splitNode = node.split('*');
QStringList splitNode = node.split( '*' );
if ( splitNode.length() != 2 )
{
qDebug() << "Old-style node info found, ignoring";
@@ -485,8 +555,8 @@ TwitterSipPlugin::directMessages( const QList< QTweetDMStatus > &messages )
QVariantHash peerData = ( m_cachedPeers.contains( status.senderScreenName() ) ) ?
m_cachedPeers[status.senderScreenName()].toHash() :
QVariantHash();
m_cachedPeers[status.senderScreenName()].toHash() :
QVariantHash();
peerData["host"] = QVariant::fromValue< QString >( host );
peerData["port"] = QVariant::fromValue< int >( port );
@@ -500,7 +570,9 @@ TwitterSipPlugin::directMessages( const QList< QTweetDMStatus > &messages )
{
qDebug() << "TwitterSipPlugin found message destined for this node; destroying it";
if ( !m_directMessageDestroy.isNull() )
{
m_directMessageDestroy.data()->destroyMessage( status.id() );
}
}
}
}
@@ -510,7 +582,7 @@ TwitterSipPlugin::directMessages( const QList< QTweetDMStatus > &messages )
}
void
TwitterSipPlugin::registerOffer( const QString &screenName, const QVariantHash &peerData )
TwitterSipPlugin::registerOffer( const QString& screenName, const QVariantHash& peerData )
{
qDebug() << Q_FUNC_INFO;
@@ -521,7 +593,9 @@ TwitterSipPlugin::registerOffer( const QString &screenName, const QVariantHash &
QString friendlyName = QString( '@' + screenName );
if ( !m_cachedAvatars.contains( screenName ) )
{
QMetaObject::invokeMethod( this, "fetchAvatar", Q_ARG( QString, screenName ) );
}
QVariantHash _peerData( peerData );
@@ -539,8 +613,8 @@ TwitterSipPlugin::registerOffer( const QString &screenName, const QVariantHash &
}
if ( !_peerData.contains( "okey" ) ||
!_peerData.contains( "onod" ) ||
( _peerData.contains( "onod" ) && _peerData["onod"] != Database::instance()->impl()->dbid() ) )
!_peerData.contains( "onod" ) ||
( _peerData.contains( "onod" ) && _peerData["onod"] != Database::instance()->impl()->dbid() ) )
{
QString okey = QUuid::createUuid().toString().split( '-' ).last();
okey.chop( 1 );
@@ -560,8 +634,10 @@ TwitterSipPlugin::registerOffer( const QString &screenName, const QVariantHash &
if ( !_peerData.contains( "ohst" ) || !_peerData.contains( "oprt" ) ||
_peerData["ohst"].toString() != Servent::instance()->externalAddress() ||
_peerData["oprt"].toInt() != Servent::instance()->externalPort()
)
)
{
needToSend = true;
}
if( needToAddToCache && _peerData.contains( "node" ) )
{
@@ -569,16 +645,20 @@ TwitterSipPlugin::registerOffer( const QString &screenName, const QVariantHash &
m_keyCache << Servent::instance()->createConnectionKey( friendlyName, _peerData["node"].toString(), _peerData["okey"].toString(), false );
}
if( needToSend && _peerData.contains( "node") )
if( needToSend && _peerData.contains( "node" ) )
{
qDebug() << "TwitterSipPlugin needs to send and has node";
_peerData["ohst"] = QVariant::fromValue< QString >( Servent::instance()->externalAddress() );
_peerData["oprt"] = QVariant::fromValue< int >( Servent::instance()->externalPort() );
peersChanged = true;
if( !Servent::instance()->externalAddress().isEmpty() && !Servent::instance()->externalPort() == 0 )
{
QMetaObject::invokeMethod( this, "sendOffer", Q_ARG( QString, screenName ), Q_ARG( QVariantHash, _peerData ) );
}
else
{
qDebug() << "TwitterSipPlugin did not send offer because external address is " << Servent::instance()->externalAddress() << " and external port is " << Servent::instance()->externalPort();
}
}
if ( peersChanged )
@@ -590,37 +670,41 @@ TwitterSipPlugin::registerOffer( const QString &screenName, const QVariantHash &
}
if ( m_state == Tomahawk::Accounts::Account::Connected && _peerData.contains( "host" ) && _peerData.contains( "port" ) && _peerData.contains( "pkey" ) )
{
QMetaObject::invokeMethod( this, "makeConnection", Q_ARG( QString, screenName ), Q_ARG( QVariantHash, _peerData ) );
}
}
void
TwitterSipPlugin::sendOffer( const QString &screenName, const QVariantHash &peerData )
TwitterSipPlugin::sendOffer( const QString& screenName, const QVariantHash& peerData )
{
qDebug() << Q_FUNC_INFO;
QString offerString = QString( "TOMAHAWKPEER:Host=%1:Port=%2:Node=%3*%4:PKey=%5" ).arg( peerData["ohst"].toString() )
.arg( peerData["oprt"].toString() )
.arg( Database::instance()->impl()->dbid() )
.arg( peerData["node"].toString().left( 8 ) )
.arg( peerData["okey"].toString() );
.arg( peerData["oprt"].toString() )
.arg( Database::instance()->impl()->dbid() )
.arg( peerData["node"].toString().left( 8 ) )
.arg( peerData["okey"].toString() );
qDebug() << "TwitterSipPlugin sending message to " << screenName << ": " << offerString;
if( !m_directMessageNew.isNull() )
{
m_directMessageNew.data()->post( screenName, offerString );
}
}
void
TwitterSipPlugin::makeConnection( const QString &screenName, const QVariantHash &peerData )
TwitterSipPlugin::makeConnection( const QString& screenName, const QVariantHash& peerData )
{
qDebug() << Q_FUNC_INFO;
if ( !peerData.contains( "host" ) || !peerData.contains( "port" ) || !peerData.contains( "pkey" ) || !peerData.contains( "node" ) ||
peerData["host"].toString().isEmpty() || peerData["port"].toString().isEmpty() || peerData["pkey"].toString().isEmpty() || peerData["node"].toString().isEmpty() )
peerData["host"].toString().isEmpty() || peerData["port"].toString().isEmpty() || peerData["pkey"].toString().isEmpty() || peerData["node"].toString().isEmpty() )
{
qDebug() << "TwitterSipPlugin could not find host and/or port and/or pkey and/or node for peer " << screenName;
return;
}
if ( peerData["host"].toString() == Servent::instance()->externalAddress() &&
peerData["port"].toInt() == Servent::instance()->externalPort() )
peerData["port"].toInt() == Servent::instance()->externalPort() )
{
qDebug() << "TwitterSipPlugin asked to make connection to our own host and port, ignoring " << screenName;
return;
@@ -644,7 +728,7 @@ TwitterSipPlugin::directMessagePosted( const QTweetDMStatus& message )
}
void
TwitterSipPlugin::directMessagePostError( QTweetNetBase::ErrorCode errorCode, const QString &message )
TwitterSipPlugin::directMessagePostError( QTweetNetBase::ErrorCode errorCode, const QString& message )
{
Q_UNUSED( errorCode );
Q_UNUSED( message );
@@ -664,22 +748,26 @@ TwitterSipPlugin::fetchAvatar( const QString& screenName )
{
qDebug() << Q_FUNC_INFO;
if ( !isValid() )
{
return;
}
QTweetUserShow *userShowFetch = new QTweetUserShow( m_cachedTwitterAuth.data(), this );
QTweetUserShow* userShowFetch = new QTweetUserShow( m_cachedTwitterAuth.data(), this );
connect( userShowFetch, SIGNAL( parsedUserInfo( QTweetUser ) ), SLOT( avatarUserDataSlot( QTweetUser ) ) );
userShowFetch->fetch( screenName );
}
void
TwitterSipPlugin::avatarUserDataSlot( const QTweetUser &user )
TwitterSipPlugin::avatarUserDataSlot( const QTweetUser& user )
{
tDebug() << Q_FUNC_INFO;
if ( !isValid() || user.profileImageUrl().isEmpty())
if ( !isValid() || user.profileImageUrl().isEmpty() )
{
return;
}
QNetworkRequest request( user.profileImageUrl() );
QNetworkReply *reply = m_cachedTwitterAuth.data()->networkAccessManager()->get( request );
QNetworkReply* reply = m_cachedTwitterAuth.data()->networkAccessManager()->get( request );
reply->setProperty( "screenname", user.screenName() );
connect( reply, SIGNAL( finished() ), this, SLOT( profilePicReply() ) );
}
@@ -689,7 +777,7 @@ void
TwitterSipPlugin::profilePicReply()
{
tDebug() << Q_FUNC_INFO;
QNetworkReply *reply = qobject_cast< QNetworkReply* >( sender() );
QNetworkReply* reply = qobject_cast< QNetworkReply* >( sender() );
if ( !reply || reply->error() != QNetworkReply::NoError || !reply->property( "screenname" ).isValid() )
{
tDebug() << Q_FUNC_INFO << " reply not valid or came back with error";
@@ -710,7 +798,9 @@ TwitterSipPlugin::configurationChanged()
{
tDebug() << Q_FUNC_INFO;
if ( m_state != Tomahawk::Accounts::Account::Disconnected )
{
m_account->deauthenticate();
}
connectPlugin();
}

View File

@@ -44,8 +44,8 @@ class ACCOUNTDLLEXPORT TwitterSipPlugin : public SipPlugin
{
Q_OBJECT
public:
TwitterSipPlugin( Tomahawk::Accounts::Account *account );
public:
TwitterSipPlugin( Tomahawk::Accounts::Account* account );
virtual ~TwitterSipPlugin() {}
@@ -53,10 +53,10 @@ public:
virtual Tomahawk::Accounts::Account::ConnectionState connectionState() const;
virtual QString inviteString() const;
signals:
signals:
void stateChanged( Tomahawk::Accounts::Account::ConnectionState );
public slots:
public slots:
virtual void connectPlugin();
void disconnectPlugin();
void configurationChanged();
@@ -67,12 +67,12 @@ public slots:
Q_UNUSED( info );
}
void broadcastMsg( const QString &msg )
void broadcastMsg( const QString& msg )
{
Q_UNUSED( msg );
}
bool addContact( const QString &peerId, AddContactOptions options, const QString& msg = QString() )
bool addContact( const QString& peerId, AddContactOptions options, const QString& msg = QString() )
{
Q_UNUSED( peerId );
Q_UNUSED( msg );
@@ -83,29 +83,29 @@ public slots:
void checkSettings();
private slots:
void accountAuthenticated( const QPointer< TomahawkOAuthTwitter > &twitterAuth, const QTweetUser &user );
private slots:
void accountAuthenticated( const QPointer< TomahawkOAuthTwitter >& twitterAuth, const QTweetUser& user );
void checkTimerFired();
void connectTimerFired();
void friendsTimelineStatuses( const QList< QTweetStatus > &statuses );
void mentionsStatuses( const QList< QTweetStatus > &statuses );
void friendsTimelineStatuses( const QList< QTweetStatus >& statuses );
void mentionsStatuses( const QList< QTweetStatus >& statuses );
void pollDirectMessages();
void directMessages( const QList< QTweetDMStatus > &messages );
void directMessagePosted( const QTweetDMStatus &message );
void directMessagePostError( QTweetNetBase::ErrorCode errorCode, const QString &message );
void directMessageDestroyed( const QTweetDMStatus &message );
void registerOffers( const QStringList &peerList );
void registerOffer( const QString &screenName, const QVariantHash &peerdata );
void sendOffer( const QString &screenName, const QVariantHash &peerdata );
void makeConnection( const QString &screenName, const QVariantHash &peerdata );
void fetchAvatar( const QString &screenName );
void avatarUserDataSlot( const QTweetUser &user );
void directMessages( const QList< QTweetDMStatus >& messages );
void directMessagePosted( const QTweetDMStatus& message );
void directMessagePostError( QTweetNetBase::ErrorCode errorCode, const QString& message );
void directMessageDestroyed( const QTweetDMStatus& message );
void registerOffers( const QStringList& peerList );
void registerOffer( const QString& screenName, const QVariantHash& peerdata );
void sendOffer( const QString& screenName, const QVariantHash& peerdata );
void makeConnection( const QString& screenName, const QVariantHash& peerdata );
void fetchAvatar( const QString& screenName );
void avatarUserDataSlot( const QTweetUser& user );
void profilePicReply();
private:
private:
void syncConfig();
bool refreshTwitterAuth();
void parseGotTomahawk( const QRegExp &regex, const QString &screenName, const QString &text );
void parseGotTomahawk( const QRegExp& regex, const QString& screenName, const QString& text );
QPointer< TomahawkOAuthTwitter > m_cachedTwitterAuth;

View File

@@ -39,7 +39,7 @@ XmppAccountFactory::createAccount( const QString& accountId )
}
XmppAccount::XmppAccount( const QString &accountId )
XmppAccount::XmppAccount( const QString& accountId )
: Account( accountId )
{
setAccountServiceName( "Jabber (XMPP)" );
@@ -61,7 +61,9 @@ QPixmap
XmppAccount::icon() const
{
if ( connectionState() == Connected )
{
return m_onlinePixmap;
}
return m_offlinePixmap;
}
@@ -70,7 +72,9 @@ void
XmppAccount::authenticate()
{
if ( connectionState() != Account::Connected )
{
sipPlugin()->connectPlugin();
}
}
@@ -78,7 +82,9 @@ void
XmppAccount::deauthenticate()
{
if ( connectionState() != Account::Disconnected && !m_xmppSipPlugin.isNull() )
{
m_xmppSipPlugin->disconnectPlugin();
}
}
bool
@@ -92,7 +98,9 @@ Account::ConnectionState
XmppAccount::connectionState() const
{
if ( m_xmppSipPlugin.isNull() )
{
return Account::Disconnected;
}
return m_xmppSipPlugin.data()->connectionState();
}
@@ -101,7 +109,9 @@ void
XmppAccount::saveConfig()
{
if ( !m_configWidget.isNull() )
{
static_cast< XmppConfigWidget* >( m_configWidget.data() )->saveConfig();
}
}
@@ -109,7 +119,9 @@ InfoSystem::InfoPluginPtr
XmppAccount::infoPlugin()
{
if( !m_xmppSipPlugin.isNull() )
{
return m_xmppSipPlugin.data()->infoPlugin();
}
return InfoSystem::InfoPluginPtr();
}
@@ -121,7 +133,9 @@ XmppAccount::sipPlugin( bool create )
if ( m_xmppSipPlugin.isNull() )
{
if ( !create )
{
return 0;
}
m_xmppSipPlugin = QPointer< XmppSipPlugin >( new XmppSipPlugin( this ) );

View File

@@ -45,15 +45,30 @@ class ACCOUNTDLLEXPORT XmppAccountFactory : public AccountFactory
// for settings access
friend class XmppConfigWidget;
public:
public:
XmppAccountFactory() {}
virtual ~XmppAccountFactory() {}
QString prettyName() const { return "Jabber (XMPP)"; }
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 ); }
QString prettyName() const
{
return "Jabber (XMPP)";
}
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 );
}
Account* createAccount( const QString& pluginId = QString() );
};
@@ -61,8 +76,8 @@ class ACCOUNTDLLEXPORT XmppAccount : public Account
{
Q_OBJECT
public:
XmppAccount( const QString &accountId );
public:
XmppAccount( const QString& accountId );
virtual ~XmppAccount();
QPixmap icon() const;
@@ -75,13 +90,19 @@ public:
SipPlugin* sipPlugin( bool create = true );
AccountConfigWidget* configurationWidget() { return m_configWidget.data(); }
QWidget* aclWidget() { return 0; }
AccountConfigWidget* configurationWidget()
{
return m_configWidget.data();
}
QWidget* aclWidget()
{
return 0;
}
void saveConfig();
virtual Tomahawk::Accounts::Account::ConnectionState connectionState() const;
protected:
protected:
QPointer< AccountConfigWidget > m_configWidget; // so the google wrapper can change the config dialog a bit
QPointer< XmppSipPlugin > m_xmppSipPlugin;
QPointer< Tomahawk::InfoSystem::XmppInfoPlugin > m_xmppInfoPlugin;

View File

@@ -35,7 +35,7 @@ namespace Tomahawk
namespace Accounts
{
XmppConfigWidget::XmppConfigWidget( XmppAccount* account, QWidget *parent )
XmppConfigWidget::XmppConfigWidget( XmppAccount* account, QWidget* parent )
: AccountConfigWidget( parent )
, m_ui( new Ui::XmppConfigWidget )
, m_account( account )
@@ -47,8 +47,8 @@ XmppConfigWidget::XmppConfigWidget( XmppAccount* account, QWidget *parent )
m_ui->xmppPassword->setText( account->credentials().contains( "password" ) ? account->credentials()[ "password" ].toString() : QString() );
m_ui->xmppServer->setText( account->configuration().contains( "server" ) ? account->configuration()[ "server" ].toString() : QString() );
m_ui->xmppPort->setValue( account->configuration().contains( "port" ) ? account->configuration()[ "port" ].toInt() : 5222 );
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->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();
@@ -71,7 +71,7 @@ XmppConfigWidget::XmppConfigWidget( XmppAccount* account, QWidget *parent )
m_ui->xmppBlurb->hide();
m_ui->xmppConfigFrame->show();
m_ui->xmppConfigLabel->setText( tr( "Account provided by %1." )
.arg( cs->prettyName() ) );
.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() ),
@@ -108,7 +108,7 @@ XmppConfigWidget::saveConfig()
m_account->setAccountFriendlyName( m_ui->xmppUsername->text() );
m_account->setCredentials( credentials );
m_account->setConfiguration( configuration);
m_account->setConfiguration( configuration );
m_account->sync();
static_cast< XmppSipPlugin* >( m_account->sipPlugin() )->checkSettings();
@@ -116,23 +116,25 @@ XmppConfigWidget::saveConfig()
void
XmppConfigWidget::onCheckJidExists( const QString &jid )
XmppConfigWidget::onCheckJidExists( const QString& jid )
{
QList< Tomahawk::Accounts::Account* > accounts = Tomahawk::Accounts::AccountManager::instance()->accounts( Tomahawk::Accounts::SipType );
foreach( Tomahawk::Accounts::Account* account, accounts )
foreach( Tomahawk::Accounts::Account * account, accounts )
{
if ( account->accountId() == m_account->accountId() )
{
continue;
}
QString savedUsername = account->credentials()[ "username" ].toString();
QStringList savedSplitUsername = account->credentials()[ "username" ].toString().split("@");
QStringList savedSplitUsername = account->credentials()[ "username" ].toString().split( "@" );
QString savedServer = account->configuration()[ "server" ].toString();
int savedPort = account->configuration()[ "port" ].toInt();
if ( ( savedUsername == jid || savedSplitUsername.contains( jid ) ) &&
savedServer == m_ui->xmppServer->text() &&
savedPort == m_ui->xmppPort->value() &&
!jid.trimmed().isEmpty() )
savedServer == m_ui->xmppServer->text() &&
savedPort == m_ui->xmppPort->value() &&
!jid.trimmed().isEmpty() )
{
m_ui->jidExistsLabel->show();
// the already jid exists

View File

@@ -26,7 +26,7 @@
namespace Ui
{
class XmppConfigWidget;
class XmppConfigWidget;
}
namespace Tomahawk
@@ -43,24 +43,24 @@ class ACCOUNTDLLEXPORT XmppConfigWidget : public AccountConfigWidget
{
Q_OBJECT
public:
explicit XmppConfigWidget( XmppAccount* account = 0, QWidget *parent = 0 );
public:
explicit XmppConfigWidget( XmppAccount* account = 0, QWidget* parent = 0 );
virtual ~XmppConfigWidget();
void saveConfig();
virtual void checkForErrors();
signals:
signals:
void dataError( bool exists );
private slots:
private slots:
void onCheckJidExists( const QString& jid );
void launchExternalConfigDialog();
private:
Ui::XmppConfigWidget *m_ui;
XmppAccount *m_account;
private:
Ui::XmppConfigWidget* m_ui;
XmppAccount* m_account;
bool m_serverWasEditedByUser;

View File

@@ -27,7 +27,7 @@
// Forward Declarations breaking QSharedPointer
#if QT_VERSION < QT_VERSION_CHECK( 5, 0, 0 )
#include "Source.h"
#include "Source.h"
#endif
@@ -63,7 +63,9 @@ Tomahawk::InfoSystem::XmppInfoPlugin::init()
}
if ( m_sipPlugin.isNull() )
{
return;
}
connect( this, SIGNAL( publishTune( QUrl, Tomahawk::InfoSystem::InfoStringHash ) ), m_sipPlugin.data(), SLOT( publishTune( QUrl, Tomahawk::InfoSystem::InfoStringHash ) ), Qt::QueuedConnection );
}
@@ -95,7 +97,7 @@ Tomahawk::InfoSystem::XmppInfoPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushDa
void
Tomahawk::InfoSystem::XmppInfoPlugin::audioStarted( const Tomahawk::InfoSystem::PushInfoPair &pushInfoPair )
Tomahawk::InfoSystem::XmppInfoPlugin::audioStarted( const Tomahawk::InfoSystem::PushInfoPair& pushInfoPair )
{
if ( !pushInfoPair.second.canConvert< QVariantMap >() )
{
@@ -120,9 +122,13 @@ Tomahawk::InfoSystem::XmppInfoPlugin::audioStarted( const Tomahawk::InfoSystem::
QUrl url;
if ( pushInfoPair.first.contains( "shorturl" ) )
{
url = pushInfoPair.first[ "shorturl" ].toUrl();
}
else
{
url = GlobalActionManager::instance()->openLink( info.value( "title" ), info.value( "artist" ), info.value( "album" ) );
}
emit publishTune( url, info );
}
@@ -142,14 +148,14 @@ Tomahawk::InfoSystem::XmppInfoPlugin::audioStopped()
void
Tomahawk::InfoSystem::XmppInfoPlugin::getInfo(Tomahawk::InfoSystem::InfoRequestData requestData)
Tomahawk::InfoSystem::XmppInfoPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
{
Q_UNUSED( requestData );
}
void
Tomahawk::InfoSystem::XmppInfoPlugin::notInCacheSlot(const Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData)
Tomahawk::InfoSystem::XmppInfoPlugin::notInCacheSlot( const Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
{
Q_UNUSED( criteria );
Q_UNUSED( requestData );

View File

@@ -26,40 +26,42 @@
class XmppSipPlugin;
namespace Tomahawk {
namespace Tomahawk
{
namespace InfoSystem {
namespace InfoSystem
{
class XmppInfoPlugin : public InfoPlugin
{
Q_OBJECT
class XmppInfoPlugin : public InfoPlugin
{
Q_OBJECT
public:
XmppInfoPlugin(XmppSipPlugin* parent);
virtual ~XmppInfoPlugin();
public:
XmppInfoPlugin( XmppSipPlugin* parent );
virtual ~XmppInfoPlugin();
signals:
void publishTune( QUrl url, Tomahawk::InfoSystem::InfoStringHash trackInfo );
signals:
void publishTune( QUrl url, Tomahawk::InfoSystem::InfoStringHash trackInfo );
public slots:
void notInCacheSlot( const Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
public slots:
void notInCacheSlot( const Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
protected slots:
void init();
void pushInfo( Tomahawk::InfoSystem::InfoPushData pushData );
void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
protected slots:
void init();
void pushInfo( Tomahawk::InfoSystem::InfoPushData pushData );
void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
private slots:
void audioStarted( const Tomahawk::InfoSystem::PushInfoPair& pushInfoPair );
void audioStopped();
void audioPaused();
private slots:
void audioStarted( const Tomahawk::InfoSystem::PushInfoPair& pushInfoPair );
void audioStopped();
void audioPaused();
private:
QPointer< XmppSipPlugin > m_sipPlugin;
QTimer m_pauseTimer;
};
private:
QPointer< XmppSipPlugin > m_sipPlugin;
QTimer m_pauseTimer;
};
}
}
}

View File

@@ -63,7 +63,7 @@ AvatarManager::fetchVCard( const QString& jid )
{
Jreen::IQ iq( Jreen::IQ::Get, jid );
iq.addExtension( new Jreen::VCard() );
Jreen::IQReply *reply = m_client->send( iq );
Jreen::IQReply* reply = m_client->send( iq );
connect( reply, SIGNAL( received( Jreen::IQ ) ), SLOT( onNewIq( Jreen::IQ ) ) );
}
@@ -80,19 +80,21 @@ AvatarManager::onNewPresence( const Jreen::Presence& presence )
Jreen::VCardUpdate::Ptr update = presence.payload<Jreen::VCardUpdate>();
if ( update )
{
// qDebug() << "vcard: found update for" << presence.from().full();
// qDebug() << "vcard: found update for" << presence.from().full();
if ( !isCached( update->photoHash() ) )
{
// qDebug() << presence.from().full() << "vcard: photo not cached, starting request..." << update->photoHash();
// qDebug() << presence.from().full() << "vcard: photo not cached, starting request..." << update->photoHash();
fetchVCard( presence.from().bare() );
}
else
{
// qDebug() << presence.from().full() << "vcard: photo already cached no request necessary " << update->photoHash();
// qDebug() << presence.from().full() << "vcard: photo already cached no request necessary " << update->photoHash();
m_JidsAvatarHashes.insert( update->photoHash(), presence.from().bare() );
if ( !this->avatar( presence.from().bare() ).isNull() )
{
emit newAvatar( presence.from().bare() );
}
}
}
else
@@ -110,20 +112,22 @@ AvatarManager::onNewIq( const Jreen::IQ& iq )
if ( vcard )
{
iq.accept();
// qDebug() << Q_FUNC_INFO << "Got vcard from " << iq.from().full();
// qDebug() << Q_FUNC_INFO << "Got vcard from " << iq.from().full();
QString id = iq.from().full();
QString avatarHash;
const Jreen::VCard::Photo &photo = vcard->photo();
const Jreen::VCard::Photo& photo = vcard->photo();
if ( !photo.data().isEmpty() )
{
// qDebug() << "vcard: got photo data" << id;
// qDebug() << "vcard: got photo data" << id;
avatarHash = QCryptographicHash::hash( photo.data(), QCryptographicHash::Sha1 ).toHex();
if ( !m_cacheDir.exists() )
{
m_cacheDir.mkpath( avatarDir( avatarHash ).absolutePath() );
}
QFile file( avatarPath( avatarHash ) );
if ( file.open( QIODevice::WriteOnly ) )
@@ -202,5 +206,5 @@ AvatarManager::isCached( const QString& avatarHash ) const
void
AvatarManager::onNewAvatar( const QString& /* jid */ )
{
// qDebug() << Q_FUNC_INFO << "Found new Avatar..." << jid;
// qDebug() << Q_FUNC_INFO << "Found new Avatar..." << jid;
}

View File

@@ -29,24 +29,24 @@
class ACCOUNTDLLEXPORT AvatarManager : public QObject
{
Q_OBJECT
Q_OBJECT
public:
AvatarManager(Jreen::Client* client);
public:
AvatarManager( Jreen::Client* client );
virtual ~AvatarManager();
QPixmap avatar(const QString& jid) const;
QPixmap avatar( const QString& jid ) const;
signals:
signals:
void newAvatar( const QString& jid );
private slots:
private slots:
void onNewPresence( const Jreen::Presence& presence );
void onNewIq(const Jreen::IQ& iq);
void onNewIq( const Jreen::IQ& iq );
void onNewConnection();
void onNewAvatar( const QString& jid );
private:
private:
void fetchVCard( const QString& jid );
QString avatarHash( const QString& jid ) const;
QString avatarPath( const QString& avatarHash ) const;

View File

@@ -27,7 +27,7 @@ TomahawkXmppMessage::TomahawkXmppMessage()
{
}
TomahawkXmppMessage::TomahawkXmppMessage( const QList<SipInfo> &sipInfos )
TomahawkXmppMessage::TomahawkXmppMessage( const QList<SipInfo>& sipInfos )
: m_sipInfos( sipInfos )
{
}
@@ -47,16 +47,24 @@ const QString
TomahawkXmppMessage::key() const
{
if ( m_sipInfos.isEmpty() )
{
return QString();
}
else
{
return m_sipInfos.first().key();
}
}
const QString
TomahawkXmppMessage::uniqname() const
{
if ( m_sipInfos.isEmpty() )
{
return QString();
}
else
{
return m_sipInfos.first().nodeId();
}
}

View File

@@ -31,29 +31,29 @@
class ACCOUNTDLLEXPORT TomahawkXmppMessage : public Jreen::Payload
{
J_PAYLOAD(TomahawkXmppMessage)
public:
TomahawkXmppMessage();
TomahawkXmppMessage(const QList<SipInfo>& sipInfos);
~TomahawkXmppMessage();
J_PAYLOAD( TomahawkXmppMessage )
public:
TomahawkXmppMessage();
TomahawkXmppMessage( const QList<SipInfo>& sipInfos );
~TomahawkXmppMessage();
/**
* The SipInfo objects that are wrapped in this XmppMessage
*/
const QList<SipInfo> sipInfos() const;
/**
* The SipInfo objects that are wrapped in this XmppMessage
*/
const QList<SipInfo> sipInfos() const;
/**
* The name of the peer contained in this message
*/
const QString key() const;
/**
* The name of the peer contained in this message
*/
const QString key() const;
/**
* The name of the peer contained in this message
*/
const QString uniqname() const;
/**
* The name of the peer contained in this message
*/
const QString uniqname() const;
private:
QList<SipInfo> m_sipInfos;
private:
QList<SipInfo> m_sipInfos;
};
#endif // ENTITYTIME_H

View File

@@ -43,18 +43,18 @@ TomahawkXmppMessageFactory::~TomahawkXmppMessageFactory()
QStringList TomahawkXmppMessageFactory::features() const
{
return QStringList(TOMAHAWK_SIP_MESSAGE_NS);
return QStringList( TOMAHAWK_SIP_MESSAGE_NS );
}
bool TomahawkXmppMessageFactory::canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
bool TomahawkXmppMessageFactory::canParse( const QStringRef& name, const QStringRef& uri, const QXmlStreamAttributes& attributes )
{
Q_UNUSED(uri);
Q_UNUSED(attributes);
return name == QLatin1String("tomahawk") && uri == TOMAHAWK_SIP_MESSAGE_NS;
Q_UNUSED( uri );
Q_UNUSED( attributes );
return name == QLatin1String( "tomahawk" ) && uri == TOMAHAWK_SIP_MESSAGE_NS;
}
void TomahawkXmppMessageFactory::handleStartElement(const QStringRef &name, const QStringRef &uri,
const QXmlStreamAttributes &attributes)
void TomahawkXmppMessageFactory::handleStartElement( const QStringRef& name, const QStringRef& uri,
const QXmlStreamAttributes& attributes )
{
m_depth++;
if ( m_depth == 1 )
@@ -73,7 +73,7 @@ void TomahawkXmppMessageFactory::handleStartElement(const QStringRef &name, cons
m_key = attributes.value( QLatin1String( "pwd" ) ).toString();
}
}
else if(m_depth == 3)
else if( m_depth == 3 )
{
if ( name == QLatin1String( "candidate" ) )
{
@@ -88,14 +88,16 @@ void TomahawkXmppMessageFactory::handleStartElement(const QStringRef &name, cons
m_sipInfos.append( info );
}
}
Q_UNUSED(uri);
Q_UNUSED(attributes);
Q_UNUSED( uri );
Q_UNUSED( attributes );
}
void TomahawkXmppMessageFactory::handleEndElement(const QStringRef &name, const QStringRef &uri)
void TomahawkXmppMessageFactory::handleEndElement( const QStringRef& name, const QStringRef& uri )
{
if ( m_depth == 3 )
{
m_state = AtTransport;
}
else if ( m_depth == 2 )
{
m_state = AtNowhere;
@@ -110,12 +112,12 @@ void TomahawkXmppMessageFactory::handleEndElement(const QStringRef &name, const
m_sipInfos.append( info );
}
}
Q_UNUSED(name);
Q_UNUSED(uri);
Q_UNUSED( name );
Q_UNUSED( uri );
m_depth--;
}
void TomahawkXmppMessageFactory::handleCharacterData(const QStringRef &text)
void TomahawkXmppMessageFactory::handleCharacterData( const QStringRef& text )
{
/*if (m_state == AtUtc) {
//m_utc = Util::fromStamp(text.toString());
@@ -125,12 +127,12 @@ void TomahawkXmppMessageFactory::handleCharacterData(const QStringRef &text)
//QTime delta = QTime::fromString(str.mid(1), QLatin1String("hh:mm"));
//m_tzo = multiple * (delta.hour() * 60 + delta.minute());
}*/
Q_UNUSED(text);
Q_UNUSED( text );
}
void TomahawkXmppMessageFactory::serialize(Payload *extension, QXmlStreamWriter *writer)
void TomahawkXmppMessageFactory::serialize( Payload* extension, QXmlStreamWriter* writer )
{
TomahawkXmppMessage *sipMessage = se_cast<TomahawkXmppMessage*>(extension);
TomahawkXmppMessage* sipMessage = se_cast<TomahawkXmppMessage*>( extension );
writer->writeStartElement( QLatin1String( "tomahawk" ) );
writer->writeDefaultNamespace( TOMAHAWK_SIP_MESSAGE_NS );
@@ -160,7 +162,9 @@ void TomahawkXmppMessageFactory::serialize(Payload *extension, QXmlStreamWriter
foreach ( SipInfo info, sipInfos )
{
if ( info.isVisible() )
{
serializeSipInfo( info, writer );
}
}
if ( lastInfo.isValid() )
@@ -183,7 +187,7 @@ TomahawkXmppMessageFactory::createPayload()
}
void
TomahawkXmppMessageFactory::serializeSipInfo(SipInfo &info, QXmlStreamWriter *writer)
TomahawkXmppMessageFactory::serializeSipInfo( SipInfo& info, QXmlStreamWriter* writer )
{
if ( info.isVisible() )
{

View File

@@ -29,18 +29,18 @@
class ACCOUNTDLLEXPORT TomahawkXmppMessageFactory : public Jreen::PayloadFactory<TomahawkXmppMessage>
{
public:
public:
TomahawkXmppMessageFactory();
virtual ~TomahawkXmppMessageFactory();
QStringList features() const;
bool canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
void handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
void handleEndElement(const QStringRef &name, const QStringRef &uri);
void handleCharacterData(const QStringRef &text);
void serialize(Jreen::Payload *extension, QXmlStreamWriter *writer);
bool canParse( const QStringRef& name, const QStringRef& uri, const QXmlStreamAttributes& attributes );
void handleStartElement( const QStringRef& name, const QStringRef& uri, const QXmlStreamAttributes& attributes );
void handleEndElement( const QStringRef& name, const QStringRef& uri );
void handleCharacterData( const QStringRef& text );
void serialize( Jreen::Payload* extension, QXmlStreamWriter* writer );
Jreen::Payload::Ptr createPayload();
private:
void serializeSipInfo(SipInfo& info, QXmlStreamWriter *writer);
private:
void serializeSipInfo( SipInfo& info, QXmlStreamWriter* writer );
enum State { AtNowhere, AtTransport, AtCandidate } m_state;

View File

@@ -34,330 +34,372 @@
using namespace Jreen;
XmlConsole::XmlConsole(Client* client, QWidget *parent) :
QWidget(parent),
m_ui(new Ui::XmlConsole),
m_client(client), m_filter(0x1f)
XmlConsole::XmlConsole( Client* client, QWidget* parent ) :
QWidget( parent ),
m_ui( new Ui::XmlConsole ),
m_client( client ), m_filter( 0x1f )
{
m_ui->setupUi(this);
m_ui->setupUi( this );
m_client->addXmlStreamHandler(this);
m_client->addXmlStreamHandler( this );
QPalette pal = palette();
pal.setColor(QPalette::Base, Qt::black);
pal.setColor(QPalette::Text, Qt::white);
m_ui->xmlBrowser->viewport()->setPalette(pal);
QTextDocument *doc = m_ui->xmlBrowser->document();
doc->setDocumentLayout(new QPlainTextDocumentLayout(doc));
doc->clear();
QPalette pal = palette();
pal.setColor( QPalette::Base, Qt::black );
pal.setColor( QPalette::Text, Qt::white );
m_ui->xmlBrowser->viewport()->setPalette( pal );
QTextDocument* doc = m_ui->xmlBrowser->document();
doc->setDocumentLayout( new QPlainTextDocumentLayout( doc ) );
doc->clear();
QTextFrameFormat format = doc->rootFrame()->frameFormat();
format.setBackground(QColor(Qt::black));
format.setMargin(0);
doc->rootFrame()->setFrameFormat(format);
QMenu *menu = new QMenu(m_ui->filterButton);
menu->setSeparatorsCollapsible(false);
menu->addSeparator()->setText(tr("Filter"));
QActionGroup *group = new QActionGroup(menu);
QAction *disabled = group->addAction(menu->addAction(tr("Disabled")));
disabled->setCheckable(true);
disabled->setData(Disabled);
QAction *jid = group->addAction(menu->addAction(tr("By JID")));
jid->setCheckable(true);
jid->setData(ByJid);
QAction *xmlns = group->addAction(menu->addAction(tr("By namespace uri")));
xmlns->setCheckable(true);
xmlns->setData(ByXmlns);
QAction *attrb = group->addAction(menu->addAction(tr("By all attributes")));
attrb->setCheckable(true);
attrb->setData(ByAllAttributes);
disabled->setChecked(true);
connect(group, SIGNAL(triggered(QAction*)), this, SLOT(onActionGroupTriggered(QAction*)));
menu->addSeparator()->setText(tr("Visible stanzas"));
group = new QActionGroup(menu);
group->setExclusive(false);
QAction *iq = group->addAction(menu->addAction(tr("Information query")));
iq->setCheckable(true);
iq->setData(XmlNode::Iq);
iq->setChecked(true);
QAction *message = group->addAction(menu->addAction(tr("Message")));
message->setCheckable(true);
message->setData(XmlNode::Message);
message->setChecked(true);
QAction *presence = group->addAction(menu->addAction(tr("Presence")));
presence->setCheckable(true);
presence->setData(XmlNode::Presence);
presence->setChecked(true);
QAction *custom = group->addAction(menu->addAction(tr("Custom")));
custom->setCheckable(true);
custom->setData(XmlNode::Custom);
custom->setChecked(true);
connect(group, SIGNAL(triggered(QAction*)), this, SLOT(onActionGroupTriggered(QAction*)));
m_ui->filterButton->setMenu(menu);
m_stackBracketsColor = QColor(0x666666);
m_stackIncoming.bodyColor = QColor(0xbb66bb);
m_stackIncoming.tagColor = QColor(0x006666);
m_stackIncoming.attributeColor = QColor(0x009933);
m_stackIncoming.paramColor = QColor(0xcc0000);
m_stackOutgoing.bodyColor = QColor(0x999999);
m_stackOutgoing.tagColor = QColor(0x22aa22);
m_stackOutgoing.attributeColor = QColor(0xffff33);
m_stackOutgoing.paramColor = QColor(0xdd8811);
QTextFrameFormat format = doc->rootFrame()->frameFormat();
format.setBackground( QColor( Qt::black ) );
format.setMargin( 0 );
doc->rootFrame()->setFrameFormat( format );
QMenu* menu = new QMenu( m_ui->filterButton );
menu->setSeparatorsCollapsible( false );
menu->addSeparator()->setText( tr( "Filter" ) );
QActionGroup* group = new QActionGroup( menu );
QAction* disabled = group->addAction( menu->addAction( tr( "Disabled" ) ) );
disabled->setCheckable( true );
disabled->setData( Disabled );
QAction* jid = group->addAction( menu->addAction( tr( "By JID" ) ) );
jid->setCheckable( true );
jid->setData( ByJid );
QAction* xmlns = group->addAction( menu->addAction( tr( "By namespace uri" ) ) );
xmlns->setCheckable( true );
xmlns->setData( ByXmlns );
QAction* attrb = group->addAction( menu->addAction( tr( "By all attributes" ) ) );
attrb->setCheckable( true );
attrb->setData( ByAllAttributes );
disabled->setChecked( true );
connect( group, SIGNAL( triggered( QAction* ) ), this, SLOT( onActionGroupTriggered( QAction* ) ) );
menu->addSeparator()->setText( tr( "Visible stanzas" ) );
group = new QActionGroup( menu );
group->setExclusive( false );
QAction* iq = group->addAction( menu->addAction( tr( "Information query" ) ) );
iq->setCheckable( true );
iq->setData( XmlNode::Iq );
iq->setChecked( true );
QAction* message = group->addAction( menu->addAction( tr( "Message" ) ) );
message->setCheckable( true );
message->setData( XmlNode::Message );
message->setChecked( true );
QAction* presence = group->addAction( menu->addAction( tr( "Presence" ) ) );
presence->setCheckable( true );
presence->setData( XmlNode::Presence );
presence->setChecked( true );
QAction* custom = group->addAction( menu->addAction( tr( "Custom" ) ) );
custom->setCheckable( true );
custom->setData( XmlNode::Custom );
custom->setChecked( true );
connect( group, SIGNAL( triggered( QAction* ) ), this, SLOT( onActionGroupTriggered( QAction* ) ) );
m_ui->filterButton->setMenu( menu );
m_stackBracketsColor = QColor( 0x666666 );
m_stackIncoming.bodyColor = QColor( 0xbb66bb );
m_stackIncoming.tagColor = QColor( 0x006666 );
m_stackIncoming.attributeColor = QColor( 0x009933 );
m_stackIncoming.paramColor = QColor( 0xcc0000 );
m_stackOutgoing.bodyColor = QColor( 0x999999 );
m_stackOutgoing.tagColor = QColor( 0x22aa22 );
m_stackOutgoing.attributeColor = QColor( 0xffff33 );
m_stackOutgoing.paramColor = QColor( 0xdd8811 );
QAction *action = new QAction(tr("Close"),this);
connect(action, SIGNAL(triggered()), SLOT(close()));
addAction(action);
QAction* action = new QAction( tr( "Close" ), this );
connect( action, SIGNAL( triggered() ), SLOT( close() ) );
addAction( action );
}
XmlConsole::~XmlConsole()
{
delete m_ui;
delete m_ui;
}
void XmlConsole::handleStreamBegin()
{
m_stackIncoming.reader.clear();
m_stackOutgoing.reader.clear();
m_stackIncoming.depth = 0;
m_stackOutgoing.depth = 0;
qDeleteAll(m_stackIncoming.tokens);
qDeleteAll(m_stackOutgoing.tokens);
m_stackIncoming.tokens.clear();
m_stackOutgoing.tokens.clear();
m_stackIncoming.reader.clear();
m_stackOutgoing.reader.clear();
m_stackIncoming.depth = 0;
m_stackOutgoing.depth = 0;
qDeleteAll( m_stackIncoming.tokens );
qDeleteAll( m_stackOutgoing.tokens );
m_stackIncoming.tokens.clear();
m_stackOutgoing.tokens.clear();
}
void XmlConsole::handleStreamEnd()
{
m_stackIncoming.reader.clear();
m_stackOutgoing.reader.clear();
m_stackIncoming.depth = 0;
m_stackOutgoing.depth = 0;
qDeleteAll(m_stackIncoming.tokens);
qDeleteAll(m_stackOutgoing.tokens);
m_stackIncoming.tokens.clear();
m_stackOutgoing.tokens.clear();
m_stackIncoming.reader.clear();
m_stackOutgoing.reader.clear();
m_stackIncoming.depth = 0;
m_stackOutgoing.depth = 0;
qDeleteAll( m_stackIncoming.tokens );
qDeleteAll( m_stackOutgoing.tokens );
m_stackIncoming.tokens.clear();
m_stackOutgoing.tokens.clear();
}
void XmlConsole::handleIncomingData(const char *data, qint64 size)
void XmlConsole::handleIncomingData( const char* data, qint64 size )
{
stackProcess(QByteArray::fromRawData(data, size), true);
stackProcess( QByteArray::fromRawData( data, size ), true );
}
void XmlConsole::handleOutgoingData(const char *data, qint64 size)
void XmlConsole::handleOutgoingData( const char* data, qint64 size )
{
stackProcess(QByteArray::fromRawData(data, size), false);
stackProcess( QByteArray::fromRawData( data, size ), false );
}
QString generate_stacked_space(int depth)
QString generate_stacked_space( int depth )
{
return QString(depth * 2, QLatin1Char(' '));
return QString( depth * 2, QLatin1Char( ' ' ) );
}
void XmlConsole::stackProcess(const QByteArray &data, bool incoming)
void XmlConsole::stackProcess( const QByteArray& data, bool incoming )
{
StackEnvironment *d = &(incoming ? m_stackIncoming : m_stackOutgoing);
d->reader.addData(data);
StackToken *token;
// debug() << incoming << data;
// debug() << "==================================================================";
while (d->reader.readNext() > QXmlStreamReader::Invalid) {
// qDebug() << incoming << d->reader.tokenString();
switch(d->reader.tokenType()) {
case QXmlStreamReader::StartElement:
// dbg << d->reader.name().toString() << d->depth
// << d->reader.attributes().value(QLatin1String("from")).toString();
d->depth++;
if (d->depth > 1) {
if (!d->tokens.isEmpty() && d->tokens.last()->type == QXmlStreamReader::Characters)
delete d->tokens.takeLast();
d->tokens << new StackToken(d->reader);
}
break;
case QXmlStreamReader::EndElement:
// dbg << d->reader.name().toString() << d->depth;
if (d->tokens.isEmpty())
break;
token = d->tokens.last();
if (token->type == QXmlStreamReader::StartElement && !token->startTag.empty)
token->startTag.empty = true;
else if (d->depth > 1)
d->tokens << new StackToken(d->reader);
if (d->depth == 2) {
QTextCursor cursor(m_ui->xmlBrowser->document());
cursor.movePosition(QTextCursor::End);
cursor.beginEditBlock();
QTextCharFormat zeroFormat = cursor.charFormat();
zeroFormat.setForeground(QColor(Qt::white));
QTextCharFormat bodyFormat = zeroFormat;
bodyFormat.setForeground(d->bodyColor);
QTextCharFormat tagFormat = zeroFormat;
tagFormat.setForeground(d->tagColor);
QTextCharFormat attributeFormat = zeroFormat;
attributeFormat.setForeground(d->attributeColor);
QTextCharFormat paramsFormat = zeroFormat;
paramsFormat.setForeground(d->paramColor);
QTextCharFormat bracketFormat = zeroFormat;
bracketFormat.setForeground(m_stackBracketsColor);
QString singleSpace = QLatin1String(" ");
cursor.insertBlock();
int depth = 0;
QString currentXmlns;
QXmlStreamReader::TokenType lastType = QXmlStreamReader::StartElement;
for (int i = 0; i < d->tokens.size(); i++) {
token = d->tokens.at(i);
if (token->type == QXmlStreamReader::StartElement) {
QString space = generate_stacked_space(depth);
cursor.insertText(QLatin1String("\n"));
cursor.insertText(space);
cursor.insertText(QLatin1String("<"), bracketFormat);
cursor.insertText(token->startTag.name->toString(), tagFormat);
const QStringRef &xmlns = *token->startTag.xmlns;
if (i == 0 || xmlns != currentXmlns) {
currentXmlns = xmlns.toString();
cursor.insertText(singleSpace);
cursor.insertText(QLatin1String("xmlns"), attributeFormat);
cursor.insertText(QLatin1String("="), zeroFormat);
cursor.insertText(QLatin1String("'"), paramsFormat);
cursor.insertText(currentXmlns, paramsFormat);
cursor.insertText(QLatin1String("'"), paramsFormat);
}
QXmlStreamAttributes *attributes = token->startTag.attributes;
for (int j = 0; j < attributes->count(); j++) {
const QXmlStreamAttribute &attr = attributes->at(j);
cursor.insertText(singleSpace);
cursor.insertText(attr.name().toString(), attributeFormat);
cursor.insertText(QLatin1String("="), zeroFormat);
cursor.insertText(QLatin1String("'"), paramsFormat);
cursor.insertText(attr.value().toString(), paramsFormat);
cursor.insertText(QLatin1String("'"), paramsFormat);
}
if (token->startTag.empty) {
cursor.insertText(QLatin1String("/>"), bracketFormat);
} else {
cursor.insertText(QLatin1String(">"), bracketFormat);
depth++;
}
} else if (token->type == QXmlStreamReader::EndElement) {
if (lastType == QXmlStreamReader::EndElement) {
QString space = generate_stacked_space(depth - 1);
cursor.insertText(QLatin1String("\n"));
cursor.insertText(space);
}
cursor.insertText(QLatin1String("</"), bracketFormat);
cursor.insertText(token->endTag.name->toString(), tagFormat);
cursor.insertText(QLatin1String(">"), bracketFormat);
depth--;
} else if (token->type == QXmlStreamReader::Characters) {
cursor.setCharFormat(bodyFormat);
QString text = token->charachters.text->toString();
if (text.contains(QLatin1Char('\n'))) {
QString space = generate_stacked_space(depth);
space.prepend(QLatin1Char('\n'));
QStringList lines = text.split(QLatin1Char('\n'));
for (int j = 0; j < lines.size(); j++) {
cursor.insertText(space);
cursor.insertText(lines.at(j));
}
space.chop(1);
cursor.insertText(space);
} else {
cursor.insertText(text);
}
}
lastType = token->type;
if (lastType == QXmlStreamReader::StartElement && token->startTag.empty)
lastType = QXmlStreamReader::EndElement;
delete token;
}
cursor.endEditBlock();
d->tokens.clear();
}
d->depth--;
break;
case QXmlStreamReader::Characters:
token = d->tokens.isEmpty() ? 0 : d->tokens.last();
if (token && token->type == QXmlStreamReader::StartElement && !token->startTag.empty) {
if (*token->startTag.name == QLatin1String("auth")
&& *token->startTag.xmlns == QLatin1String("urn:ietf:params:xml:ns:xmpp-sasl")) {
d->tokens << new StackToken(QLatin1String("<<Private data>>"));
} else {
d->tokens << new StackToken(d->reader);
}
}
break;
default:
break;
}
}
// qDebug() << d->reader.tokenString();
// if (d->reader.tokenType() == QXmlStreamReader::Invalid)
// dbg << d->reader.error() << d->reader.errorString();
if (!incoming && d->depth > 1) {
qFatal("outgoing depth %d on\n\"%s\"", d->depth,
qPrintable(QString::fromUtf8(data, data.size())));
}
StackEnvironment* d = &( incoming ? m_stackIncoming : m_stackOutgoing );
d->reader.addData( data );
StackToken* token;
// debug() << incoming << data;
// debug() << "==================================================================";
while ( d->reader.readNext() > QXmlStreamReader::Invalid )
{
// qDebug() << incoming << d->reader.tokenString();
switch( d->reader.tokenType() )
{
case QXmlStreamReader::StartElement:
// dbg << d->reader.name().toString() << d->depth
// << d->reader.attributes().value(QLatin1String("from")).toString();
d->depth++;
if ( d->depth > 1 )
{
if ( !d->tokens.isEmpty() && d->tokens.last()->type == QXmlStreamReader::Characters )
{
delete d->tokens.takeLast();
}
d->tokens << new StackToken( d->reader );
}
break;
case QXmlStreamReader::EndElement:
// dbg << d->reader.name().toString() << d->depth;
if ( d->tokens.isEmpty() )
{
break;
}
token = d->tokens.last();
if ( token->type == QXmlStreamReader::StartElement && !token->startTag.empty )
{
token->startTag.empty = true;
}
else if ( d->depth > 1 )
{
d->tokens << new StackToken( d->reader );
}
if ( d->depth == 2 )
{
QTextCursor cursor( m_ui->xmlBrowser->document() );
cursor.movePosition( QTextCursor::End );
cursor.beginEditBlock();
QTextCharFormat zeroFormat = cursor.charFormat();
zeroFormat.setForeground( QColor( Qt::white ) );
QTextCharFormat bodyFormat = zeroFormat;
bodyFormat.setForeground( d->bodyColor );
QTextCharFormat tagFormat = zeroFormat;
tagFormat.setForeground( d->tagColor );
QTextCharFormat attributeFormat = zeroFormat;
attributeFormat.setForeground( d->attributeColor );
QTextCharFormat paramsFormat = zeroFormat;
paramsFormat.setForeground( d->paramColor );
QTextCharFormat bracketFormat = zeroFormat;
bracketFormat.setForeground( m_stackBracketsColor );
QString singleSpace = QLatin1String( " " );
cursor.insertBlock();
int depth = 0;
QString currentXmlns;
QXmlStreamReader::TokenType lastType = QXmlStreamReader::StartElement;
for ( int i = 0; i < d->tokens.size(); i++ )
{
token = d->tokens.at( i );
if ( token->type == QXmlStreamReader::StartElement )
{
QString space = generate_stacked_space( depth );
cursor.insertText( QLatin1String( "\n" ) );
cursor.insertText( space );
cursor.insertText( QLatin1String( "<" ), bracketFormat );
cursor.insertText( token->startTag.name->toString(), tagFormat );
const QStringRef& xmlns = *token->startTag.xmlns;
if ( i == 0 || xmlns != currentXmlns )
{
currentXmlns = xmlns.toString();
cursor.insertText( singleSpace );
cursor.insertText( QLatin1String( "xmlns" ), attributeFormat );
cursor.insertText( QLatin1String( "=" ), zeroFormat );
cursor.insertText( QLatin1String( "'" ), paramsFormat );
cursor.insertText( currentXmlns, paramsFormat );
cursor.insertText( QLatin1String( "'" ), paramsFormat );
}
QXmlStreamAttributes* attributes = token->startTag.attributes;
for ( int j = 0; j < attributes->count(); j++ )
{
const QXmlStreamAttribute& attr = attributes->at( j );
cursor.insertText( singleSpace );
cursor.insertText( attr.name().toString(), attributeFormat );
cursor.insertText( QLatin1String( "=" ), zeroFormat );
cursor.insertText( QLatin1String( "'" ), paramsFormat );
cursor.insertText( attr.value().toString(), paramsFormat );
cursor.insertText( QLatin1String( "'" ), paramsFormat );
}
if ( token->startTag.empty )
{
cursor.insertText( QLatin1String( "/>" ), bracketFormat );
}
else
{
cursor.insertText( QLatin1String( ">" ), bracketFormat );
depth++;
}
}
else if ( token->type == QXmlStreamReader::EndElement )
{
if ( lastType == QXmlStreamReader::EndElement )
{
QString space = generate_stacked_space( depth - 1 );
cursor.insertText( QLatin1String( "\n" ) );
cursor.insertText( space );
}
cursor.insertText( QLatin1String( "</" ), bracketFormat );
cursor.insertText( token->endTag.name->toString(), tagFormat );
cursor.insertText( QLatin1String( ">" ), bracketFormat );
depth--;
}
else if ( token->type == QXmlStreamReader::Characters )
{
cursor.setCharFormat( bodyFormat );
QString text = token->charachters.text->toString();
if ( text.contains( QLatin1Char( '\n' ) ) )
{
QString space = generate_stacked_space( depth );
space.prepend( QLatin1Char( '\n' ) );
QStringList lines = text.split( QLatin1Char( '\n' ) );
for ( int j = 0; j < lines.size(); j++ )
{
cursor.insertText( space );
cursor.insertText( lines.at( j ) );
}
space.chop( 1 );
cursor.insertText( space );
}
else
{
cursor.insertText( text );
}
}
lastType = token->type;
if ( lastType == QXmlStreamReader::StartElement && token->startTag.empty )
{
lastType = QXmlStreamReader::EndElement;
}
delete token;
}
cursor.endEditBlock();
d->tokens.clear();
}
d->depth--;
break;
case QXmlStreamReader::Characters:
token = d->tokens.isEmpty() ? 0 : d->tokens.last();
if ( token && token->type == QXmlStreamReader::StartElement && !token->startTag.empty )
{
if ( *token->startTag.name == QLatin1String( "auth" )
&& *token->startTag.xmlns == QLatin1String( "urn:ietf:params:xml:ns:xmpp-sasl" ) )
{
d->tokens << new StackToken( QLatin1String( "<<Private data>>" ) );
}
else
{
d->tokens << new StackToken( d->reader );
}
}
break;
default:
break;
}
}
// qDebug() << d->reader.tokenString();
// if (d->reader.tokenType() == QXmlStreamReader::Invalid)
// dbg << d->reader.error() << d->reader.errorString();
if ( !incoming && d->depth > 1 )
{
qFatal( "outgoing depth %d on\n\"%s\"", d->depth,
qPrintable( QString::fromUtf8( data, data.size() ) ) );
}
}
void XmlConsole::changeEvent(QEvent *e)
void XmlConsole::changeEvent( QEvent* e )
{
QWidget::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
m_ui->retranslateUi(this);
break;
default:
break;
}
QWidget::changeEvent( e );
switch ( e->type() )
{
case QEvent::LanguageChange:
m_ui->retranslateUi( this );
break;
default:
break;
}
}
void XmlConsole::onActionGroupTriggered(QAction *action)
void XmlConsole::onActionGroupTriggered( QAction* action )
{
int type = action->data().toInt();
if (type >= 0x10) {
m_filter = (m_filter & 0xf) | type;
m_ui->lineEdit->setEnabled(type != 0x10);
} else {
m_filter = m_filter ^ type;
}
on_lineEdit_textChanged(m_ui->lineEdit->text());
int type = action->data().toInt();
if ( type >= 0x10 )
{
m_filter = ( m_filter & 0xf ) | type;
m_ui->lineEdit->setEnabled( type != 0x10 );
}
else
{
m_filter = m_filter ^ type;
}
on_lineEdit_textChanged( m_ui->lineEdit->text() );
}
void XmlConsole::on_lineEdit_textChanged(const QString &text)
void XmlConsole::on_lineEdit_textChanged( const QString& text )
{
int filterType = m_filter & 0xf0;
JID filterJid = (filterType == ByJid) ? text : QString();
for (int i = 0; i < m_nodes.size(); i++) {
XmlNode &node = m_nodes[i];
bool ok = true;
switch (filterType) {
case ByXmlns:
ok = node.xmlns.contains(text);
break;
case ByJid:
ok = node.jid.full() == filterJid.full() || node.jid.bare() == filterJid.full();
break;
case ByAllAttributes:
ok = node.attributes.contains(text);
break;
default:
break;
}
ok &= bool(node.type & m_filter);
node.block.setVisible(ok);
node.block.setLineCount(ok ? node.lineCount : 0);
// qDebug() << node.block.lineCount();
}
QAbstractTextDocumentLayout *layout = m_ui->xmlBrowser->document()->documentLayout();
Q_ASSERT(qobject_cast<QPlainTextDocumentLayout*>(layout));
qobject_cast<QPlainTextDocumentLayout*>(layout)->requestUpdate();
int filterType = m_filter & 0xf0;
JID filterJid = ( filterType == ByJid ) ? text : QString();
for ( int i = 0; i < m_nodes.size(); i++ )
{
XmlNode& node = m_nodes[i];
bool ok = true;
switch ( filterType )
{
case ByXmlns:
ok = node.xmlns.contains( text );
break;
case ByJid:
ok = node.jid.full() == filterJid.full() || node.jid.bare() == filterJid.full();
break;
case ByAllAttributes:
ok = node.attributes.contains( text );
break;
default:
break;
}
ok &= bool( node.type & m_filter );
node.block.setVisible( ok );
node.block.setLineCount( ok ? node.lineCount : 0 );
// qDebug() << node.block.lineCount();
}
QAbstractTextDocumentLayout* layout = m_ui->xmlBrowser->document()->documentLayout();
Q_ASSERT( qobject_cast<QPlainTextDocumentLayout*>( layout ) );
qobject_cast<QPlainTextDocumentLayout*>( layout )->requestUpdate();
}
void XmlConsole::on_saveButton_clicked()
{
QString fileName = QFileDialog::getSaveFileName(this, tr("Save XMPP log to file"),
QString(), tr("OpenDocument Format (*.odf);;HTML file (*.html);;Plain text (*.txt)"));
if (!fileName.isEmpty()) {
QTextDocumentWriter writer(fileName);
writer.write(m_ui->xmlBrowser->document());
}
QString fileName = QFileDialog::getSaveFileName( this, tr( "Save XMPP log to file" ),
QString(), tr( "OpenDocument Format (*.odf);;HTML file (*.html);;Plain text (*.txt)" ) );
if ( !fileName.isEmpty() )
{
QTextDocumentWriter writer( fileName );
writer.write( m_ui->xmlBrowser->document() );
}
}

View File

@@ -29,7 +29,8 @@
#include <QDateTime>
#include <QTextBlock>
namespace Ui {
namespace Ui
{
class XmlConsole;
}
@@ -39,148 +40,162 @@ class ACCOUNTDLLEXPORT XmlConsole : public QWidget, public Jreen::XmlStreamHandl
{
Q_OBJECT
public:
XmlConsole(Jreen::Client* client, QWidget *parent = 0);
~XmlConsole();
public:
XmlConsole( Jreen::Client* client, QWidget* parent = 0 );
~XmlConsole();
virtual void handleStreamBegin();
virtual void handleStreamEnd();
virtual void handleIncomingData(const char *data, qint64 size);
virtual void handleOutgoingData(const char *data, qint64 size);
virtual void handleStreamBegin();
virtual void handleStreamEnd();
virtual void handleIncomingData( const char* data, qint64 size );
virtual void handleOutgoingData( const char* data, qint64 size );
protected:
void changeEvent(QEvent *e);
private:
void stackProcess(const QByteArray &data, bool incoming);
protected:
void changeEvent( QEvent* e );
private:
void stackProcess( const QByteArray& data, bool incoming );
struct XmlNode
{
enum Type
{
Iq = 1,
Presence = 2,
Message = 4,
Custom = 8
};
QDateTime time;
Type type;
bool incoming;
QSet<QString> xmlns;
Jreen::JID jid;
QSet<QString> attributes;
QTextBlock block;
int lineCount;
};
enum FilterType
{
Disabled = 0x10,
ByJid = 0x20,
ByXmlns = 0x30,
ByAllAttributes = 0x40
};
struct XmlNode
{
enum Type
{
Iq = 1,
Presence = 2,
Message = 4,
Custom = 8
};
QDateTime time;
Type type;
bool incoming;
QSet<QString> xmlns;
Jreen::JID jid;
QSet<QString> attributes;
QTextBlock block;
int lineCount;
};
enum FilterType
{
Disabled = 0x10,
ByJid = 0x20,
ByXmlns = 0x30,
ByAllAttributes = 0x40
};
enum State
{
WaitingForStanza,
ReadFeatures,
ReadStanza,
ReadCustom
};
enum State
{
WaitingForStanza,
ReadFeatures,
ReadStanza,
ReadCustom
};
struct StackToken
{
StackToken(QXmlStreamReader &reader)
{
type = reader.tokenType();
if (type == QXmlStreamReader::StartElement) {
QStringRef tmp = reader.name();
startTag.namePointer = new QString(*tmp.string());
startTag.name = new QStringRef(startTag.namePointer, tmp.position(), tmp.length());
tmp = reader.namespaceUri();
startTag.xmlnsPointer = new QString(*tmp.string());
startTag.xmlns = new QStringRef(startTag.xmlnsPointer, tmp.position(), tmp.length());
startTag.attributes = new QXmlStreamAttributes(reader.attributes());
startTag.empty = false;
} else if (type == QXmlStreamReader::Characters) {
QStringRef tmp = reader.text();
charachters.textPointer = new QString(*tmp.string());
charachters.text = new QStringRef(charachters.textPointer, tmp.position(), tmp.length());
} else if (type == QXmlStreamReader::EndElement) {
QStringRef tmp = reader.name();
endTag.namePointer = new QString(*tmp.string());
endTag.name = new QStringRef(endTag.namePointer, tmp.position(), tmp.length());
}
}
struct StackToken
{
StackToken( QXmlStreamReader& reader )
{
type = reader.tokenType();
if ( type == QXmlStreamReader::StartElement )
{
QStringRef tmp = reader.name();
startTag.namePointer = new QString( *tmp.string() );
startTag.name = new QStringRef( startTag.namePointer, tmp.position(), tmp.length() );
tmp = reader.namespaceUri();
startTag.xmlnsPointer = new QString( *tmp.string() );
startTag.xmlns = new QStringRef( startTag.xmlnsPointer, tmp.position(), tmp.length() );
startTag.attributes = new QXmlStreamAttributes( reader.attributes() );
startTag.empty = false;
}
else if ( type == QXmlStreamReader::Characters )
{
QStringRef tmp = reader.text();
charachters.textPointer = new QString( *tmp.string() );
charachters.text = new QStringRef( charachters.textPointer, tmp.position(), tmp.length() );
}
else if ( type == QXmlStreamReader::EndElement )
{
QStringRef tmp = reader.name();
endTag.namePointer = new QString( *tmp.string() );
endTag.name = new QStringRef( endTag.namePointer, tmp.position(), tmp.length() );
}
}
StackToken(const QString &name)
{
type = QXmlStreamReader::Characters;
charachters.textPointer = new QString(name);
charachters.text = new QStringRef(charachters.textPointer);
}
StackToken( const QString& name )
{
type = QXmlStreamReader::Characters;
charachters.textPointer = new QString( name );
charachters.text = new QStringRef( charachters.textPointer );
}
~StackToken()
{
if (type == QXmlStreamReader::StartElement) {
delete startTag.namePointer;
delete startTag.name;
delete startTag.xmlnsPointer;
delete startTag.xmlns;
delete startTag.attributes;
} else if (type == QXmlStreamReader::Characters) {
delete charachters.textPointer;
delete charachters.text;
} else if (type == QXmlStreamReader::EndElement) {
delete endTag.namePointer;
delete endTag.name;
}
}
~StackToken()
{
if ( type == QXmlStreamReader::StartElement )
{
delete startTag.namePointer;
delete startTag.name;
delete startTag.xmlnsPointer;
delete startTag.xmlns;
delete startTag.attributes;
}
else if ( type == QXmlStreamReader::Characters )
{
delete charachters.textPointer;
delete charachters.text;
}
else if ( type == QXmlStreamReader::EndElement )
{
delete endTag.namePointer;
delete endTag.name;
}
}
QXmlStreamReader::TokenType type;
union {
struct {
QString *namePointer;
QStringRef *name;
QString *xmlnsPointer;
QStringRef *xmlns;
QXmlStreamAttributes *attributes;
bool empty;
} startTag;
struct {
QString *textPointer;
QStringRef *text;
} charachters;
struct {
QString *namePointer;
QStringRef *name;
} endTag;
};
};
QXmlStreamReader::TokenType type;
union
{
struct
{
QString* namePointer;
QStringRef* name;
QString* xmlnsPointer;
QStringRef* xmlns;
QXmlStreamAttributes* attributes;
bool empty;
} startTag;
struct
{
QString* textPointer;
QStringRef* text;
} charachters;
struct
{
QString* namePointer;
QStringRef* name;
} endTag;
};
};
struct StackEnvironment
{
QXmlStreamReader reader;
State state;
int depth;
QList<StackToken*> tokens;
QColor bodyColor;
QColor tagColor;
QColor attributeColor;
QColor paramColor;
};
struct StackEnvironment
{
QXmlStreamReader reader;
State state;
int depth;
QList<StackToken*> tokens;
QColor bodyColor;
QColor tagColor;
QColor attributeColor;
QColor paramColor;
};
Ui::XmlConsole *m_ui;
Jreen::Client *m_client;
QList<XmlNode> m_nodes;
StackEnvironment m_stackIncoming;
StackEnvironment m_stackOutgoing;
QColor m_stackBracketsColor;
int m_filter;
Ui::XmlConsole* m_ui;
Jreen::Client* m_client;
QList<XmlNode> m_nodes;
StackEnvironment m_stackIncoming;
StackEnvironment m_stackOutgoing;
QColor m_stackBracketsColor;
int m_filter;
private slots:
void on_lineEdit_textChanged(const QString &);
void onActionGroupTriggered(QAction *action);
void on_saveButton_clicked();
private slots:
void on_lineEdit_textChanged( const QString& );
void onActionGroupTriggered( QAction* action );
void on_saveButton_clicked();
};

View File

@@ -57,9 +57,9 @@
#include <QTimer>
#ifndef ENABLE_HEADLESS
#include <QInputDialog>
#include <QLineEdit>
#include <QMessageBox>
#include <QInputDialog>
#include <QLineEdit>
#include <QMessageBox>
#endif
using namespace Tomahawk;
@@ -74,7 +74,7 @@ using namespace Accounts;
#if QT_VERSION <= QT_VERSION_CHECK( 5, 0, 0 )
void
JreenMessageHandler( QtMsgType type, const char *msg )
JreenMessageHandler( QtMsgType type, const char* msg )
{
switch ( type )
{
@@ -166,9 +166,9 @@ XmppSipPlugin::XmppSipPlugin( Account* account )
connect( m_client, SIGNAL( iqReceived( Jreen::IQ ) ), SLOT( onNewIq( Jreen::IQ ) ) );
connect( m_roster, SIGNAL( presenceReceived( Jreen::RosterItem::Ptr, Jreen::Presence ) ),
SLOT( onPresenceReceived( Jreen::RosterItem::Ptr, Jreen::Presence ) ) );
SLOT( onPresenceReceived( Jreen::RosterItem::Ptr, Jreen::Presence ) ) );
connect( m_roster, SIGNAL( subscriptionReceived( Jreen::RosterItem::Ptr, Jreen::Presence ) ),
SLOT( onSubscriptionReceived( Jreen::RosterItem::Ptr, Jreen::Presence ) ) );
SLOT( onSubscriptionReceived( Jreen::RosterItem::Ptr, Jreen::Presence ) ) );
#ifndef ENABLE_HEADLESS
connect( m_avatarManager, SIGNAL( newAvatar( QString ) ), SLOT( onNewAvatar( QString ) ) );
@@ -210,7 +210,9 @@ InfoSystem::InfoPluginPtr
XmppSipPlugin::infoPlugin()
{
if ( m_infoPlugin.isNull() )
{
m_infoPlugin = QPointer< Tomahawk::InfoSystem::XmppInfoPlugin >( new Tomahawk::InfoSystem::XmppInfoPlugin( this ) );
}
return InfoSystem::InfoPluginPtr( m_infoPlugin.data() );
}
@@ -246,7 +248,9 @@ XmppSipPlugin::connectPlugin()
QTimer::singleShot( 1000, m_client, SLOT( connectToServer() ) );
if ( m_client->connection() )
{
connect( m_client->connection(), SIGNAL( error( Jreen::Connection::SocketError ) ), SLOT( onError( Jreen::Connection::SocketError ) ), Qt::UniqueConnection );
}
m_state = Account::Connecting;
emit stateChanged( m_state );
@@ -332,7 +336,7 @@ XmppSipPlugin::onDisconnect( Jreen::Client::DisconnectReason reason )
switch( reason )
{
case Jreen::Client::User:
foreach( const Jreen::JID &peer, m_peers.keys() )
foreach( const Jreen::JID & peer, m_peers.keys() )
{
handlePeerStatus( peer, Jreen::Presence::Unavailable );
}
@@ -375,7 +379,9 @@ XmppSipPlugin::onDisconnect( Jreen::Client::DisconnectReason reason )
removeMenuHelper();
if ( !m_infoPlugin.isNull() )
{
Tomahawk::InfoSystem::InfoSystem::instance()->removeInfoPlugin( infoPlugin() );
}
}
@@ -453,13 +459,15 @@ XmppSipPlugin::sendSipInfos( const Tomahawk::peerinfo_ptr& receiver, const QList
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << receiver << info;
if ( !m_client )
{
return;
}
TomahawkXmppMessage* sipMessage = new TomahawkXmppMessage( info );
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Send sip messsage to" << receiver;
Jreen::IQ iq( Jreen::IQ::Set, receiver->id() );
iq.addExtension( sipMessage );
Jreen::IQReply *reply = m_client->send( iq );
Jreen::IQReply* reply = m_client->send( iq );
reply->setData( SipMessageSent );
connect( reply, SIGNAL( received( Jreen::IQ ) ), SLOT( onNewIq( Jreen::IQ ) ) );
}
@@ -499,7 +507,9 @@ XmppSipPlugin::showAddFriendDialog()
tr( "Enter Xmpp ID:" ), QLineEdit::Normal, "", &ok ).trimmed();
if ( !ok )
{
return;
}
qDebug() << "Attempting to add xmpp contact to roster:" << id;
addContact( id, SendInvite );
@@ -510,7 +520,7 @@ XmppSipPlugin::showAddFriendDialog()
void
XmppSipPlugin::publishTune( const QUrl& url, const InfoSystem::InfoStringHash& trackInfo )
{
if ( m_account->configuration().value("publishtracks").toBool() == false )
if ( m_account->configuration().value( "publishtracks" ).toBool() == false )
{
tDebug() << Q_FUNC_INFO << m_client->jid().full() << "Not publishing now playing info (disabled in account config)";
return;
@@ -553,7 +563,7 @@ void
XmppSipPlugin::showXmlConsole()
{
#ifndef ENABLE_HEADLESS
m_xmlConsole->show();
m_xmlConsole->show();
#endif
}
@@ -650,7 +660,7 @@ XmppSipPlugin::addMenuHelper()
#ifndef ENABLE_HEADLESS
if ( !m_menu )
{
m_menu = new QMenu( QString( "%1 (" ).arg( friendlyName() ).append( readUsername() ).append(")" ) );
m_menu = new QMenu( QString( "%1 (" ).arg( friendlyName() ).append( readUsername() ).append( ")" ) );
QAction* addFriendAction = m_menu->addAction( tr( "Add Friend..." ) );
connect( addFriendAction, SIGNAL( triggered() ), SLOT( showAddFriendDialog() ) );
@@ -686,13 +696,17 @@ void
XmppSipPlugin::onNewMessage( const Jreen::Message& message )
{
if ( m_state != Account::Connected )
{
return;
}
QString from = message.from().full();
QString msg = message.body();
if ( msg.isEmpty() )
{
return;
}
if ( message.subtype() == Jreen::Message::Error )
{
@@ -711,7 +725,7 @@ XmppSipPlugin::onNewMessage( const Jreen::Message& message )
" are trying to reach is probably not signed on, so please try again later!" ) );
// this is not a sip message, so we send it directly through the client
m_client->send( Jreen::Message ( Jreen::Message::Error, Jreen::JID( to ), response) );
m_client->send( Jreen::Message ( Jreen::Message::Error, Jreen::JID( to ), response ) );
return;
}
@@ -722,9 +736,11 @@ XmppSipPlugin::onNewMessage( const Jreen::Message& message )
void
XmppSipPlugin::onPresenceReceived( const Jreen::RosterItem::Ptr& item, const Jreen::Presence& presence )
{
Q_UNUSED(item);
Q_UNUSED( item );
if ( m_state != Account::Connected )
{
return;
}
Jreen::JID jid = presence.from();
QString fulljid( jid.full() );
@@ -732,7 +748,9 @@ XmppSipPlugin::onPresenceReceived( const Jreen::RosterItem::Ptr& item, const Jre
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "New presence:" << fulljid << presence.subtype();
if ( jid == m_client->jid() )
{
return;
}
if ( presence.error() )
{
@@ -747,13 +765,15 @@ XmppSipPlugin::onPresenceReceived( const Jreen::RosterItem::Ptr& item, const Jre
m_jidsNames.insert( jid.bare(), item->name() );
// find peers for the jid and update their friendlyName
foreach ( const Jreen::JID& peer, m_peers.keys() )
foreach ( const Jreen::JID & peer, m_peers.keys() )
{
if ( peer.bare() == jid.bare() )
{
Tomahawk::peerinfo_ptr peerInfo = PeerInfo::get( this, peer.full() );
if( !peerInfo.isNull() )
{
peerInfo->setFriendlyName( item->name() );
}
}
}
}
@@ -770,15 +790,17 @@ XmppSipPlugin::onPresenceReceived( const Jreen::RosterItem::Ptr& item, const Jre
Jreen::IQ featuresIq( Jreen::IQ::Get, jid );
featuresIq.addExtension( new Jreen::Disco::Info( node ) );
Jreen::IQReply *reply = m_client->send( featuresIq );
Jreen::IQReply* reply = m_client->send( featuresIq );
reply->setData( RequestDisco );
connect( reply, SIGNAL( received( Jreen::IQ ) ), SLOT( onNewIq( Jreen::IQ ) ) );
}
else if ( !caps )
{
// qDebug() << Q_FUNC_INFO << "Running tomahawk: no" << "no caps";
// qDebug() << Q_FUNC_INFO << "Running tomahawk: no" << "no caps";
if ( presenceMeansOnline( m_peers[ jid ] ) )
{
handlePeerStatus( jid, Jreen::Presence::Unavailable );
}
}
}
@@ -787,23 +809,29 @@ void
XmppSipPlugin::onSubscriptionReceived( const Jreen::RosterItem::Ptr& item, const Jreen::Presence& presence )
{
if ( m_state != Account::Connected )
{
return;
}
if ( item )
{
qDebug() << Q_FUNC_INFO << presence.from().full() << "subs" << item->subscription() << "ask" << item->ask();
}
else
{
qDebug() << Q_FUNC_INFO << "item empty";
}
// don't do anything if the contact is already subscribed to us
if ( presence.subtype() != Jreen::Presence::Subscribe ||
( item && (item->subscription() == Jreen::RosterItem::From || item->subscription() == Jreen::RosterItem::Both ) ) )
( item && ( item->subscription() == Jreen::RosterItem::From || item->subscription() == Jreen::RosterItem::Both ) ) )
{
return;
}
// check if the requester is already on the roster
if ( item &&
( item->subscription() == Jreen::RosterItem::To || ( item->subscription() == Jreen::RosterItem::None && !item->ask().isEmpty() ) ) )
( item->subscription() == Jreen::RosterItem::To || ( item->subscription() == Jreen::RosterItem::None && !item->ask().isEmpty() ) ) )
{
qDebug() << Q_FUNC_INFO << presence.from().bare() << "already on the roster so we assume ack'ing subscription request is okay...";
m_roster->allowSubscription( presence.from(), true );
@@ -813,13 +841,13 @@ XmppSipPlugin::onSubscriptionReceived( const Jreen::RosterItem::Ptr& item, const
#ifndef ENABLE_HEADLESS
// preparing the confirm box for the user
QMessageBox *confirmBox = new QMessageBox(
QMessageBox::Question,
tr( "Authorize User" ),
QString( tr( "Do you want to add <b>%1</b> to your friend list?" ) ).arg( presence.from().bare() ),
QMessageBox::Yes | QMessageBox::No,
TomahawkUtils::tomahawkWindow()
);
QMessageBox* confirmBox = new QMessageBox(
QMessageBox::Question,
tr( "Authorize User" ),
QString( tr( "Do you want to add <b>%1</b> to your friend list?" ) ).arg( presence.from().bare() ),
QMessageBox::Yes | QMessageBox::No,
TomahawkUtils::tomahawkWindow()
);
// add confirmBox to m_subscriptionConfirmBoxes
m_subscriptionConfirmBoxes.insert( presence.from(), confirmBox );
@@ -839,7 +867,7 @@ XmppSipPlugin::onSubscriptionRequestConfirmed( int result )
QList< QMessageBox* > confirmBoxes = m_subscriptionConfirmBoxes.values();
Jreen::JID jid;
foreach ( QMessageBox* currentBox, confirmBoxes )
foreach ( QMessageBox * currentBox, confirmBoxes )
{
if ( currentBox == sender() )
{
@@ -871,17 +899,21 @@ void
XmppSipPlugin::onNewIq( const Jreen::IQ& iq )
{
if ( m_state != Account::Connected )
{
return;
}
Jreen::IQReply *reply = qobject_cast< Jreen::IQReply* >( sender() );
Jreen::IQReply* reply = qobject_cast< Jreen::IQReply* >( sender() );
int context = reply ? reply->data().toInt() : NoContext;
if ( context == RequestDisco )
{
// qDebug() << Q_FUNC_INFO << "Received disco IQ...";
Jreen::Disco::Info *discoInfo = iq.payload< Jreen::Disco::Info >().data();
// qDebug() << Q_FUNC_INFO << "Received disco IQ...";
Jreen::Disco::Info* discoInfo = iq.payload< Jreen::Disco::Info >().data();
if ( !discoInfo )
{
return;
}
iq.accept();
Jreen::JID jid = iq.from();
@@ -995,11 +1027,13 @@ XmppSipPlugin::handlePeerStatus( const Jreen::JID& jid, Jreen::Presence::Type pr
QString fulljid = jid.full();
if ( fulljid.contains( "public.talk.google.com" ) )
{
return;
}
// "going offline" event
if ( !presenceMeansOnline( presenceType ) &&
( !m_peers.contains( jid ) || presenceMeansOnline( m_peers.value( jid ) ) ) )
( !m_peers.contains( jid ) || presenceMeansOnline( m_peers.value( jid ) ) ) )
{
qDebug() << Q_FUNC_INFO << "* Peer goes offline:" << fulljid;
@@ -1030,7 +1064,7 @@ XmppSipPlugin::handlePeerStatus( const Jreen::JID& jid, Jreen::Presence::Type pr
// "coming online" event
if ( presenceMeansOnline( presenceType ) &&
( !m_peers.contains( jid ) || !presenceMeansOnline( m_peers.value( jid ) ) ) )
( !m_peers.contains( jid ) || !presenceMeansOnline( m_peers.value( jid ) ) ) )
{
qDebug() << Q_FUNC_INFO << "* Peer goes online:" << fulljid;
@@ -1046,13 +1080,15 @@ XmppSipPlugin::handlePeerStatus( const Jreen::JID& jid, Jreen::Presence::Type pr
#ifndef ENABLE_HEADLESS
if ( !m_avatarManager->avatar( jid.bare() ).isNull() )
{
onNewAvatar( jid.bare() );
}
#endif
// request software version
Jreen::IQ versionIq( Jreen::IQ::Get, jid );
versionIq.addExtension( new Jreen::SoftwareVersion() );
Jreen::IQReply *reply = m_client->send( versionIq );
Jreen::IQReply* reply = m_client->send( versionIq );
reply->setData( RequestVersion );
connect( reply, SIGNAL( received( Jreen::IQ ) ), SLOT( onNewIq( Jreen::IQ ) ) );
@@ -1068,21 +1104,25 @@ void
XmppSipPlugin::onNewAvatar( const QString& jid )
{
#ifndef ENABLE_HEADLESS
// qDebug() << Q_FUNC_INFO << jid;
// qDebug() << Q_FUNC_INFO << jid;
if ( m_state != Account::Connected )
{
return;
}
Q_ASSERT( !m_avatarManager->avatar( jid ).isNull() );
// find peers for the jid
QList< Jreen::JID > peers = m_peers.keys();
foreach ( const Jreen::JID& peer, peers )
foreach ( const Jreen::JID & peer, peers )
{
if ( peer.bare() == jid )
{
Tomahawk::peerinfo_ptr peerInfo = PeerInfo::get( this, peer.full() );
if ( !peerInfo.isNull() )
{
peerInfo->setAvatar( m_avatarManager->avatar( jid ) );
}
}
}

View File

@@ -28,7 +28,7 @@
#include "AvatarManager.h"
#ifndef ENABLE_HEADLESS
#include "XmlConsole.h"
#include "XmlConsole.h"
#endif
#include "accounts/AccountDllMacro.h"
@@ -51,7 +51,7 @@
#include <jreen/pubsubmanager.h>
#ifndef ENABLE_HEADLESS
#include <QMessageBox>
#include <QMessageBox>
#endif
@@ -59,14 +59,17 @@ class ACCOUNTDLLEXPORT XmppSipPlugin : public SipPlugin
{
Q_OBJECT
friend class Tomahawk::InfoSystem::XmppInfoPlugin;
friend class Tomahawk::InfoSystem::XmppInfoPlugin;
public:
public:
XmppSipPlugin( Tomahawk::Accounts::Account* account );
virtual ~XmppSipPlugin();
//FIXME: Make this more correct
virtual bool isValid() const { return true; }
virtual bool isValid() const
{
return true;
}
virtual QString inviteString() const;
Tomahawk::InfoSystem::InfoPluginPtr infoPlugin();
@@ -78,14 +81,14 @@ public:
// used by XmppAccount to expose connection state and controls
Tomahawk::Accounts::Account::ConnectionState connectionState() const;
signals:
signals:
void jidChanged( const QString& );
// Used by XmppAccount
void stateChanged( Tomahawk::Accounts::Account::ConnectionState state );
void error( int errorId, const QString& errorStr );
public slots:
public slots:
virtual void connectPlugin();
virtual void disconnectPlugin();
virtual void checkSettings();
@@ -97,10 +100,10 @@ public slots:
void showAddFriendDialog();
void publishTune( const QUrl& url, const Tomahawk::InfoSystem::InfoStringHash& trackInfo );
protected:
protected:
virtual QString defaultSuffix() const;
private slots:
private slots:
void showXmlConsole();
void onConnect();
void onDisconnect( Jreen::Client::DisconnectReason reason );
@@ -114,7 +117,7 @@ private slots:
void onNewIq( const Jreen::IQ& iq );
void onNewAvatar( const QString& jid );
private:
private:
bool readXmlConsoleEnabled();
QString readUsername();
QString readPassword();

View File

@@ -37,9 +37,9 @@
class Node : public QObject
{
Q_OBJECT
Q_OBJECT
public:
public:
Node( const QString& i, const QString& n, int p )
: ip( i ), nid( n ), port( p )
{
@@ -51,17 +51,21 @@ public:
qDebug() << Q_FUNC_INFO;
}
signals:
signals:
void tomahawkHostFound( const QString&, int, const QString&, const QString& );
public slots:
public slots:
void resolved( QHostInfo i )
{
qDebug() << Q_FUNC_INFO << "zeroconf-derived IP has resolved to name " << i.hostName();
if ( i.hostName().length() )
{
emit tomahawkHostFound( ip, port, i.hostName(), nid );
}
else
{
emit tomahawkHostFound( ip, port, "Unknown", nid );
}
this->deleteLater();
}
@@ -71,7 +75,7 @@ public slots:
QHostInfo::lookupHost( ip, this, SLOT( resolved( QHostInfo ) ) );
}
private:
private:
QString ip;
QString nid;
int port;
@@ -80,9 +84,9 @@ private:
class ACCOUNTDLLEXPORT TomahawkZeroconf : public QObject
{
Q_OBJECT
Q_OBJECT
public:
public:
TomahawkZeroconf( int port, QObject* parent = 0 )
: QObject( parent ), m_sock( this ), m_port( port )
{
@@ -97,34 +101,36 @@ public:
qDebug() << Q_FUNC_INFO;
}
public slots:
public slots:
void advertise()
{
qDebug() << "Advertising us on the LAN (both versions)";
// Keep newer versions first
QByteArray advert = QString( "TOMAHAWKADVERT:%1:%2:%3" )
.arg( m_port )
.arg( Tomahawk::Database::instance()->impl()->dbid() )
.arg( QHostInfo::localHostName() )
.toLatin1();
.arg( m_port )
.arg( Tomahawk::Database::instance()->impl()->dbid() )
.arg( QHostInfo::localHostName() )
.toLatin1();
m_sock.writeDatagram( advert.data(), advert.size(), QHostAddress::Broadcast, ZCONF_PORT );
advert = QString( "TOMAHAWKADVERT:%1:%2" )
.arg( m_port )
.arg( Tomahawk::Database::instance()->impl()->dbid() )
.toLatin1();
.arg( m_port )
.arg( Tomahawk::Database::instance()->impl()->dbid() )
.toLatin1();
m_sock.writeDatagram( advert.data(), advert.size(), QHostAddress::Broadcast, ZCONF_PORT );
}
signals:
signals:
// IP, port, name, session
void tomahawkHostFound( const QString&, int, const QString&, const QString& );
private slots:
private slots:
void readPacket()
{
if ( !m_sock.hasPendingDatagrams() )
{
return;
}
QByteArray datagram;
datagram.resize( m_sock.pendingDatagramSize() );
@@ -135,17 +141,19 @@ private slots:
// Ignore our own requests
if ( QNetworkInterface::allAddresses().contains( sender ) )
{
return;
}
// only process msgs originating on the LAN:
if ( datagram.startsWith( "TOMAHAWKADVERT:" ) &&
Servent::isIPWhitelisted( sender ) )
Servent::isIPWhitelisted( sender ) )
{
QStringList parts = QString::fromLatin1( datagram ).split( ':' );
if ( parts.length() == 4 )
{
bool ok;
int port = parts.at(1).toInt( &ok );
int port = parts.at( 1 ).toInt( &ok );
if ( ok && Tomahawk::Database::instance()->impl()->dbid() != parts.at( 2 ) )
{
emit tomahawkHostFound( sender.toString(), port, parts.at( 3 ), parts.at( 2 ) );
@@ -154,11 +162,11 @@ private slots:
else if ( parts.length() == 3 )
{
bool ok;
int port = parts.at(1).toInt( &ok );
int port = parts.at( 1 ).toInt( &ok );
if ( ok && Tomahawk::Database::instance()->impl()->dbid() != parts.at( 2 ) )
{
qDebug() << "ADVERT received:" << sender << port;
Node *n = new Node( sender.toString(), parts.at( 2 ), port );
Node* n = new Node( sender.toString(), parts.at( 2 ), port );
connect( n, SIGNAL( tomahawkHostFound( QString, int, QString, QString ) ),
this, SIGNAL( tomahawkHostFound( QString, int, QString, QString ) ) );
n->resolve();
@@ -167,10 +175,12 @@ private slots:
}
if ( m_sock.hasPendingDatagrams() )
{
QTimer::singleShot( 0, this, SLOT( readPacket() ) );
}
}
private:
private:
QUdpSocket m_sock;
int m_port;
};

View File

@@ -94,14 +94,14 @@ ZeroconfPlugin::connectPlugin()
delete m_zeroconf;
m_zeroconf = new TomahawkZeroconf( Servent::instance()->port(), this );
QObject::connect( m_zeroconf, SIGNAL( tomahawkHostFound( QString, int, QString, QString ) ),
SLOT( lanHostFound( QString, int, QString, QString ) ) );
SLOT( lanHostFound( QString, int, QString, QString ) ) );
advertise();
m_state = Account::Connected;
foreach( const QStringList& nodeSet, m_cachedNodes )
foreach( const QStringList & nodeSet, m_cachedNodes )
{
lanHostFound( nodeSet[0], nodeSet[1].toInt(), nodeSet[2], nodeSet[3]);
lanHostFound( nodeSet[0], nodeSet[1].toInt(), nodeSet[2], nodeSet[3] );
}
m_cachedNodes.clear();
@@ -142,7 +142,9 @@ void
ZeroconfPlugin::lanHostFound( const QString& host, int port, const QString& name, const QString& nodeid )
{
if ( sender() != m_zeroconf )
{
return;
}
qDebug() << "Found LAN host:" << host << port << nodeid;

View File

@@ -40,7 +40,7 @@ class ACCOUNTDLLEXPORT ZeroconfPlugin : public SipPlugin
{
Q_OBJECT
public:
public:
ZeroconfPlugin( ZeroconfAccount* acc );
virtual ~ZeroconfPlugin();
@@ -50,14 +50,17 @@ public:
virtual const QString accountName() const;
virtual const QString serviceName() const;
virtual Account::ConnectionState connectionState() const;
virtual bool isValid() const { return true; }
virtual bool isValid() const
{
return true;
}
#ifndef ENABLE_HEADLESS
virtual QIcon icon() const;
#endif
virtual void checkSettings() {}
virtual void configurationChanged() {}
public slots:
public slots:
void connectPlugin();
void disconnectPlugin();
@@ -65,12 +68,15 @@ public slots:
virtual void sendSipInfos( const Tomahawk::peerinfo_ptr& /* receiver */, const QList<SipInfo>& /* info */ ) {}
void broadcastMsg( const QString& ) {}
bool addContact( const QString&, AddContactOptions, const QString& ) { return false; }
bool addContact( const QString&, AddContactOptions, const QString& )
{
return false;
}
private slots:
private slots:
void lanHostFound( const QString& host, int port, const QString& name, const QString& nodeid );
private:
private:
TomahawkZeroconf* m_zeroconf;
Account::ConnectionState m_state;
QVector<QStringList> m_cachedNodes;

View File

@@ -31,7 +31,9 @@ ZeroconfFactory::ZeroconfFactory()
{
#ifndef ENABLE_HEADLESS
if ( s_icon == 0 )
{
s_icon = new QPixmap( ":/zeroconf-account/zeroconf-icon.png" );
}
#endif
}
@@ -84,7 +86,9 @@ void
ZeroconfAccount::authenticate()
{
if ( !isAuthenticated() )
{
sipPlugin()->connectPlugin();
}
}
@@ -92,7 +96,9 @@ void
ZeroconfAccount::deauthenticate()
{
if ( isAuthenticated() && !m_sipPlugin.isNull() )
{
m_sipPlugin->disconnectPlugin();
}
}
@@ -107,7 +113,9 @@ Account::ConnectionState
ZeroconfAccount::connectionState() const
{
if ( m_sipPlugin.isNull() )
{
return Disconnected;
}
// TODO can we get called before sipPlugin()?
return m_sipPlugin->connectionState();
@@ -117,9 +125,12 @@ ZeroconfAccount::connectionState() const
SipPlugin*
ZeroconfAccount::sipPlugin( bool create )
{
if ( m_sipPlugin.isNull() ) {
if ( m_sipPlugin.isNull() )
{
if ( !create )
{
return 0;
}
m_sipPlugin = QPointer< ZeroconfPlugin >( new ZeroconfPlugin( this ) );
}

View File

@@ -37,17 +37,32 @@ class ACCOUNTDLLEXPORT ZeroconfFactory : public AccountFactory
Q_OBJECT
Q_INTERFACES( Tomahawk::Accounts::AccountFactory )
public:
public:
ZeroconfFactory();
virtual ~ZeroconfFactory();
virtual QString factoryId() const { return "zeroconfaccount"; }
virtual QString prettyName() const { return tr( "Local Network" ); }
QString description() const { return tr( "Automatically connect to Tomahawks on the local network" ); }
virtual bool isUnique() const { return true; }
AccountTypes types() const { return AccountTypes( SipType ); };
virtual QString factoryId() const
{
return "zeroconfaccount";
}
virtual QString prettyName() const
{
return tr( "Local Network" );
}
QString description() const
{
return tr( "Automatically connect to Tomahawks on the local network" );
}
virtual bool isUnique() const
{
return true;
}
AccountTypes types() const
{
return AccountTypes( SipType );
};
#ifndef ENABLE_HEADLESS
virtual QPixmap icon() const;
virtual QPixmap icon() const;
#endif
@@ -57,8 +72,8 @@ virtual QPixmap icon() const;
class ACCOUNTDLLEXPORT ZeroconfAccount : public Account
{
Q_OBJECT
public:
ZeroconfAccount( const QString &accountId );
public:
ZeroconfAccount( const QString& accountId );
virtual ~ZeroconfAccount();
QPixmap icon() const;
@@ -68,13 +83,22 @@ public:
bool isAuthenticated() const;
ConnectionState connectionState() const;
virtual Tomahawk::InfoSystem::InfoPluginPtr infoPlugin() { return Tomahawk::InfoSystem::InfoPluginPtr(); }
virtual Tomahawk::InfoSystem::InfoPluginPtr infoPlugin()
{
return Tomahawk::InfoSystem::InfoPluginPtr();
}
SipPlugin* sipPlugin( bool create = true );
AccountConfigWidget* configurationWidget() { return 0; }
QWidget* aclWidget() { return 0; }
AccountConfigWidget* configurationWidget()
{
return 0;
}
QWidget* aclWidget()
{
return 0;
}
private:
private:
QPointer< ZeroconfPlugin > m_sipPlugin;
};

View File

@@ -42,21 +42,21 @@ CrashReporter::CrashReporter( const QUrl& url, const QStringList& args )
ui.progressBar->setValue( 0 );
ui.progressLabel->setPalette( Qt::gray );
#ifdef Q_OS_MAC
#ifdef Q_OS_MAC
QFont f = ui.bottomLabel->font();
f.setPointSize( 10 );
ui.bottomLabel->setFont( f );
f.setPointSize( 11 );
ui.progressLabel->setFont( f );
ui.progressLabel->setIndent( 3 );
#else
#else
ui.vboxLayout->setSpacing( 16 );
ui.hboxLayout1->setSpacing( 16 );
ui.progressBar->setTextVisible( false );
ui.progressLabel->setIndent( 1 );
ui.bottomLabel->setDisabled( true );
ui.bottomLabel->setIndent( 1 );
#endif //Q_OS_MAC
#endif //Q_OS_MAC
m_request = new QNetworkRequest( m_url );
@@ -115,14 +115,14 @@ CrashReporter::send()
{
body += "--thkboundary\r\n";
body += "Content-Disposition: form-data; name=\"" +
pair.first + "\"\r\n\r\n" +
pair.second + "\r\n";
pair.first + "\"\r\n\r\n" +
pair.second + "\r\n";
}
// add minidump file
body += "--thkboundary\r\n";
body += "Content-Disposition: form-data; name=\"upload_file_minidump\"; filename=\""
+ QFileInfo( m_minidump ).fileName() + "\"\r\n";
+ QFileInfo( m_minidump ).fileName() + "\"\r\n";
body += "Content-Type: application/octet-stream\r\n";
body += "\r\n";
body += contents( m_minidump );
@@ -179,7 +179,9 @@ CrashReporter::onDone()
onFail( m_reply->error(), m_reply->errorString() );
}
else
{
ui.progressLabel->setText( tr( "Sent! <b>Many thanks</b>." ) );
}
}

View File

@@ -31,11 +31,11 @@ class CrashReporter : public QDialog
{
Q_OBJECT
public:
public:
CrashReporter( const QUrl& url, const QStringList& argv );
virtual ~CrashReporter( );
private:
private:
Ui::CrashReporter ui;
QString m_minidump;
@@ -45,10 +45,10 @@ private:
QNetworkReply* m_reply;
QUrl m_url;
public slots:
public slots:
void send();
private slots:
private slots:
void onDone();
void onProgress( qint64 done, qint64 total );
void onFail( int error, const QString& errorString );

View File

@@ -59,7 +59,7 @@ ChartsPlugin::ChartsPlugin()
m_chartVersion = "2.6.6";
m_supportedGetTypes << InfoChart << InfoChartCapabilities;
m_cacheIdentifier = TomahawkUtils::md5( QString("ChartsPlugin" + m_chartVersion ).toUtf8() );
m_cacheIdentifier = TomahawkUtils::md5( QString( "ChartsPlugin" + m_chartVersion ).toUtf8() );
}
@@ -75,27 +75,29 @@ ChartsPlugin::init()
QVariant data = TomahawkUtils::Cache::instance()->getData( m_cacheIdentifier, "chart_sources" );
if ( data.canConvert< QList< Tomahawk::InfoSystem::InfoStringHash > >() )
{
const QList< Tomahawk::InfoSystem::InfoStringHash > sourceList = data.value< QList< Tomahawk::InfoSystem::InfoStringHash > >();
foreach ( const Tomahawk::InfoSystem::InfoStringHash &sourceHash, sourceList )
{
bool ok;
qlonglong maxAge = getMaxAge( QString( sourceHash[ "chart_expires" ] ).toLongLong( &ok ) );
if ( !ok || maxAge <= 0 )
{
// This source has expired.
m_refetchSource << sourceHash[ "chart_source" ];
}
m_chartResources << sourceHash;
}
const QList< Tomahawk::InfoSystem::InfoStringHash > sourceList = data.value< QList< Tomahawk::InfoSystem::InfoStringHash > >();
foreach ( const Tomahawk::InfoSystem::InfoStringHash & sourceHash, sourceList )
{
bool ok;
qlonglong maxAge = getMaxAge( QString( sourceHash[ "chart_expires" ] ).toLongLong( &ok ) );
if ( !ok || maxAge <= 0 )
{
// This source has expired.
m_refetchSource << sourceHash[ "chart_source" ];
}
m_chartResources << sourceHash;
}
data = TomahawkUtils::Cache::instance()->getData( m_cacheIdentifier, "allCharts" );
data = TomahawkUtils::Cache::instance()->getData( m_cacheIdentifier, "allCharts" );
if ( data.canConvert< QVariantMap >() )
{
m_allChartsMap = data.toMap();
if ( !m_allChartsMap.empty() )
m_fetchAll = false;
}
if ( data.canConvert< QVariantMap >() )
{
m_allChartsMap = data.toMap();
if ( !m_allChartsMap.empty() )
{
m_fetchAll = false;
}
}
}
else
{
@@ -137,7 +139,7 @@ ChartsPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
}
else
{
foreach ( const Tomahawk::InfoSystem::InfoStringHash &sourceHash, m_chartResources )
foreach ( const Tomahawk::InfoSystem::InfoStringHash & sourceHash, m_chartResources )
{
if ( sourceHash[ "chart_source" ] == hash[ "chart_source" ] )
{
@@ -240,7 +242,7 @@ ChartsPlugin::fetchChartCapabilitiesFromCache( Tomahawk::InfoSystem::InfoRequest
}
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Checking cache for " << "InfoChartCapabilities" << m_chartVersion;
emit getCachedInfo( criteria, Q_INT64_C(172800000) /* 2 days */, requestData );
emit getCachedInfo( criteria, Q_INT64_C( 172800000 ) /* 2 days */, requestData );
}
@@ -309,7 +311,7 @@ ChartsPlugin::chartSourcesList()
m_chartResources.clear();
foreach ( const QVariant &rsource, sources )
foreach ( const QVariant & rsource, sources )
{
/// Each item has an expiration, on next request for cache, it will be checked */
const QString source = rsource.toString();
@@ -320,13 +322,13 @@ ChartsPlugin::chartSourcesList()
const QString headerExpiration = reply->rawHeader( QString( tmpSource ).toLocal8Bit() );
const qlonglong maxAge = getMaxAge( headerExpiration.toLocal8Bit() );
const qlonglong expires = headerExpiration.toLongLong(&ok);
const qlonglong expires = headerExpiration.toLongLong( &ok );
Tomahawk::InfoSystem::InfoStringHash source_expire;
if ( ok )
{
source_expire[ "chart_source" ] = source;
source_expire[ "chart_expires" ] = QString::number(expires);
source_expire[ "chart_expires" ] = QString::number( expires );
m_chartResources << source_expire;
if( !m_fetchAll )
@@ -367,12 +369,14 @@ ChartsPlugin::chartSourcesList()
}
}
else
{
tDebug() << Q_FUNC_INFO << "Encountered error fetching chart sources list";
}
}
void
ChartsPlugin::fetchSource(const QString& source)
ChartsPlugin::fetchSource( const QString& source )
{
QUrl url = QUrl( QString( CHART_URL "charts/%1" ).arg( source ) );
TomahawkUtils::urlAddQueryItem( url, "version", TomahawkUtils::appFriendlyVersion() );
@@ -392,9 +396,9 @@ ChartsPlugin::fetchExpiredSources()
{
if ( !m_refetchSource.isEmpty() )
{
foreach ( const QString& source, m_refetchSource )
foreach ( const QString & source, m_refetchSource )
{
fetchSource(source);
fetchSource( source );
}
}
}
@@ -407,7 +411,7 @@ ChartsPlugin::fetchAllChartSources()
{
foreach ( const Tomahawk::InfoSystem::InfoStringHash source, m_chartResources )
{
fetchSource(source[ "chart_source" ]);
fetchSource( source[ "chart_source" ] );
}
}
}
@@ -478,7 +482,7 @@ ChartsPlugin::chartsList()
QHash< QString, QVariantMap > extraType;
QStringList processed;
foreach ( const QVariant& chartObj, response.values() )
foreach ( const QVariant & chartObj, response.values() )
{
if ( !chartObj.toMap().isEmpty() )
{
@@ -497,14 +501,20 @@ ChartsPlugin::chartsList()
if ( geo == "jp" && type == "Tracks" )
{
if ( processed.contains( name ) )
{
continue;
}
processed << name;
}
if ( !geo.isEmpty() )
{
extra = countryName( geo );
}
else
{
extra = chart.value( "extra" ).toString();
}
InfoStringHash c;
c[ "id" ] = id;
@@ -521,14 +531,14 @@ ChartsPlugin::chartsList()
}
// If this item has expired, set it to 0.
c[ "expires" ] = ( ok ? QString::number (expires ) : QString::number( 0 ) );
c[ "expires" ] = ( ok ? QString::number ( expires ) : QString::number( 0 ) );
QList< Tomahawk::InfoSystem::InfoStringHash > extraTypeData = extraType[ extra ][ type ].value< QList< Tomahawk::InfoSystem::InfoStringHash > >();
extraTypeData.append( c );
extraType[ extra ][ type ] = QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( extraTypeData );
}
foreach ( const QString& c, extraType.keys() )
foreach ( const QString & c, extraType.keys() )
{
charts[ c ] = extraType[ c ];
}
@@ -543,7 +553,7 @@ ChartsPlugin::chartsList()
QList< InfoStringHash > trackCharts;
QList< InfoStringHash > artistCharts;
foreach ( const QVariant& chartObj, response.values() )
foreach ( const QVariant & chartObj, response.values() )
{
if ( !chartObj.toMap().isEmpty() )
{
@@ -567,20 +577,32 @@ ChartsPlugin::chartsList()
}
if ( type == "Albums" )
{
albumCharts.append( c );
}
else if ( type == "Tracks" )
{
trackCharts.append( c );
}
else if ( type == "Artists" )
{
artistCharts.append( c );
}
}
if ( !artistCharts.isEmpty() )
{
charts.insert( tr( "Artists" ), QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( artistCharts ) );
}
if ( !albumCharts.isEmpty() )
{
charts.insert( tr( "Albums" ), QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( albumCharts ) );
}
if ( !trackCharts.isEmpty() )
{
charts.insert( tr( "Tracks" ), QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( trackCharts ) );
}
}
}
@@ -613,7 +635,7 @@ ChartsPlugin::chartsList()
criteria[ "InfoChartVersion" ] = m_chartVersion;
/// We can cache it the lot for 2 days, it will be checked on next request
emit updateCache( criteria, Q_INT64_C(172800000) /* 2 days */, request.type, m_allChartsMap );
emit updateCache( criteria, Q_INT64_C( 172800000 ) /* 2 days */, request.type, m_allChartsMap );
}
TomahawkUtils::Cache::instance()->putData( m_cacheIdentifier, 172800000 /* 2 days */, "allCharts", m_allChartsMap );
@@ -654,15 +676,23 @@ ChartsPlugin::chartReturned()
/// @todo: We allready know the type, append it to breadcrumb hash
if ( res.value( "type" ).toString() == "Album" )
{
setChartType( Album );
}
else if ( res.value( "type" ).toString() == "Track" )
{
setChartType( Track );
}
else if ( res.value( "type" ).toString() == "Artist" )
{
setChartType( Artist );
}
else
{
setChartType( None );
}
foreach ( const QVariant& chartR, chartResponse )
foreach ( const QVariant & chartR, chartResponse )
{
QString title, artist, album, streamUrl;
QVariantMap chartMap = chartR.toMap();
@@ -749,7 +779,7 @@ ChartsPlugin::chartReturned()
criteria[ "chart_expires" ] = ( ok ? QString::number( expires ) : QString::number( 0 ) );
/// If the item has expired, cache it for one hour and try and refetch later
emit updateCache( criteria, (maxAge == Q_INT64_C(0) ? Q_INT64_C(3600000) /* One hour */ : maxAge), requestData.type, returnedData );
emit updateCache( criteria, ( maxAge == Q_INT64_C( 0 ) ? Q_INT64_C( 3600000 ) /* One hour */ : maxAge ), requestData.type, returnedData );
}
else
{
@@ -768,7 +798,9 @@ QString
ChartsPlugin::countryName( const QString& cc )
{
if ( m_cachedCountries.contains( cc ) )
{
return m_cachedCountries[ cc ];
}
QString name = Tomahawk::CountryUtils::fullCountryFromCode( cc );
for ( int i = 1; i < name.size(); i++ )
@@ -785,7 +817,7 @@ ChartsPlugin::countryName( const QString& cc )
qlonglong
ChartsPlugin::getMaxAge( const QByteArray &rawHeader ) const
ChartsPlugin::getMaxAge( const QByteArray& rawHeader ) const
{
bool ok;
qlonglong expires = QString( rawHeader ).toLongLong( &ok );
@@ -799,12 +831,12 @@ ChartsPlugin::getMaxAge( const QByteArray &rawHeader ) const
qlonglong
ChartsPlugin::getMaxAge( const qlonglong expires ) const
{
qlonglong currentEpoch = QDateTime::currentMSecsSinceEpoch()/1000;
qlonglong expiresInSeconds = expires-currentEpoch;
qlonglong currentEpoch = QDateTime::currentMSecsSinceEpoch() / 1000;
qlonglong expiresInSeconds = expires - currentEpoch;
if ( expiresInSeconds > 0 )
{
return ( qlonglong )expiresInSeconds*1000;
return ( qlonglong )expiresInSeconds * 1000;
}
return 0;
}

View File

@@ -41,21 +41,28 @@ class INFOPLUGINDLLEXPORT ChartsPlugin : public InfoPlugin
Q_OBJECT
Q_INTERFACES( Tomahawk::InfoSystem::InfoPlugin )
public:
public:
ChartsPlugin();
virtual ~ChartsPlugin();
enum ChartType {
enum ChartType
{
None = 0x00,
Track = 0x01,
Album = 0x02,
Artist = 0x04
};
void setChartType( ChartType type ) { m_chartType = type; }
ChartType chartType() const { return m_chartType; }
void setChartType( ChartType type )
{
m_chartType = type;
}
ChartType chartType() const
{
return m_chartType;
}
protected slots:
protected slots:
virtual void init();
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
@@ -80,7 +87,7 @@ protected slots:
*/
void chartReturned();
private:
private:
/**
* Fetch list of chart sources (e.g., itunes, billboard)
* Populates the m_chartResources member.
@@ -104,7 +111,7 @@ private:
QString countryName( const QString& cc );
qlonglong getMaxAge( const QByteArray &rawHeader ) const;
qlonglong getMaxAge( const QByteArray& rawHeader ) const;
qlonglong getMaxAge( const qlonglong expires ) const;
QVariantMap m_allChartsMap;

View File

@@ -68,7 +68,7 @@ DiscogsPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
criteria["artist"] = hash["artist"];
criteria["album"] = hash["album"];
emit getCachedInfo( criteria, Q_INT64_C(2419200000), requestData );
emit getCachedInfo( criteria, Q_INT64_C( 2419200000 ), requestData );
break;
}
@@ -114,7 +114,7 @@ DiscogsPlugin::notInCacheSlot( InfoStringHash criteria, InfoRequestData requestD
void
DiscogsPlugin::albumSearchSlot( const InfoRequestData &requestData, QNetworkReply *reply )
DiscogsPlugin::albumSearchSlot( const InfoRequestData& requestData, QNetworkReply* reply )
{
QJson::Parser p;
QVariantMap results = p.parse( reply ).toMap();
@@ -169,11 +169,13 @@ DiscogsPlugin::albumInfoSlot( const InfoRequestData& requestData, QNetworkReply*
}
QStringList trackNameList;
foreach ( const QVariant& v, release[ "tracklist" ].toList() )
foreach ( const QVariant & v, release[ "tracklist" ].toList() )
{
const QVariantMap track = v.toMap();
if ( track.contains( "title" ) )
{
trackNameList << track[ "title" ].toString();
}
}
QVariantMap returnedData;
@@ -185,7 +187,7 @@ DiscogsPlugin::albumInfoSlot( const InfoRequestData& requestData, QNetworkReply*
criteria["artist"] = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash>()["artist"];
criteria["album"] = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash>()["album"];
emit updateCache( criteria, Q_INT64_C(0), requestData.type, returnedData );
emit updateCache( criteria, Q_INT64_C( 0 ), requestData.type, returnedData );
}

View File

@@ -39,21 +39,21 @@ class INFOPLUGINDLLEXPORT DiscogsPlugin : public InfoPlugin
Q_OBJECT
Q_INTERFACES( Tomahawk::InfoSystem::InfoPlugin )
public:
public:
DiscogsPlugin();
virtual ~DiscogsPlugin();
protected slots:
protected slots:
virtual void init() {}
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void notInCacheSlot( InfoStringHash criteria, InfoRequestData requestData );
virtual void pushInfo( Tomahawk::InfoSystem::InfoPushData ) {}
private slots:
void albumSearchSlot( const Tomahawk::InfoSystem::InfoRequestData& , QNetworkReply* );
void albumInfoSlot( const Tomahawk::InfoSystem::InfoRequestData& , QNetworkReply* );
private slots:
void albumSearchSlot( const Tomahawk::InfoSystem::InfoRequestData&, QNetworkReply* );
void albumInfoSlot( const Tomahawk::InfoSystem::InfoRequestData&, QNetworkReply* );
private:
private:
bool isValidTrackData( Tomahawk::InfoSystem::InfoRequestData requestData );
};

View File

@@ -83,25 +83,27 @@ EchonestPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
void
EchonestPlugin::getSongProfile( const Tomahawk::InfoSystem::InfoRequestData &requestData, const QString &item )
EchonestPlugin::getSongProfile( const Tomahawk::InfoSystem::InfoRequestData& requestData, const QString& item )
{
//WARNING: Totally not implemented yet
Q_UNUSED( item );
if( !isValidTrackData( requestData ) )
{
return;
}
// Track track( input.toString() );
// Artist artist( customData.input()->property("artistName").toString() );
// reply->setProperty("artist", QVariant::fromValue<Artist>(artist));
// reply->setProperty( "input", input );
// m_replyMap[reply] = customData;
// connect(reply, SIGNAL(finished()), SLOT(getArtistBiographySlot()));
// Track track( input.toString() );
// Artist artist( customData.input()->property("artistName").toString() );
// reply->setProperty("artist", QVariant::fromValue<Artist>(artist));
// reply->setProperty( "input", input );
// m_replyMap[reply] = customData;
// connect(reply, SIGNAL(finished()), SLOT(getArtistBiographySlot()));
}
void
EchonestPlugin::getArtistBiography( const Tomahawk::InfoSystem::InfoRequestData &requestData )
EchonestPlugin::getArtistBiography( const Tomahawk::InfoSystem::InfoRequestData& requestData )
{
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
{
@@ -114,7 +116,7 @@ EchonestPlugin::getArtistBiography( const Tomahawk::InfoSystem::InfoRequestData
}
Echonest::Artist artist( hash["artist"] );
QNetworkReply *reply = artist.fetchBiographies();
QNetworkReply* reply = artist.fetchBiographies();
reply->setProperty( "artist", QVariant::fromValue< Echonest::Artist >( artist ) );
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
connect( reply, SIGNAL( finished() ), SLOT( getArtistBiographySlot() ) );
@@ -122,10 +124,12 @@ EchonestPlugin::getArtistBiography( const Tomahawk::InfoSystem::InfoRequestData
void
EchonestPlugin::getArtistFamiliarity( const Tomahawk::InfoSystem::InfoRequestData &requestData )
EchonestPlugin::getArtistFamiliarity( const Tomahawk::InfoSystem::InfoRequestData& requestData )
{
if( !isValidArtistData( requestData ) )
{
return;
}
qDebug() << "Fetching artist familiarity!" << requestData.input;
Echonest::Artist artist( requestData.input.toString() );
@@ -137,10 +141,12 @@ EchonestPlugin::getArtistFamiliarity( const Tomahawk::InfoSystem::InfoRequestDat
void
EchonestPlugin::getArtistHotttnesss( const Tomahawk::InfoSystem::InfoRequestData &requestData )
EchonestPlugin::getArtistHotttnesss( const Tomahawk::InfoSystem::InfoRequestData& requestData )
{
if( !isValidArtistData( requestData ) )
{
return;
}
Echonest::Artist artist( requestData.input.toString() );
QNetworkReply* reply = artist.fetchHotttnesss();
@@ -151,10 +157,12 @@ EchonestPlugin::getArtistHotttnesss( const Tomahawk::InfoSystem::InfoRequestData
void
EchonestPlugin::getArtistTerms( const Tomahawk::InfoSystem::InfoRequestData &requestData )
EchonestPlugin::getArtistTerms( const Tomahawk::InfoSystem::InfoRequestData& requestData )
{
if( !isValidArtistData( requestData ) )
{
return;
}
Echonest::Artist artist( requestData.input.toString() );
QNetworkReply* reply = artist.fetchTerms( Echonest::Artist::Weight );
@@ -165,7 +173,7 @@ EchonestPlugin::getArtistTerms( const Tomahawk::InfoSystem::InfoRequestData &req
void
EchonestPlugin::getMiscTopTerms( const Tomahawk::InfoSystem::InfoRequestData &requestData )
EchonestPlugin::getMiscTopTerms( const Tomahawk::InfoSystem::InfoRequestData& requestData )
{
QNetworkReply* reply = Echonest::Artist::topTerms( 20 );
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
@@ -180,7 +188,7 @@ EchonestPlugin::getArtistBiographySlot()
Echonest::Artist artist = artistFromReply( reply );
Echonest::BiographyList biographies = artist.biographies();
QVariantMap biographyMap;
Q_FOREACH( const Echonest::Biography& biography, biographies )
Q_FOREACH( const Echonest::Biography & biography, biographies )
{
QVariantHash siteData;
siteData[ "site" ] = biography.site();
@@ -227,7 +235,8 @@ EchonestPlugin::getArtistTermsSlot()
Echonest::Artist artist = artistFromReply( reply );
Echonest::TermList terms = artist.terms();
QVariantMap termsMap;
Q_FOREACH( const Echonest::Term& term, terms ) {
Q_FOREACH( const Echonest::Term & term, terms )
{
QVariantHash termHash;
termHash[ "weight" ] = QString::number( term.weight() );
termHash[ "frequency" ] = QString::number( term.frequency() );
@@ -245,7 +254,8 @@ EchonestPlugin::getMiscTopSlot()
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
Echonest::TermList terms = Echonest::Artist::parseTopTerms( reply );
QVariantMap termsMap;
Q_FOREACH( const Echonest::Term& term, terms ) {
Q_FOREACH( const Echonest::Term & term, terms )
{
QVariantHash termHash;
termHash[ "weight" ] = QString::number( term.weight() );
termHash[ "frequency" ] = QString::number( term.frequency() );
@@ -258,7 +268,7 @@ EchonestPlugin::getMiscTopSlot()
bool
EchonestPlugin::isValidArtistData( const Tomahawk::InfoSystem::InfoRequestData &requestData )
EchonestPlugin::isValidArtistData( const Tomahawk::InfoSystem::InfoRequestData& requestData )
{
if ( requestData.input.isNull() || !requestData.input.isValid() || !requestData.input.canConvert< QString >() )
{
@@ -276,7 +286,7 @@ EchonestPlugin::isValidArtistData( const Tomahawk::InfoSystem::InfoRequestData &
bool
EchonestPlugin::isValidTrackData( const Tomahawk::InfoSystem::InfoRequestData &requestData )
EchonestPlugin::isValidTrackData( const Tomahawk::InfoSystem::InfoRequestData& requestData )
{
if ( requestData.input.isNull() || !requestData.input.isValid() || !requestData.input.canConvert< QString >() )
{
@@ -301,10 +311,13 @@ EchonestPlugin::isValidTrackData( const Tomahawk::InfoSystem::InfoRequestData &r
Echonest::Artist
EchonestPlugin::artistFromReply( QNetworkReply* reply )
{
Echonest::Artist artist = reply->property("artist").value<Echonest::Artist>();
try {
Echonest::Artist artist = reply->property( "artist" ).value<Echonest::Artist>();
try
{
artist.parseProfile( reply );
} catch( const Echonest::ParseError& e ) {
}
catch( const Echonest::ParseError& e )
{
qWarning() << "Caught parser error from echonest!" << e.what();
}
return artist;

View File

@@ -42,13 +42,13 @@ class INFOPLUGINDLLEXPORT EchonestPlugin : public InfoPlugin
Q_OBJECT
Q_INTERFACES( Tomahawk::InfoSystem::InfoPlugin )
public:
public:
EchonestPlugin();
virtual ~EchonestPlugin();
protected slots:
protected slots:
virtual void init();
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
@@ -62,19 +62,19 @@ protected slots:
Q_UNUSED( requestData );
}
private:
void getSongProfile( const Tomahawk::InfoSystem::InfoRequestData &requestData, const QString &item = QString() );
void getArtistBiography( const Tomahawk::InfoSystem::InfoRequestData &requestData );
void getArtistFamiliarity( const Tomahawk::InfoSystem::InfoRequestData &requestData );
void getArtistHotttnesss( const Tomahawk::InfoSystem::InfoRequestData &requestData );
void getArtistTerms( const Tomahawk::InfoSystem::InfoRequestData &requestData );
void getMiscTopTerms( const Tomahawk::InfoSystem::InfoRequestData &requestData );
private:
void getSongProfile( const Tomahawk::InfoSystem::InfoRequestData& requestData, const QString& item = QString() );
void getArtistBiography( const Tomahawk::InfoSystem::InfoRequestData& requestData );
void getArtistFamiliarity( const Tomahawk::InfoSystem::InfoRequestData& requestData );
void getArtistHotttnesss( const Tomahawk::InfoSystem::InfoRequestData& requestData );
void getArtistTerms( const Tomahawk::InfoSystem::InfoRequestData& requestData );
void getMiscTopTerms( const Tomahawk::InfoSystem::InfoRequestData& requestData );
bool isValidArtistData( const Tomahawk::InfoSystem::InfoRequestData &requestData );
bool isValidTrackData( const Tomahawk::InfoSystem::InfoRequestData &requestData );
bool isValidArtistData( const Tomahawk::InfoSystem::InfoRequestData& requestData );
bool isValidTrackData( const Tomahawk::InfoSystem::InfoRequestData& requestData );
Echonest::Artist artistFromReply( QNetworkReply* );
private slots:
private slots:
void getArtistBiographySlot();
void getArtistFamiliaritySlot();
void getArtistHotttnesssSlot();

View File

@@ -176,7 +176,7 @@ HypemPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
criteria["chart_source"] = hash["chart_source"];
/// @todo
/// set cache time based on wether requested type is 3day, lastweek or recent.
emit getCachedInfo( criteria, Q_INT64_C(86400000), requestData );
emit getCachedInfo( criteria, Q_INT64_C( 86400000 ), requestData );
}
void
@@ -189,7 +189,7 @@ HypemPlugin::fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData reque
}
Tomahawk::InfoSystem::InfoStringHash criteria;
emit getCachedInfo( criteria, Q_INT64_C(0), requestData );
emit getCachedInfo( criteria, Q_INT64_C( 0 ), requestData );
}
void
@@ -202,7 +202,7 @@ HypemPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSys
{
/// Fetch the chart, we need source and id
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "InfoChart not in cache! Fetching...";
QUrl url = QUrl( QString( HYPEM_URL "%1/%2" ).arg( criteria["chart_id"].toLower() ).arg(HYPEM_END_URL) );
QUrl url = QUrl( QString( HYPEM_URL "%1/%2" ).arg( criteria["chart_id"].toLower() ).arg( HYPEM_END_URL ) );
qDebug() << Q_FUNC_INFO << "Getting chart url" << url;
QNetworkReply* reply = Tomahawk::Utils::nam()->get( QNetworkRequest( url ) );
@@ -245,32 +245,40 @@ HypemPlugin::chartTypes()
QVariantMap charts;
foreach(QVariant types, m_types )
foreach( QVariant types, m_types )
{
QList< InfoStringHash > chart_types;
QList< InfoStringHash > pop_charts;
InfoStringHash c;
if(types.toString() != "Artists")
if( types.toString() != "Artists" )
{
if(types.toString() == "Tracks")
if( types.toString() == "Tracks" )
{
foreach(QVariant trackType, m_trackTypes)
foreach( QVariant trackType, m_trackTypes )
{
QString typeId;
if(trackType.toString() == "Last 3 Days")
if( trackType.toString() == "Last 3 Days" )
{
typeId = "popular/3day";
}
if(trackType.toString() == "Last Week")
if( trackType.toString() == "Last Week" )
{
typeId = "popular/lastweek";
}
if(trackType.toString() == "No Remixes")
if( trackType.toString() == "No Remixes" )
{
typeId = "popular/noremix";
}
if(trackType.toString() == "On Twitter")
if( trackType.toString() == "On Twitter" )
{
typeId = "popular/twitter";
}
c[ "id" ] = typeId;
c[ "label" ] = trackType.toString();
@@ -281,9 +289,9 @@ HypemPlugin::chartTypes()
chart_types.append( pop_charts );
}
else if(types.toString() == "Recent by Tag")
else if( types.toString() == "Recent by Tag" )
{
foreach(QVariant tagTypes, m_byTagTypes)
foreach( QVariant tagTypes, m_byTagTypes )
{
c[ "id" ] = "tags/" + tagTypes.toString().toLower();
@@ -294,7 +302,8 @@ HypemPlugin::chartTypes()
}
}else
}
else
{
InfoStringHash c;
c[ "id" ] = "popular/artists";
@@ -338,9 +347,13 @@ HypemPlugin::chartReturned()
QStringList top_artists;
if ( url.contains( "artists" ) )
{
setChartType( Artist );
}
else
{
setChartType( Track );
}
foreach ( QVariant result, res )
{
@@ -363,7 +376,9 @@ HypemPlugin::chartReturned()
if ( chartType() == Artist )
{
top_artists << artist;
}
}
}
@@ -394,10 +409,12 @@ HypemPlugin::chartReturned()
criteria[ "chart_source" ] = origData[ "chart_source" ];
/// @todo
/// set cache time based on wether requested type is 3day, lastweek or recent.
emit updateCache( criteria, Q_INT64_C(86400000), requestData.type, returnedData );
emit updateCache( criteria, Q_INT64_C( 86400000 ), requestData.type, returnedData );
}
else
{
qDebug() << "Network error in fetching chart:" << reply->url().toString();
}
}

View File

@@ -41,25 +41,32 @@ class INFOPLUGINDLLEXPORT HypemPlugin : public InfoPlugin
Q_OBJECT
Q_INTERFACES( Tomahawk::InfoSystem::InfoPlugin )
public:
public:
HypemPlugin();
virtual ~HypemPlugin();
enum ChartType {
enum ChartType
{
None = 0x00,
Track = 0x01,
Album = 0x02,
Artist = 0x04
};
void setChartType( ChartType type ) { m_chartType = type; }
ChartType chartType() const { return m_chartType; }
void setChartType( ChartType type )
{
m_chartType = type;
}
ChartType chartType() const
{
return m_chartType;
}
public slots:
public slots:
void chartReturned();
void chartTypes();
protected slots:
protected slots:
virtual void init();
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
@@ -69,7 +76,7 @@ protected slots:
}
private:
private:
void fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData );
void fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requestData );
void dataError( Tomahawk::InfoSystem::InfoRequestData requestData );

View File

@@ -65,7 +65,7 @@ MusicBrainzPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
Tomahawk::InfoSystem::InfoStringHash criteria;
criteria["artist"] = hash["artist"];
emit getCachedInfo( criteria, Q_INT64_C(2419200000), requestData );
emit getCachedInfo( criteria, Q_INT64_C( 2419200000 ), requestData );
break;
}
@@ -75,7 +75,7 @@ MusicBrainzPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
criteria["artist"] = hash["artist"];
criteria["album"] = hash["album"];
emit getCachedInfo( criteria, Q_INT64_C(2419200000), requestData );
emit getCachedInfo( criteria, Q_INT64_C( 2419200000 ), requestData );
break;
}
@@ -97,7 +97,7 @@ MusicBrainzPlugin::notInCacheSlot( InfoStringHash criteria, InfoRequestData requ
{
case InfoArtistReleases:
{
querySt.append( QString( "artist:\"%1\"" ).arg(criteria["artist"]) );
querySt.append( QString( "artist:\"%1\"" ).arg( criteria["artist"] ) );
querySt.append( " AND (type:album OR type:ep)" );
querySt.append( " AND status:official" );
querySt.append( " AND NOT secondarytype:live" );
@@ -120,8 +120,8 @@ MusicBrainzPlugin::notInCacheSlot( InfoStringHash criteria, InfoRequestData requ
}
case InfoAlbumSongs:
{
querySt.append( QString( "release:\"%1\"" ).arg(criteria["album"]) );
querySt.append( QString( " AND artist:\"%1\"" ).arg(criteria["artist"]) );
querySt.append( QString( "release:\"%1\"" ).arg( criteria["album"] ) );
querySt.append( QString( " AND artist:\"%1\"" ).arg( criteria["artist"] ) );
// not pre-filtering will yield more than 100 results which we dont handle atm. But since we only take the first result anyway that wont hurt
QString requestString( "http://musicbrainz.org/ws/2/release" );
@@ -154,7 +154,9 @@ MusicBrainzPlugin::gotReleaseGroupsSlot()
{
QNetworkReply* oldReply = qobject_cast<QNetworkReply*>( sender() );
if ( !oldReply )
return; //timeout will handle it
{
return; //timeout will handle it
}
QDomDocument doc;
doc.setContent( oldReply->readAll() );
@@ -172,14 +174,14 @@ MusicBrainzPlugin::gotReleaseGroupsSlot()
{
case InfoArtistReleases:
{
QString popularId = releaseGroupsNL.at(0).firstChildElement( "artist-credit" ).firstChildElement( "name-credit" ).firstChildElement( "artist" ).attribute( "id" );
QString popularId = releaseGroupsNL.at( 0 ).firstChildElement( "artist-credit" ).firstChildElement( "name-credit" ).firstChildElement( "artist" ).attribute( "id" );
QStringList albums;
for ( int i = 0; i < releaseGroupsNL.count(); i++ )
{
QString groupTitle = releaseGroupsNL.at(i).firstChildElement("title").text();
QString a = releaseGroupsNL.at(i).firstChildElement( "artist-credit" ).firstChildElement( "name-credit" ).firstChildElement( "artist" ).firstChildElement( "name" ).text();
QString id = releaseGroupsNL.at(i).firstChildElement( "artist-credit" ).firstChildElement( "name-credit" ).firstChildElement( "artist" ).attribute( "id" );
QString groupTitle = releaseGroupsNL.at( i ).firstChildElement( "title" ).text();
QString a = releaseGroupsNL.at( i ).firstChildElement( "artist-credit" ).firstChildElement( "name-credit" ).firstChildElement( "artist" ).firstChildElement( "name" ).text();
QString id = releaseGroupsNL.at( i ).firstChildElement( "artist-credit" ).firstChildElement( "name-credit" ).firstChildElement( "artist" ).attribute( "id" );
if ( !albums.contains( groupTitle ) && id == popularId && a.normalized( QString::NormalizationForm_KC ) == hash["artist"].normalized( QString::NormalizationForm_KC ) )
{
albums << groupTitle;
@@ -194,7 +196,7 @@ MusicBrainzPlugin::gotReleaseGroupsSlot()
Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash>();
Tomahawk::InfoSystem::InfoStringHash criteria;
criteria["artist"] = origData["artist"];
emit updateCache( criteria, Q_INT64_C(0), requestData.type, returnedData );
emit updateCache( criteria, Q_INT64_C( 0 ), requestData.type, returnedData );
break;
}
@@ -212,7 +214,9 @@ MusicBrainzPlugin::gotReleasesSlot()
{
QNetworkReply* oldReply = qobject_cast<QNetworkReply*>( sender() );
if ( !oldReply )
return; //timeout will handle it
{
return; //timeout will handle it
}
QDomDocument doc;
doc.setContent( oldReply->readAll() );
@@ -230,7 +234,7 @@ MusicBrainzPlugin::gotReleasesSlot()
case InfoAlbumSongs:
{
// we can simply use the first result as they are sorted by score
QString release_id = releasesNL.at(0).toElement().attribute( "id" );
QString release_id = releasesNL.at( 0 ).toElement().attribute( "id" );
QString requestString = QString( "http://musicbrainz.org/ws/2/release/%1" ).arg( release_id );
QUrl url( requestString );
@@ -259,7 +263,9 @@ MusicBrainzPlugin::gotRecordingsSlot()
{
QNetworkReply* reply = qobject_cast< QNetworkReply* >( sender() );
if ( !reply )
return; //timeout will handle it
{
return; //timeout will handle it
}
QDomDocument doc;
doc.setContent( reply->readAll() );
@@ -272,15 +278,15 @@ MusicBrainzPlugin::gotRecordingsSlot()
}
QDomNodeList tracksNL = mediumList.at(0).toElement().elementsByTagName( "track" );
QDomNodeList tracksNL = mediumList.at( 0 ).toElement().elementsByTagName( "track" );
QStringList tracksSL;
for ( int i = 0; i < tracksNL.count(); i++ )
{
QString track = tracksNL.at(i).firstChildElement( "recording" ).firstChildElement( "title" ).text();
QString track = tracksNL.at( i ).firstChildElement( "recording" ).firstChildElement( "title" ).text();
if ( !tracksSL.contains( track ) )
{
tracksSL << track;
tDebug(LOGVERBOSE) << Q_FUNC_INFO << track;
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << track;
}
}
@@ -293,7 +299,7 @@ MusicBrainzPlugin::gotRecordingsSlot()
Tomahawk::InfoSystem::InfoStringHash criteria;
criteria["artist"] = origData["artist"];
criteria["album"] = origData["album"];
emit updateCache( criteria, Q_INT64_C(0), requestData.type, returnedData );
emit updateCache( criteria, Q_INT64_C( 0 ), requestData.type, returnedData );
}
Q_EXPORT_PLUGIN2( Tomahawk::InfoSystem::InfoPlugin, Tomahawk::InfoSystem::MusicBrainzPlugin )

View File

@@ -39,11 +39,11 @@ class INFOPLUGINDLLEXPORT MusicBrainzPlugin : public InfoPlugin
Q_OBJECT
Q_INTERFACES( Tomahawk::InfoSystem::InfoPlugin )
public:
public:
MusicBrainzPlugin();
virtual ~MusicBrainzPlugin();
protected slots:
protected slots:
virtual void init() {}
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void notInCacheSlot( InfoStringHash criteria, InfoRequestData requestData );
@@ -54,7 +54,7 @@ protected slots:
}
private slots:
private slots:
void gotReleaseGroupsSlot();
void gotReleasesSlot();

View File

@@ -51,7 +51,9 @@ MusixMatchPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
{
tDebug() << Q_FUNC_INFO;
if( !isValidTrackData( requestData ) || requestData.type != Tomahawk::InfoSystem::InfoTrackLyrics )
{
return;
}
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
QString artist = hash["artist"];
@@ -80,7 +82,7 @@ bool
MusixMatchPlugin::isValidTrackData( Tomahawk::InfoSystem::InfoRequestData requestData )
{
tDebug() << Q_FUNC_INFO;
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
{
emit info( requestData, QVariant() );
@@ -111,18 +113,20 @@ MusixMatchPlugin::trackSearchSlot()
tDebug() << Q_FUNC_INFO;
QNetworkReply* oldReply = qobject_cast<QNetworkReply*>( sender() );
if ( !oldReply )
return; //timeout will handle it
{
return; //timeout will handle it
}
QDomDocument doc;
doc.setContent(oldReply->readAll());
doc.setContent( oldReply->readAll() );
qDebug() << doc.toString();
QDomNodeList domNodeList = doc.elementsByTagName("track_id");
QDomNodeList domNodeList = doc.elementsByTagName( "track_id" );
if ( domNodeList.isEmpty() )
{
emit info( oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
return;
}
QString track_id = domNodeList.at(0).toElement().text();
QString track_id = domNodeList.at( 0 ).toElement().text();
QString requestString( "http://api.musixmatch.com/ws/1.1/track.lyrics.get?track_id=%1&format=xml&apikey=%2" );
QUrl url( requestString );
@@ -141,7 +145,9 @@ MusixMatchPlugin::trackLyricsSlot()
tDebug() << Q_FUNC_INFO;
QNetworkReply* reply = qobject_cast< QNetworkReply* >( sender() );
if ( !reply )
return; //timeout will handle it
{
return; //timeout will handle it
}
QDomDocument doc;
doc.setContent( reply->readAll() );
@@ -151,7 +157,7 @@ MusixMatchPlugin::trackLyricsSlot()
emit info( reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
return;
}
QString lyrics = domNodeList.at(0).toElement().text();
QString lyrics = domNodeList.at( 0 ).toElement().text();
emit info( reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant( lyrics ) );
}

View File

@@ -40,15 +40,15 @@ class INFOPLUGINDLLEXPORT MusixMatchPlugin : public InfoPlugin
Q_OBJECT
Q_INTERFACES( Tomahawk::InfoSystem::InfoPlugin )
public:
public:
MusixMatchPlugin();
virtual ~MusixMatchPlugin();
public slots:
public slots:
void trackSearchSlot();
void trackLyricsSlot();
protected slots:
protected slots:
virtual void init() {}
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
@@ -57,15 +57,15 @@ protected slots:
Q_UNUSED( pushData );
}
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
{
Q_UNUSED( criteria );
Q_UNUSED( requestData );
}
private:
private:
bool isValidTrackData( Tomahawk::InfoSystem::InfoRequestData requestData );
QString m_apiKey;
};

View File

@@ -94,18 +94,18 @@ NewReleasesPlugin::init()
QVariant data = TomahawkUtils::Cache::instance()->getData( "NewReleasesPlugin", "nr_sources" );
if ( data.canConvert< QList< Tomahawk::InfoSystem::InfoStringHash > >() )
{
const QList< Tomahawk::InfoSystem::InfoStringHash > sourceList = data.value< QList< Tomahawk::InfoSystem::InfoStringHash > >();
foreach ( const Tomahawk::InfoSystem::InfoStringHash &sourceHash, sourceList )
{
bool ok;
qlonglong maxAge = getMaxAge( QString( sourceHash[ "nr_expires" ] ).toLongLong( &ok ) );
if ( !ok || maxAge <= 0 )
{
// This source has expired.
m_refetchSource << sourceHash[ "nr_source" ];
}
m_nrSources << sourceHash;
}
const QList< Tomahawk::InfoSystem::InfoStringHash > sourceList = data.value< QList< Tomahawk::InfoSystem::InfoStringHash > >();
foreach ( const Tomahawk::InfoSystem::InfoStringHash & sourceHash, sourceList )
{
bool ok;
qlonglong maxAge = getMaxAge( QString( sourceHash[ "nr_expires" ] ).toLongLong( &ok ) );
if ( !ok || maxAge <= 0 )
{
// This source has expired.
m_refetchSource << sourceHash[ "nr_source" ];
}
m_nrSources << sourceHash;
}
}
else
{
@@ -138,42 +138,42 @@ NewReleasesPlugin::getInfo( InfoRequestData requestData )
switch( requestData.type )
{
case InfoNewRelease:
/// We need something to check if the request is actually ment to go to this plugin
if ( !hash.contains( "nr_source" ) )
{
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Hash did not contain required param!";
dataError( requestData );
break;
}
else
{
foreach ( const Tomahawk::InfoSystem::InfoStringHash &sourceHash, m_nrSources )
case InfoNewRelease:
/// We need something to check if the request is actually ment to go to this plugin
if ( !hash.contains( "nr_source" ) )
{
if ( sourceHash[ "nr_source" ] == hash[ "nr_source" ] )
{
foundSource = true;
}
}
if ( !foundSource )
{
tDebug ( LOGVERBOSE ) << Q_FUNC_INFO << "Hash did not contain source " << hash["nr_source"];
dataError ( requestData );
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Hash did not contain required param!";
dataError( requestData );
break;
}
else
{
foreach ( const Tomahawk::InfoSystem::InfoStringHash & sourceHash, m_nrSources )
{
if ( sourceHash[ "nr_source" ] == hash[ "nr_source" ] )
{
foundSource = true;
}
}
}
fetchNRFromCache( requestData );
break;
if ( !foundSource )
{
tDebug ( LOGVERBOSE ) << Q_FUNC_INFO << "Hash did not contain source " << hash["nr_source"];
dataError ( requestData );
break;
}
case InfoNewReleaseCapabilities:
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Requesting InfoNewReleaseCapabilities from cache";
fetchNRCapabilitiesFromCache( requestData );
break;
}
fetchNRFromCache( requestData );
break;
default:
dataError( requestData );
case InfoNewReleaseCapabilities:
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Requesting InfoNewReleaseCapabilities from cache";
fetchNRCapabilitiesFromCache( requestData );
break;
default:
dataError( requestData );
}
}
@@ -244,7 +244,7 @@ NewReleasesPlugin::fetchNRCapabilitiesFromCache( InfoRequestData requestData )
}
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Fetching fetchNRCapabilitiesFromCache";
emit getCachedInfo ( criteria, Q_INT64_C(172800000) /* 2 days */, requestData );
emit getCachedInfo ( criteria, Q_INT64_C( 172800000 ) /* 2 days */, requestData );
}
@@ -316,7 +316,7 @@ NewReleasesPlugin::nrSourcesList()
return;
}
foreach ( const QVariant &rsource, sources )
foreach ( const QVariant & rsource, sources )
{
/**
@@ -335,7 +335,7 @@ NewReleasesPlugin::nrSourcesList()
{
for ( int i = 0; i < m_nrSources.size(); i++ )
{
const Tomahawk::InfoSystem::InfoStringHash &hash = m_nrSources.at( i );
const Tomahawk::InfoSystem::InfoStringHash& hash = m_nrSources.at( i );
if ( hash[ "nr_source" ] == source )
{
tDebug() << Q_FUNC_INFO << "Removing invalid source" << source;
@@ -356,13 +356,13 @@ NewReleasesPlugin::nrSourcesList()
const QString headerExpiration = reply->rawHeader( QString( tmpSource ).toLocal8Bit() );
const qlonglong maxAge = getMaxAge( headerExpiration.toLocal8Bit() );
const qlonglong expires = headerExpiration.toLongLong(&ok);
const qlonglong expires = headerExpiration.toLongLong( &ok );
Tomahawk::InfoSystem::InfoStringHash source_expire;
if ( ok )
{
source_expire[ "nr_source" ] = source;
source_expire[ "nr_expires" ] = QString::number(expires);
source_expire[ "nr_expires" ] = QString::number( expires );
m_nrSources << source_expire;
}
@@ -469,7 +469,7 @@ NewReleasesPlugin::nrList()
{
// Itunes has geographic-area based releases. So we build a breadcrumb of
// iTunes - Country - Featured/Just Released/New Releases - Genre
foreach ( const QVariant &nrObj, res.values() )
foreach ( const QVariant & nrObj, res.values() )
{
if ( !nrObj.toMap().isEmpty() )
{
@@ -483,7 +483,9 @@ NewReleasesPlugin::nrList()
// We only have albums in newReleases
if ( type != "Albums" || name.isEmpty() )
{
continue;
}
QString extra;
if ( !geo.isEmpty() )
@@ -491,7 +493,8 @@ NewReleasesPlugin::nrList()
if ( !m_cachedCountries.contains( geo ) )
{
extra = Tomahawk::CountryUtils::fullCountryFromCode( geo );
if ( extra.isEmpty() || extra.isNull() ){
if ( extra.isEmpty() || extra.isNull() )
{
qWarning() << "Geo string seems to be off!" << geo;
continue;
}
@@ -523,10 +526,12 @@ NewReleasesPlugin::nrList()
/**
* If this item has expired, set it to 0.
*/
nr[ "expires" ] = ( ok ? QString::number (expires ) : QString::number( 0 ) );
nr[ "expires" ] = ( ok ? QString::number ( expires ) : QString::number( 0 ) );
if ( isDefault )
{
nr[ "default" ] = "true";
}
QList< Tomahawk::InfoSystem::InfoStringHash > extraTypeData = extraType[ nrExtraType ][ extra ].value< QList< Tomahawk::InfoSystem::InfoStringHash > >();
@@ -543,7 +548,7 @@ NewReleasesPlugin::nrList()
}
}
foreach ( const QString& nr, extraType.keys() )
foreach ( const QString & nr, extraType.keys() )
{
newreleases[ nr ] = extraType[ nr ];
}
@@ -556,7 +561,7 @@ NewReleasesPlugin::nrList()
}
else
{
foreach ( const QVariant &nrObj, res.values() )
foreach ( const QVariant & nrObj, res.values() )
{
if ( !nrObj.toMap().isEmpty() )
{
@@ -581,7 +586,9 @@ NewReleasesPlugin::nrList()
extraType[ extra ][ type ] = QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( extraTypeData );
}
else
{
albumNRs.append( nr );
}
}
else
{
@@ -591,14 +598,16 @@ NewReleasesPlugin::nrList()
}
foreach ( const QString& c, extraType.keys() )
foreach ( const QString & c, extraType.keys() )
{
newreleases[ c ] = extraType[ c ];
}
}
if ( !albumNRs.isEmpty() )
{
newreleases.insert ( tr ( "Albums" ), QVariant::fromValue< QList< Tomahawk::InfoSystem::InfoStringHash > >( albumNRs ) );
}
/// @note For displaying purposes, upper the first letter
/// @note Remeber to lower it when fetching this!
@@ -629,14 +638,14 @@ NewReleasesPlugin::nrList()
/**
* We can cache it the lot for 2 days, it will be checked on next request
*/
emit updateCache( criteria, Q_INT64_C(172800000) /* 2 days */, request.type, m_allNRsMap );
emit updateCache( criteria, Q_INT64_C( 172800000 ) /* 2 days */, request.type, m_allNRsMap );
}
m_cachedRequests.clear();
}
}
qlonglong
NewReleasesPlugin::getMaxAge( const QByteArray &rawHeader ) const
NewReleasesPlugin::getMaxAge( const QByteArray& rawHeader ) const
{
bool ok;
qlonglong expires = QString( rawHeader ).toLongLong( &ok );
@@ -650,12 +659,12 @@ NewReleasesPlugin::getMaxAge( const QByteArray &rawHeader ) const
qlonglong
NewReleasesPlugin::getMaxAge( const qlonglong expires ) const
{
qlonglong currentEpoch = QDateTime::currentMSecsSinceEpoch()/1000;
qlonglong expiresInSeconds = expires-currentEpoch;
qlonglong currentEpoch = QDateTime::currentMSecsSinceEpoch() / 1000;
qlonglong expiresInSeconds = expires - currentEpoch;
if ( expiresInSeconds > 0 )
{
return ( qlonglong )expiresInSeconds*1000;
return ( qlonglong )expiresInSeconds * 1000;
}
return 0;
}
@@ -722,10 +731,12 @@ NewReleasesPlugin::nrReturned()
/**
* If the item has expired, cache it for one hour and try and refetch later
*/
emit updateCache( criteria, (maxAge == Q_INT64_C(0) ? (3600000) /* One hour */ : maxAge), requestData.type, returnedData );
emit updateCache( criteria, ( maxAge == Q_INT64_C( 0 ) ? ( 3600000 ) /* One hour */ : maxAge ), requestData.type, returnedData );
}
else
{
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Network error in fetching newrelease:" << reply->url().toString();
}
}
Q_EXPORT_PLUGIN2( Tomahawk::InfoSystem::InfoPlugin, Tomahawk::InfoSystem::NewReleasesPlugin )

View File

@@ -43,11 +43,11 @@ class INFOPLUGINDLLEXPORT NewReleasesPlugin : public InfoPlugin
Q_OBJECT
Q_INTERFACES( Tomahawk::InfoSystem::InfoPlugin )
public:
public:
NewReleasesPlugin();
virtual ~NewReleasesPlugin();
protected slots:
protected slots:
virtual void init();
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
@@ -72,7 +72,7 @@ protected slots:
*/
void nrReturned();
private:
private:
/**
* Requests newrelease list for each source in m_chartSources
*/
@@ -86,7 +86,7 @@ private:
void fetchNRCapabilitiesFromCache( Tomahawk::InfoSystem::InfoRequestData requestData );
void dataError( Tomahawk::InfoSystem::InfoRequestData requestData );
qlonglong getMaxAge( const QByteArray &rawHeader ) const;
qlonglong getMaxAge( const QByteArray& rawHeader ) const;
qlonglong getMaxAge( const qlonglong expires ) const;
QList< Tomahawk::InfoSystem::InfoStringHash > m_nrSources;

View File

@@ -68,7 +68,7 @@ RoviPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
criteria["artist"] = hash["artist"];
criteria["album"] = hash["album"];
emit getCachedInfo( criteria, Q_INT64_C(0), requestData );
emit getCachedInfo( criteria, Q_INT64_C( 0 ), requestData );
}
@@ -105,7 +105,9 @@ void
RoviPlugin::albumLookupError( QNetworkReply::NetworkError error )
{
if ( error == QNetworkReply::NoError )
{
return;
}
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
Q_ASSERT( reply );
@@ -124,7 +126,9 @@ RoviPlugin::albumLookupFinished()
Q_ASSERT( reply );
if ( reply->error() != QNetworkReply::NoError )
{
return;
}
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
@@ -157,11 +161,13 @@ RoviPlugin::albumLookupFinished()
QStringList trackNameList;
foreach ( const QVariant& track, tracks )
foreach ( const QVariant & track, tracks )
{
const QVariantMap trackData = track.toMap();
if ( trackData.contains( "title" ) )
{
trackNameList << trackData[ "title" ].toString();
}
}
QVariantMap returnedData;
@@ -173,7 +179,7 @@ RoviPlugin::albumLookupFinished()
criteria["artist"] = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash>()["artist"];
criteria["album"] = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash>()["album"];
emit updateCache( criteria, Q_INT64_C(0), requestData.type, returnedData );
emit updateCache( criteria, Q_INT64_C( 0 ), requestData.type, returnedData );
}

View File

@@ -41,13 +41,13 @@ class INFOPLUGINDLLEXPORT RoviPlugin : public InfoPlugin
Q_OBJECT
Q_INTERFACES( Tomahawk::InfoSystem::InfoPlugin )
public:
public:
RoviPlugin();
virtual ~RoviPlugin();
protected:
protected:
virtual void init() {}
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
@@ -57,10 +57,10 @@ protected:
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
private slots:
private slots:
void albumLookupFinished();
void albumLookupError( QNetworkReply::NetworkError );
private:
private:
QNetworkReply* makeRequest( QUrl url );
QByteArray generateSig() const;

View File

@@ -117,7 +117,7 @@ SpotifyPlugin::fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData )
criteria["chart_id"] = hash["chart_id"];
criteria["chart_source"] = hash["chart_source"];
emit getCachedInfo( criteria, Q_INT64_C(86400000) /* Expire chart cache in 1 day */, requestData );
emit getCachedInfo( criteria, Q_INT64_C( 86400000 ) /* Expire chart cache in 1 day */, requestData );
}
@@ -132,7 +132,7 @@ SpotifyPlugin::fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData req
Tomahawk::InfoSystem::InfoStringHash criteria;
criteria[ "InfoChartCapabilities" ] = "spotifyplugin";
emit getCachedInfo( criteria, Q_INT64_C(604800000), requestData );
emit getCachedInfo( criteria, Q_INT64_C( 604800000 ), requestData );
}
@@ -159,7 +159,9 @@ SpotifyPlugin::notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, To
// we never need to re-fetch
if ( !m_allChartsMap.isEmpty() )
{
return;
}
/// We need to fetch possible types before they are asked for
tDebug() << "SpotifyPlugin: InfoChart fetching possible resources";
@@ -215,44 +217,48 @@ SpotifyPlugin::chartTypes()
QVariantMap charts;
foreach( QVariant geos, chartObj.value( "Charts" ).toList().takeLast().toMap().value( "geo" ).toList() )
{
const QString geo = geos.toMap().value( "name" ).toString();
const QString geoId = geos.toMap().value( "id" ).toString();
QString country;
const QString geo = geos.toMap().value( "name" ).toString();
const QString geoId = geos.toMap().value( "id" ).toString();
QString country;
if( geo == "For me" )
continue; /// country = geo; Lets use this later, when we can get the spotify username from tomahawk
else if( geo == "Everywhere" )
country = geo;
else
{
QLocale l( QString( "en_%1" ).arg( geo ) );
country = Tomahawk::CountryUtils::fullCountryFromCode( geo );
if( geo == "For me" )
{
continue; /// country = geo; Lets use this later, when we can get the spotify username from tomahawk
}
else if( geo == "Everywhere" )
{
country = geo;
}
else
{
QLocale l( QString( "en_%1" ).arg( geo ) );
country = Tomahawk::CountryUtils::fullCountryFromCode( geo );
for ( int i = 1; i < country.size(); i++ )
{
if ( country.at( i ).isUpper() )
{
country.insert( i, " " );
i++;
}
}
}
for ( int i = 1; i < country.size(); i++ )
{
if ( country.at( i ).isUpper() )
{
country.insert( i, " " );
i++;
}
}
}
QList< InfoStringHash > chart_types;
foreach( QVariant types, chartObj.value( "Charts" ).toList().takeFirst().toMap().value( "types" ).toList() )
{
QString type = types.toMap().value( "id" ).toString();
QString label = types.toMap().value( "name" ).toString();
QList< InfoStringHash > chart_types;
foreach( QVariant types, chartObj.value( "Charts" ).toList().takeFirst().toMap().value( "types" ).toList() )
{
QString type = types.toMap().value( "id" ).toString();
QString label = types.toMap().value( "name" ).toString();
InfoStringHash c;
c[ "id" ] = type + "/" + geoId;
c[ "label" ] = label;
c[ "type" ] = type;
InfoStringHash c;
c[ "id" ] = type + "/" + geoId;
c[ "label" ] = label;
c[ "type" ] = type;
chart_types.append( c );
}
chart_types.append( c );
}
charts.insert( country.toUtf8(), QVariant::fromValue<QList< InfoStringHash > >( chart_types ) );
charts.insert( country.toUtf8(), QVariant::fromValue<QList< InfoStringHash > >( chart_types ) );
}
QVariantMap defaultMap;
@@ -273,7 +279,7 @@ SpotifyPlugin::chartTypes()
emit info( request, m_allChartsMap );
Tomahawk::InfoSystem::InfoStringHash criteria;
criteria[ "InfoChartCapabilities" ] = "spotifyplugin";
emit updateCache( criteria, Q_INT64_C(604800000), request.type, m_allChartsMap );
emit updateCache( criteria, Q_INT64_C( 604800000 ), request.type, m_allChartsMap );
}
m_cachedRequests.clear();
}
@@ -305,13 +311,21 @@ SpotifyPlugin::chartReturned()
QStringList top_artists;
if( url.contains( "albums" ) )
{
setChartType( Album );
}
else if( url.contains( "tracks" ) )
{
setChartType( Track );
}
else if( url.contains( "artists" ) )
{
setChartType( Artist );
}
else
{
setChartType( None );
}
foreach( QVariant result, res.value( "toplist" ).toMap().value( "result" ).toList() )
{
@@ -380,10 +394,12 @@ SpotifyPlugin::chartReturned()
Tomahawk::InfoSystem::InfoStringHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
criteria[ "chart_id" ] = origData[ "chart_id" ];
criteria[ "chart_source" ] = origData[ "chart_source" ];
emit updateCache( criteria, Q_INT64_C(86400000), requestData.type, returnedData );
emit updateCache( criteria, Q_INT64_C( 86400000 ), requestData.type, returnedData );
}
else
{
qDebug() << "Network error in fetching chart:" << reply->url().toString();
}
}

View File

@@ -43,25 +43,32 @@ class INFOPLUGINDLLEXPORT SpotifyPlugin : public InfoPlugin
Q_OBJECT
Q_INTERFACES( Tomahawk::InfoSystem::InfoPlugin )
public:
public:
SpotifyPlugin();
virtual ~SpotifyPlugin();
enum ChartType {
enum ChartType
{
None = 0x00,
Track = 0x01,
Album = 0x02,
Artist = 0x04
};
void setChartType( ChartType type ) { m_chartType = type; }
ChartType chartType() const { return m_chartType; }
void setChartType( ChartType type )
{
m_chartType = type;
}
ChartType chartType() const
{
return m_chartType;
}
public slots:
public slots:
void chartReturned();
void chartTypes();
protected slots:
protected slots:
virtual void init() {}
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
@@ -70,7 +77,7 @@ protected slots:
Q_UNUSED( pushData );
}
private:
private:
void fetchChart( Tomahawk::InfoSystem::InfoRequestData requestData );
void fetchChartCapabilities( Tomahawk::InfoSystem::InfoRequestData requestData );
void dataError( Tomahawk::InfoSystem::InfoRequestData requestData );

View File

@@ -70,7 +70,7 @@ FdoNotifyPlugin::FdoNotifyPlugin()
// Query the window manager for its capabilties in styling notifications.
notifications_interface = new org::freedesktop::Notifications( "org.freedesktop.Notifications", "/org/freedesktop/Notifications",
QDBusConnection::sessionBus(), this );
QDBusConnection::sessionBus(), this );
QDBusPendingReply<QStringList> reply = notifications_interface->GetCapabilities();
QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher( reply, this );
@@ -106,7 +106,9 @@ FdoNotifyPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "showing notification:" << TomahawkSettings::instance()->songChangeNotificationEnabled();
if ( !TomahawkSettings::instance()->songChangeNotificationEnabled() )
{
return;
}
QVariant inputData = pushData.infoPair.second;
@@ -145,7 +147,7 @@ FdoNotifyPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
int
FdoNotifyPlugin::getNotificationIconHeight()
{
return 6 * TomahawkUtils::defaultFontHeight();
return 6 * TomahawkUtils::defaultFontHeight();
}
@@ -172,22 +174,32 @@ void FdoNotifyPlugin::inboxReceived( const QVariant& input )
{
tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
if ( !input.canConvert< QVariantMap >() )
{
return;
}
QVariantMap map = input.toMap();
if ( !map.contains( "trackinfo" ) || !map[ "trackinfo" ].canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
{
return;
}
if ( !map.contains( "sourceinfo" ) || !map[ "sourceinfo" ].canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
{
return;
}
InfoStringHash hash = map[ "trackinfo" ].value< Tomahawk::InfoSystem::InfoStringHash >();
if ( !hash.contains( "title" ) || !hash.contains( "artist" ) )
{
return;
}
InfoStringHash src = map[ "sourceinfo" ].value< Tomahawk::InfoSystem::InfoStringHash >();
if ( !src.contains( "friendlyname" ) )
{
return;
}
QString messageText;
// If the window manager supports notification styling then use it.
@@ -195,10 +207,10 @@ void FdoNotifyPlugin::inboxReceived( const QVariant& input )
{
// Remark: If using xml-based markup in notifications, the supplied strings need to be escaped.
messageText = tr( "%1 sent you\n%2%4 %3.", "%1 is a nickname, %2 is a title, %3 is an artist, %4 is the preposition used to link track and artist ('by' in english)" )
.arg( Qt::escape( src["friendlyname"] ) )
.arg( Qt::escape( hash[ "title" ] ) )
.arg( Qt::escape( hash[ "artist" ] ) )
.arg( QString( "\n<i>%1</i>" ).arg( tr( "by", "preposition to link track and artist" ) ) );
.arg( Qt::escape( src["friendlyname"] ) )
.arg( Qt::escape( hash[ "title" ] ) )
.arg( Qt::escape( hash[ "artist" ] ) )
.arg( QString( "\n<i>%1</i>" ).arg( tr( "by", "preposition to link track and artist" ) ) );
// Dirty hack(TM) so that KNotify/QLabel recognizes the message as Rich Text
messageText = QString( "<i></i>%1" ).arg( messageText );
@@ -206,9 +218,9 @@ void FdoNotifyPlugin::inboxReceived( const QVariant& input )
else
{
messageText = tr( "%1 sent you \"%2\" by %3.", "%1 is a nickname, %2 is a title, %3 is an artist" )
.arg( src["friendlyname"] )
.arg( hash[ "title" ] )
.arg( hash[ "artist" ] );
.arg( src["friendlyname"] )
.arg( hash[ "title" ] )
.arg( hash[ "artist" ] );
}
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "sending message" << messageText;
@@ -236,15 +248,21 @@ FdoNotifyPlugin::nowPlaying( const QVariant& input )
{
tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
if ( !input.canConvert< QVariantMap >() )
{
return;
}
QVariantMap map = input.toMap();
if ( !map.contains( "trackinfo" ) || !map[ "trackinfo" ].canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
{
return;
}
InfoStringHash hash = map[ "trackinfo" ].value< Tomahawk::InfoSystem::InfoStringHash >();
if ( !hash.contains( "title" ) || !hash.contains( "artist" ) || !hash.contains( "album" ) )
{
return;
}
QString messageText;
// If the window manager supports notification styling then use it.
@@ -253,13 +271,15 @@ FdoNotifyPlugin::nowPlaying( const QVariant& input )
// Remark: If using xml-based markup in notifications, the supplied strings need to be escaped.
QString album;
if ( !hash[ "album" ].isEmpty() )
{
album = QString( "\n<i>%1</i> %2" ).arg( tr( "on", "'on' is followed by an album name" ) ).arg( Qt::escape( hash[ "album" ] ) );
}
messageText = tr( "%1%4 %2%3.", "%1 is a title, %2 is an artist and %3 is replaced by either the previous message or nothing, %4 is the preposition used to link track and artist ('by' in english)" )
.arg( Qt::escape( hash[ "title" ] ) )
.arg( Qt::escape( hash[ "artist" ] ) )
.arg( album )
.arg( QString( "\n<i>%1</i>" ).arg( tr( "by", "preposition to link track and artist" ) ) );
.arg( Qt::escape( hash[ "title" ] ) )
.arg( Qt::escape( hash[ "artist" ] ) )
.arg( album )
.arg( QString( "\n<i>%1</i>" ).arg( tr( "by", "preposition to link track and artist" ) ) );
// Dirty hack(TM) so that KNotify/QLabel recognizes the message as Rich Text
messageText = QString( "<i></i>%1" ).arg( messageText );
@@ -268,12 +288,14 @@ FdoNotifyPlugin::nowPlaying( const QVariant& input )
{
QString album;
if ( !hash[ "album" ].isEmpty() )
{
album = QString( " %1" ).arg( tr( "on \"%1\"", "%1 is an album name" ).arg( hash[ "album" ] ) );
}
messageText = tr( "\"%1\" by %2%3.", "%1 is a title, %2 is an artist and %3 is replaced by either the previous message or nothing" )
.arg( hash[ "title" ] )
.arg( hash[ "artist" ] )
.arg( album );
.arg( hash[ "title" ] )
.arg( hash[ "artist" ] )
.arg( album );
}
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "sending message" << messageText;
@@ -284,23 +306,27 @@ FdoNotifyPlugin::nowPlaying( const QVariant& input )
// If there is a cover availble use it, else use Tomahawk logo as default.
QImage image;
if ( map.contains( "coveruri" ) && map[ "coveruri" ].canConvert< QString >() )
{
image = QImage( map[ "coveruri" ].toString(), "PNG" );
}
else
{
image = QImage( RESPATH "icons/tomahawk-icon-512x512.png" );
}
// Convert image to QVariant and scale to a consistent size.
hints[ "image_data" ] = ImageConverter::variantForImage( image.scaledToHeight( getNotificationIconHeight() ) );
QDBusPendingReply<> reply = notifications_interface->Notify(
"Tomahawk", // app_name
m_nowPlayingId, // notification_id
"", // app_icon
"Tomahawk - Now Playing", // summary
messageText, // body
QStringList(), // actions
hints, // hints
-1 // expire_timeout
);
"Tomahawk", // app_name
m_nowPlayingId, // notification_id
"", // app_icon
"Tomahawk - Now Playing", // summary
messageText, // body
QStringList(), // actions
hints, // hints
-1 // expire_timeout
);
QDBusPendingCallWatcher* watcher = new QDBusPendingCallWatcher( reply, this );
connect( watcher, SIGNAL( finished( QDBusPendingCallWatcher* ) ), SLOT( dbusPlayingReplyReceived( QDBusPendingCallWatcher* ) ) );
@@ -319,13 +345,15 @@ FdoNotifyPlugin::dbusPlayingReplyReceived( QDBusPendingCallWatcher* watcher )
if ( reply.type() == QDBusMessage::ErrorMessage )
{
tLog(LOGVERBOSE) << "Failed to grab media keys" << reply.errorName() << reply.errorMessage();
tLog( LOGVERBOSE ) << "Failed to grab media keys" << reply.errorName() << reply.errorMessage();
return;
}
const QVariantList& list = reply.arguments();
if ( !list.isEmpty() )
{
m_nowPlayingId = list.first().toInt();
}
}
} //ns InfoSystem

View File

@@ -39,11 +39,11 @@ class INFOPLUGINDLLEXPORT FdoNotifyPlugin : public InfoPlugin
Q_OBJECT
Q_INTERFACES( Tomahawk::InfoSystem::InfoPlugin )
public:
public:
FdoNotifyPlugin();
virtual ~FdoNotifyPlugin();
protected slots:
protected slots:
virtual void init() {}
virtual void dbusPlayingReplyReceived( QDBusPendingCallWatcher* watcher );
@@ -62,7 +62,7 @@ protected slots:
Q_UNUSED( requestData );
}
private:
private:
int getNotificationIconHeight();
void notifyUser( const QString& messageText );

View File

@@ -1,7 +1,7 @@
/*
Copyright (C) 2009 by Aurélien Gâteau <aurelien.gateau@canonical.com>
Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
This program 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 2, or (at your option)
@@ -34,76 +34,78 @@ namespace ImageConverter
*/
struct SpecImage
{
int width, height, rowStride;
bool hasAlpha;
int bitsPerSample, channels;
QByteArray data;
int width, height, rowStride;
bool hasAlpha;
int bitsPerSample, channels;
QByteArray data;
};
QDBusArgument &operator<<(QDBusArgument &argument, const SpecImage &image)
QDBusArgument& operator<<( QDBusArgument& argument, const SpecImage& image )
{
argument.beginStructure();
argument << image.width << image.height << image.rowStride << image.hasAlpha;
argument << image.bitsPerSample << image.channels << image.data;
argument.endStructure();
return argument;
argument.beginStructure();
argument << image.width << image.height << image.rowStride << image.hasAlpha;
argument << image.bitsPerSample << image.channels << image.data;
argument.endStructure();
return argument;
}
const QDBusArgument &operator>>(const QDBusArgument &argument, SpecImage &image)
const QDBusArgument& operator>>( const QDBusArgument& argument, SpecImage& image )
{
argument.beginStructure();
argument >> image.width >> image.height >> image.rowStride >> image.hasAlpha;
argument >> image.bitsPerSample >> image.channels >> image.data;
argument.endStructure();
return argument;
argument.beginStructure();
argument >> image.width >> image.height >> image.rowStride >> image.hasAlpha;
argument >> image.bitsPerSample >> image.channels >> image.data;
argument.endStructure();
return argument;
}
} // namespace
// This must be before the QVariant::fromValue below (#211726)
Q_DECLARE_METATYPE(ImageConverter::SpecImage)
Q_DECLARE_METATYPE( ImageConverter::SpecImage )
namespace ImageConverter
{
QVariant variantForImage(const QImage &_image)
QVariant variantForImage( const QImage& _image )
{
qDBusRegisterMetaType<SpecImage>();
qDBusRegisterMetaType<SpecImage>();
QImage image = _image.convertToFormat(QImage::Format_ARGB32);
QImage image = _image.convertToFormat( QImage::Format_ARGB32 );
int rowStride = image.width() * 4;
int rowStride = image.width() * 4;
// Notification spec stores pixels in R,G,B,A order, regardless of
// endianess
// Qt represents pixels as 32 bit unsigned int. So the order depend on
// endianess:
// - In big endian the order is A,R,G,B
// - In little endian the order is B,G,R,A
QByteArray data;
data.resize(rowStride * image.height());
char* dst = data.data();
for (int y=0; y<image.height(); ++y) {
QRgb* src = (QRgb*)image.scanLine(y);
QRgb* end = src + image.width();
for (;src != end; ++src) {
// Probably slow, but free of endianess issues
*dst++ = qRed(*src);
*dst++ = qGreen(*src);
*dst++ = qBlue(*src);
*dst++ = qAlpha(*src);
}
}
// Notification spec stores pixels in R,G,B,A order, regardless of
// endianess
// Qt represents pixels as 32 bit unsigned int. So the order depend on
// endianess:
// - In big endian the order is A,R,G,B
// - In little endian the order is B,G,R,A
QByteArray data;
data.resize( rowStride * image.height() );
char* dst = data.data();
for ( int y = 0; y < image.height(); ++y )
{
QRgb* src = ( QRgb* )image.scanLine( y );
QRgb* end = src + image.width();
for ( ; src != end; ++src )
{
// Probably slow, but free of endianess issues
*dst++ = qRed( *src );
*dst++ = qGreen( *src );
*dst++ = qBlue( *src );
*dst++ = qAlpha( *src );
}
}
SpecImage specImage;
specImage.width = image.width();
specImage.height = image.height();
specImage.rowStride = rowStride;
specImage.hasAlpha = true;
specImage.bitsPerSample = 8;
specImage.channels = 4;
specImage.data = data;
SpecImage specImage;
specImage.width = image.width();
specImage.height = image.height();
specImage.rowStride = rowStride;
specImage.hasAlpha = true;
specImage.bitsPerSample = 8;
specImage.channels = 4;
specImage.data = data;
return QVariant::fromValue(specImage);
return QVariant::fromValue( specImage );
}
} // namespace

View File

@@ -1,7 +1,7 @@
/*
Copyright (C) 2009 by Aurélien Gâteau <aurelien.gateau@canonical.com>
Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
This program 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 2, or (at your option)
@@ -30,7 +30,7 @@ namespace ImageConverter
* Returns a variant representing an image using the format describe in the
* galago spec
*/
QVariant variantForImage(const QImage &image);
QVariant variantForImage( const QImage& image );
} // namespace

View File

@@ -75,23 +75,23 @@ MprisPlugin::init()
// Listen to volume changes
connect( AudioEngine::instance(), SIGNAL( volumeChanged( int ) ),
SLOT( onVolumeChanged( int ) ) );
SLOT( onVolumeChanged( int ) ) );
// When the playlist changes, signals for several properties are sent
connect( AudioEngine::instance(), SIGNAL( playlistChanged( Tomahawk::playlistinterface_ptr ) ),
SLOT( onPlaylistChanged( Tomahawk::playlistinterface_ptr ) ) );
SLOT( onPlaylistChanged( Tomahawk::playlistinterface_ptr ) ) );
// When a track is added or removed, CanGoNext updated signal is sent
Tomahawk::playlistinterface_ptr playlist = AudioEngine::instance()->playlist();
if ( !playlist.isNull() )
{
connect( playlist.data(), SIGNAL( itemCountChanged( unsigned int ) ),
SLOT( onTrackCountChanged( unsigned int ) ) );
SLOT( onTrackCountChanged( unsigned int ) ) );
}
// Connect to AudioEngine's seeked signal
connect( AudioEngine::instance(), SIGNAL( seeked( qint64 ) ),
SLOT( onSeeked( qint64 ) ) );
SLOT( onSeeked( qint64 ) ) );
}
@@ -205,7 +205,9 @@ MprisPlugin::canSeek() const
{
Tomahawk::playlistinterface_ptr p = AudioEngine::instance()->playlist();
if ( p.isNull() )
{
return false;
}
return p->seekRestrictions() != PlaylistModes::NoSeek;
}
@@ -216,7 +218,9 @@ MprisPlugin::loopStatus() const
{
Tomahawk::playlistinterface_ptr p = AudioEngine::instance()->playlist();
if ( p.isNull() )
{
return "None";
}
PlaylistModes::RepeatMode mode = p->repeatMode();
switch( mode )
{
@@ -243,13 +247,21 @@ MprisPlugin::setLoopStatus( const QString& value )
{
Tomahawk::playlistinterface_ptr p = AudioEngine::instance()->playlist();
if ( p.isNull() )
{
return;
}
if ( value == "Track" )
{
p->setRepeatMode( PlaylistModes::RepeatOne );
}
else if ( value == "Playlist" )
{
p->setRepeatMode( PlaylistModes::RepeatAll );
}
else if ( value == "None" )
{
p->setRepeatMode( PlaylistModes::NoRepeat );
}
}
@@ -267,8 +279,8 @@ MprisPlugin::metadata() const
Tomahawk::result_ptr track = AudioEngine::instance()->currentTrack();
if ( track )
{
metadataMap.insert( "mpris:trackid", QVariant::fromValue(QDBusObjectPath(QString( "/track/" ) + track->id().replace( "-", "" ))) );
metadataMap.insert( "mpris:length", static_cast<qlonglong>(track->track()->duration()) * 1000000 );
metadataMap.insert( "mpris:trackid", QVariant::fromValue( QDBusObjectPath( QString( "/track/" ) + track->id().replace( "-", "" ) ) ) );
metadataMap.insert( "mpris:length", static_cast<qlonglong>( track->track()->duration() ) * 1000000 );
metadataMap.insert( "xesam:album", track->track()->album() );
metadataMap.insert( "xesam:artist", QStringList( track->track()->artist() ) );
metadataMap.insert( "xesam:title", track->track()->track() );
@@ -278,7 +290,9 @@ MprisPlugin::metadata() const
{
QFile coverFile( m_coverTempFile );
if ( coverFile.exists() && coverFile.fileName().contains( track->track()->artist() + "_" + track->track()->album() + "_tomahawk_cover.png" ) )
{
metadataMap.insert( "mpris:artUrl", QString( QUrl::fromLocalFile( m_coverTempFile ).toEncoded() ) );
}
}
}
@@ -304,7 +318,7 @@ qlonglong
MprisPlugin::position() const
{
// Convert Tomahawk's milliseconds to microseconds
return (qlonglong) ( AudioEngine::instance()->currentTime() * 1000 );
return ( qlonglong ) ( AudioEngine::instance()->currentTime() * 1000 );
}
@@ -327,7 +341,9 @@ MprisPlugin::shuffle() const
{
Tomahawk::playlistinterface_ptr p = AudioEngine::instance()->playlist();
if ( p.isNull() )
{
return false;
}
return p->shuffled();
}
@@ -337,7 +353,9 @@ MprisPlugin::setShuffle( bool value )
{
Tomahawk::playlistinterface_ptr p = AudioEngine::instance()->playlist();
if ( p.isNull() )
{
return;
}
return p->setShuffled( value );
}
@@ -345,7 +363,7 @@ MprisPlugin::setShuffle( bool value )
double
MprisPlugin::volume() const
{
return static_cast<double>(AudioEngine::instance()->volume()) / 100.0;
return static_cast<double>( AudioEngine::instance()->volume() ) / 100.0;
}
@@ -402,16 +420,24 @@ void
MprisPlugin::Seek( qlonglong Offset )
{
if ( !canSeek() )
{
return;
}
qlonglong seekTime = position() + Offset;
if ( seekTime < 0 )
{
AudioEngine::instance()->seek( 0 );
else if ( seekTime > AudioEngine::instance()->currentTrackTotalTime()*1000 )
}
else if ( seekTime > AudioEngine::instance()->currentTrackTotalTime() * 1000 )
{
Next();
}
// seekTime is in microseconds, but we work internally in milliseconds
else
AudioEngine::instance()->seek( (qint64) ( seekTime / 1000 ) );
{
AudioEngine::instance()->seek( ( qint64 ) ( seekTime / 1000 ) );
}
}
@@ -420,15 +446,21 @@ void
MprisPlugin::SetPosition( const QDBusObjectPath& TrackId, qlonglong Position )
{
if ( !canSeek() )
{
return;
}
if ( TrackId.path() != QString( "/track/" ) + AudioEngine::instance()->currentTrack()->id().replace( "-", "" ) )
{
return;
}
if ( ( Position < 0) || ( Position > AudioEngine::instance()->currentTrackTotalTime()*1000 ) )
if ( ( Position < 0 ) || ( Position > AudioEngine::instance()->currentTrackTotalTime() * 1000 ) )
{
return;
}
AudioEngine::instance()->seek( (qint64) (Position / 1000 ) );
AudioEngine::instance()->seek( ( qint64 ) ( Position / 1000 ) );
}
@@ -449,28 +481,30 @@ MprisPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
switch ( pushData.type )
{
case InfoNowPlaying:
isPlayingInfo = true;
audioStarted( pushData.infoPair.second );
break;
isPlayingInfo = true;
audioStarted( pushData.infoPair.second );
break;
case InfoNowPaused:
isPlayingInfo = true;
audioPaused();
break;
isPlayingInfo = true;
audioPaused();
break;
case InfoNowResumed:
isPlayingInfo = true;
audioResumed( pushData.infoPair.second );
break;
isPlayingInfo = true;
audioResumed( pushData.infoPair.second );
break;
case InfoNowStopped:
isPlayingInfo = true;
audioStopped();
break;
isPlayingInfo = true;
audioStopped();
break;
default:
break;
break;
}
if ( isPlayingInfo )
{
notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "PlaybackStatus" );
}
}
@@ -487,21 +521,29 @@ void
MprisPlugin::audioStarted( const QVariant& input )
{
if ( !input.canConvert< QVariantMap >() )
{
return;
}
QVariantMap map = input.toMap();
if ( !map.contains( "trackinfo" ) || !map[ "trackinfo" ].canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
{
return;
}
InfoStringHash hash = map[ "trackinfo" ].value< Tomahawk::InfoSystem::InfoStringHash >();
if ( !hash.contains( "title" ) || !hash.contains( "artist" ) || !hash.contains( "album" ) )
{
return;
}
m_playbackStatus = "Playing";
if ( map.contains( "coveruri" ) )
{
m_coverTempFile = map[ "coveruri" ].toString();
}
notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Metadata" );
}
@@ -550,7 +592,7 @@ MprisPlugin::onPlaylistChanged( Tomahawk::playlistinterface_ptr playlist )
if ( !playlist.isNull() )
connect( playlist.data(), SIGNAL( itemCountChanged( unsigned int ) ),
SLOT( onTrackCountChanged( unsigned int ) ) );
SLOT( onTrackCountChanged( unsigned int ) ) );
// Notify relevant changes
notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "LoopStatus" );
@@ -572,7 +614,7 @@ MprisPlugin::onTrackCountChanged( unsigned int tracks )
void
MprisPlugin::onSeeked( qint64 ms )
{
qlonglong us = (qlonglong) ( ms*1000 );
qlonglong us = ( qlonglong ) ( ms * 1000 );
emit Seeked( us );
}
@@ -581,15 +623,15 @@ void
MprisPlugin::notifyPropertyChanged( const QString& interface, const QString& propertyName )
{
QDBusMessage signal = QDBusMessage::createSignal(
"/org/mpris/MediaPlayer2",
"org.freedesktop.DBus.Properties",
"PropertiesChanged" );
"/org/mpris/MediaPlayer2",
"org.freedesktop.DBus.Properties",
"PropertiesChanged" );
signal << interface;
QVariantMap changedProps;
changedProps.insert(propertyName, property(propertyName.toLatin1()));
changedProps.insert( propertyName, property( propertyName.toLatin1() ) );
signal << changedProps;
signal << QStringList();
QDBusConnection::sessionBus().send(signal);
QDBusConnection::sessionBus().send( signal );
}
} //ns InfoSystem

View File

@@ -29,7 +29,7 @@
// Forward Declarations breaking QSharedPointer
#if QT_VERSION < QT_VERSION_CHECK( 5, 0, 0 )
#include "PlaylistInterface.h"
#include "PlaylistInterface.h"
#endif
@@ -49,7 +49,7 @@ class INFOPLUGINDLLEXPORT MprisPlugin : public InfoPlugin
Q_OBJECT
Q_INTERFACES( Tomahawk::InfoSystem::InfoPlugin )
public:
public:
MprisPlugin();
virtual ~MprisPlugin();
@@ -129,7 +129,7 @@ public:
double volume() const;
void setVolume( double value );
public slots:
public slots:
virtual void notInCacheSlot( const Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
{
Q_UNUSED( criteria );
@@ -151,7 +151,7 @@ public slots:
void SetPosition( const QDBusObjectPath& TrackId, qlonglong Position );
void Stop();
protected slots:
protected slots:
virtual void init();
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
@@ -160,17 +160,17 @@ protected slots:
}
void pushInfo( Tomahawk::InfoSystem::InfoPushData pushData );
private slots:
private slots:
void stateChanged( AudioState newState, AudioState oldState );
void onVolumeChanged( int volume );
void onPlaylistChanged( Tomahawk::playlistinterface_ptr );
void onTrackCountChanged( unsigned int tracks );
void onSeeked( qint64 ms );
signals:
signals:
void Seeked( qlonglong Position );
private:
private:
// Get Info
// Push Info

View File

@@ -35,13 +35,13 @@
QString adium_beforeStatus;
QString adium_afterStatus;
static void setStatus(const QString &status)
static void setStatus( const QString& status )
{
// The command that updates the status
QString scriptqstr;
scriptqstr.append(adium_beforeStatus);
scriptqstr.append(status);
scriptqstr.append(adium_afterStatus);
scriptqstr.append( adium_beforeStatus );
scriptqstr.append( status );
scriptqstr.append( adium_afterStatus );
const char* scriptstr = scriptqstr.toUtf8();
script( scriptstr );
@@ -59,21 +59,21 @@ AdiumPlugin::AdiumPlugin()
qDebug() << Q_FUNC_INFO;
adium_beforeStatus = "if appIsRunning(\"Adium\") then\n";
adium_beforeStatus.append("tell application \"Adium\"\n");
adium_beforeStatus.append("set the status message of every account to \"");
adium_beforeStatus.append( "tell application \"Adium\"\n" );
adium_beforeStatus.append( "set the status message of every account to \"" );
adium_afterStatus.append("\"\nend tell\n");
adium_afterStatus.append("end if\n");
adium_afterStatus.append("on appIsRunning(appName)\n");
adium_afterStatus.append("tell application \"System Events\" to (name of processes) contains appName\n");
adium_afterStatus.append("end appIsRunning\n");
adium_afterStatus.append( "\"\nend tell\n" );
adium_afterStatus.append( "end if\n" );
adium_afterStatus.append( "on appIsRunning(appName)\n" );
adium_afterStatus.append( "tell application \"System Events\" to (name of processes) contains appName\n" );
adium_afterStatus.append( "end appIsRunning\n" );
m_supportedPushTypes << InfoNowPlaying << InfoNowPaused << InfoNowResumed << InfoNowStopped;
m_active = TomahawkSettings::instance()->nowPlayingEnabled();
connect( TomahawkSettings::instance(), SIGNAL( changed() ),
SLOT( settingsChanged() ), Qt::QueuedConnection );
SLOT( settingsChanged() ), Qt::QueuedConnection );
m_pauseTimer = new QTimer( this );
m_pauseTimer->setSingleShot( true );
@@ -86,7 +86,9 @@ AdiumPlugin::~AdiumPlugin()
{
qDebug() << Q_FUNC_INFO;
if( m_active )
setStatus( "" );
{
setStatus( "" );
}
}
@@ -111,25 +113,27 @@ AdiumPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
qDebug() << Q_FUNC_INFO;
if( !m_active )
{
return;
}
switch ( pushData.type )
{
case InfoNowPlaying:
audioStarted( pushData.infoPair );
break;
audioStarted( pushData.infoPair );
break;
case InfoNowPaused:
audioPaused();
return;
audioPaused();
return;
case InfoNowResumed:
audioResumed( pushData.infoPair );
break;
audioResumed( pushData.infoPair );
break;
case InfoNowStopped:
audioStopped();
break;
audioStopped();
break;
default:
return;
return;
}
// Stop the pause timer always, unless pausing of course
@@ -142,20 +146,28 @@ void
AdiumPlugin::audioStarted( const Tomahawk::InfoSystem::PushInfoPair pushInfoPair )
{
if ( !pushInfoPair.second.canConvert< QVariantMap >() )
{
return;
}
QVariantMap map = pushInfoPair.second.toMap();
if ( map.contains( "private" ) && map[ "private" ] == TomahawkSettings::FullyPrivate )
{
return;
}
if ( !map.contains( "trackinfo" ) || !map[ "trackinfo" ].canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
{
return;
}
InfoStringHash hash = map[ "trackinfo" ].value< Tomahawk::InfoSystem::InfoStringHash >();
if ( !hash.contains( "title" ) || !hash.contains( "artist" ) )
{
return;
}
m_currentTitle = hash["title"];
m_currentArtist = hash["artist"];
@@ -165,11 +177,13 @@ AdiumPlugin::audioStarted( const Tomahawk::InfoSystem::PushInfoPair pushInfoPair
QUrl shortUrl = m_currentLongUrl;
if ( pushInfoPair.first.contains( "shortUrl" ) )
{
shortUrl = pushInfoPair.first[ "shortUrl" ].toUrl();
}
QString nowPlaying = "";
nowPlaying.append( m_currentArtist );
nowPlaying.append(" - ");
nowPlaying.append( " - " );
nowPlaying.append( m_currentTitle );
nowPlaying.replace( "\"", "\\\"" ); // Escape quotes, or Applescript gets confused
@@ -187,7 +201,7 @@ AdiumPlugin::audioStarted( const Tomahawk::InfoSystem::PushInfoPair pushInfoPair
}
void
AdiumPlugin::audioFinished( const QVariant &input )
AdiumPlugin::audioFinished( const QVariant& input )
{
//qDebug() << Q_FUNC_INFO;
}

View File

@@ -31,9 +31,11 @@
class QTimer;
namespace Tomahawk {
namespace Tomahawk
{
namespace InfoSystem {
namespace InfoSystem
{
class INFOPLUGINDLLEXPORT AdiumPlugin : public InfoPlugin
{
@@ -41,13 +43,13 @@ class INFOPLUGINDLLEXPORT AdiumPlugin : public InfoPlugin
Q_OBJECT
Q_INTERFACES( Tomahawk::InfoSystem::InfoPlugin )
public:
public:
AdiumPlugin();
virtual ~AdiumPlugin();
protected slots:
protected slots:
virtual void init() {}
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData )
{
Q_UNUSED( requestData );
@@ -55,20 +57,20 @@ protected slots:
virtual void pushInfo( Tomahawk::InfoSystem::InfoPushData pushData );
public slots:
public slots:
virtual void notInCacheSlot( const Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
{
Q_UNUSED( criteria );
Q_UNUSED( requestData );
}
private slots:
private slots:
void clearStatus();
void settingsChanged();
private:
private:
void audioStarted( const Tomahawk::InfoSystem::PushInfoPair pushInfoPair );
void audioFinished( const QVariant &input );
void audioFinished( const QVariant& input );
void audioStopped();
void audioPaused();
void audioResumed( const Tomahawk::InfoSystem::PushInfoPair pushInfoPair );

View File

@@ -42,14 +42,14 @@ using namespace Tomahawk;
using namespace TomahawkUtils;
Api_v1::Api_v1( QxtAbstractWebSessionManager* sm, QObject* parent )
: QxtWebSlotService(sm, parent)
: QxtWebSlotService( sm, parent )
, m_api_v1_5( new Api_v1_5( this ) )
{
}
Api_v1::~Api_v1()
{
delete m_api_v1_5;
delete m_api_v1_5;
}
void
@@ -79,7 +79,9 @@ Api_v1::auth_1( QxtWebRequestEvent* event, QString arg )
QString authPage = RESPATH "www/auth.html";
QHash< QString, QString > args;
if ( urlHasQueryItem( event->url, "receiverurl" ) )
{
args[ "url" ] = urlQueryItemValue( event->url, "receiverurl" ).toUtf8();
}
args[ "formtoken" ] = formToken;
args[ "website" ] = urlQueryItemValue( event->url, "website" ).toUtf8();
@@ -105,13 +107,17 @@ Api_v1::auth_2( QxtWebRequestEvent* event, QString arg )
QStringList pieces = params.split( '&' );
QHash< QString, QString > queryItems;
foreach ( const QString& part, pieces )
foreach ( const QString & part, pieces )
{
QStringList keyval = part.split( '=' );
if ( keyval.size() == 2 )
{
queryItems.insert( keyval.first(), keyval.last() );
}
else
{
tDebug( LOGVERBOSE ) << "Failed parsing url parameters:" << part;
}
}
tDebug( LOGVERBOSE ) << "has query items:" << pieces;
@@ -159,7 +165,7 @@ Api_v1::auth_2( QxtWebRequestEvent* event, QString arg )
}
DatabaseCommand_AddClientAuth* dbcmd = new DatabaseCommand_AddClientAuth( authtoken, website, name, event->headers.key( "ua" ) );
Database::instance()->enqueue( Tomahawk::dbcmd_ptr(dbcmd) );
Database::instance()->enqueue( Tomahawk::dbcmd_ptr( dbcmd ) );
}
@@ -174,20 +180,30 @@ Api_v1::api( QxtWebRequestEvent* event, const QString& version, const QString& m
{
tDebug( LOGVERBOSE ) << "HTTP" << event->url.toString();
if ( version.isEmpty() ) {
// We dealing with API 1.0
if ( version.isEmpty() )
{
// We dealing with API 1.0
const QUrl& url = event->url;
if ( urlHasQueryItem( url, "method" ) )
{
const QString method = urlQueryItemValue( url, "method" );
const QUrl& url = event->url;
if ( urlHasQueryItem( url, "method" ) )
{
const QString method = urlQueryItemValue( url, "method" );
if ( method == "stat" ) return stat( event );
if ( method == "resolve" ) return resolve( event );
if ( method == "get_results" ) return get_results( event );
}
if ( method == "stat" )
{
return stat( event );
}
if ( method == "resolve" )
{
return resolve( event );
}
if ( method == "get_results" )
{
return get_results( event );
}
}
send404( event );
send404( event );
}
else if ( version == "1.5" )
{
@@ -195,28 +211,28 @@ Api_v1::api( QxtWebRequestEvent* event, const QString& version, const QString& m
{
if ( !QMetaObject::invokeMethod( m_api_v1_5, method.toLatin1().constData(), Q_ARG( QxtWebRequestEvent*, event ), Q_ARG( QString, arg1 ), Q_ARG( QString, arg2 ), Q_ARG( QString, arg3 ) ) )
{
apiCallFailed(event, method);
apiCallFailed( event, method );
}
}
else if ( !arg2.isEmpty() )
{
if ( !QMetaObject::invokeMethod( m_api_v1_5, method.toLatin1().constData(), Q_ARG( QxtWebRequestEvent*, event ), Q_ARG( QString, arg1 ), Q_ARG( QString, arg2 ) ) )
{
apiCallFailed(event, method);
apiCallFailed( event, method );
}
}
else if ( !arg1.isEmpty() )
{
if ( !QMetaObject::invokeMethod( m_api_v1_5, method.toLatin1().constData(), Q_ARG( QxtWebRequestEvent*, event ), Q_ARG( QString, arg1 ) ) )
{
apiCallFailed(event, method);
apiCallFailed( event, method );
}
}
else
{
if ( !QMetaObject::invokeMethod( m_api_v1_5, method.toLatin1().constData(), Q_ARG( QxtWebRequestEvent*, event ) ) )
{
apiCallFailed(event, method);
apiCallFailed( event, method );
}
}
}
@@ -243,7 +259,7 @@ Api_v1::sid( QxtWebRequestEvent* event, QString unused )
}
boost::function< void ( QSharedPointer< QIODevice >& ) > callback =
boost::bind( &Api_v1::processSid, this, event, rp, _1 );
boost::bind( &Api_v1::processSid, this, event, rp, _1 );
Tomahawk::UrlHandler::getIODeviceForUrl( rp, rp->url(), callback );
}
@@ -262,7 +278,9 @@ Api_v1::processSid( QxtWebRequestEvent* event, Tomahawk::result_ptr& rp, QShared
e->streaming = iodev->isSequential();
e->contentType = rp->mimetype().toLatin1();
if ( rp->size() > 0 )
{
e->headers.insert( "Content-Length", QString::number( rp->size() ) );
}
postEvent( e );
}
@@ -281,7 +299,7 @@ Api_v1::send404( QxtWebRequestEvent* event )
void
Api_v1::sendPlain404( QxtWebRequestEvent* event, const QString& message, const QString& statusmessage )
{
QxtWebPageEvent * e = new QxtWebPageEvent( event->sessionID, event->requestID, message.toUtf8() );
QxtWebPageEvent* e = new QxtWebPageEvent( event->sessionID, event->requestID, message.toUtf8() );
e->contentType = "text/plain";
e->status = 404;
e->statusMessage = statusmessage.toLatin1().constData();
@@ -296,14 +314,16 @@ Api_v1::stat( QxtWebRequestEvent* event )
m_storedEvent = event;
if ( !event->content.isNull() )
{
tDebug( LOGVERBOSE ) << "BODY:" << event->content->readAll();
}
if ( urlHasQueryItem( event->url, "auth" ) )
{
// check for auth status
DatabaseCommand_ClientAuthValid* dbcmd = new DatabaseCommand_ClientAuthValid( urlQueryItemValue( event->url, "auth" ) );
connect( dbcmd, SIGNAL( authValid( QString, QString, bool ) ), this, SLOT( statResult( QString, QString, bool ) ) );
Database::instance()->enqueue( Tomahawk::dbcmd_ptr(dbcmd) );
Database::instance()->enqueue( Tomahawk::dbcmd_ptr( dbcmd ) );
}
else
{
@@ -320,7 +340,9 @@ Api_v1::statResult( const QString& clientToken, const QString& name, bool valid
Q_ASSERT( m_storedEvent );
if ( !m_storedEvent )
{
return;
}
QVariantMap m;
m.insert( "name", "playdar" );
@@ -337,7 +359,7 @@ void
Api_v1::resolve( QxtWebRequestEvent* event )
{
if ( !urlHasQueryItem( event->url, "artist" ) ||
!urlHasQueryItem( event->url, "track" ) )
!urlHasQueryItem( event->url, "track" ) )
{
tDebug( LOGVERBOSE ) << "Malformed HTTP resolve request";
return send404( event );
@@ -348,7 +370,7 @@ Api_v1::resolve( QxtWebRequestEvent* event )
const QString album = urlQueryItemValue( event->url, "album" );
if ( artist.trimmed().isEmpty() ||
track.trimmed().isEmpty() )
track.trimmed().isEmpty() )
{
tDebug( LOGVERBOSE ) << "Malformed HTTP resolve request";
return send404( event );
@@ -356,9 +378,13 @@ Api_v1::resolve( QxtWebRequestEvent* event )
QString qid;
if ( urlHasQueryItem( event->url, "qid" ) )
{
qid = urlQueryItemValue( event->url, "qid" );
}
else
{
qid = uuid();
}
query_ptr qry = Query::get( artist, track, album, qid, false );
if ( qry.isNull() )
@@ -392,11 +418,17 @@ Api_v1::staticdata( QxtWebRequestEvent* event, const QString& file )
QxtWebPageEvent* e = new QxtWebPageEvent( event->sessionID, event->requestID, data );
if ( file.endsWith( ".png" ) )
{
e->contentType = "image/png";
}
if ( file.endsWith( ".css" ) )
{
e->contentType = "text/css";
}
if ( file.endsWith( ".js" ) )
{
e->contentType = "application/javascript";
}
postEvent( e );
}
@@ -441,10 +473,12 @@ Api_v1::get_results( QxtWebRequestEvent* event )
r.insert( "query", qry->toVariant() );
QVariantList res;
foreach( const result_ptr& rp, qry->results() )
foreach( const result_ptr & rp, qry->results() )
{
if ( rp->isOnline() )
{
res << rp->toVariant();
}
}
r.insert( "results", res );
@@ -462,7 +496,7 @@ Api_v1::sendJSON( const QVariantMap& m, QxtWebRequestEvent* event )
if ( urlHasQueryItem( event->url, "jsonp" ) && !urlQueryItemValue( event->url, "jsonp" ).isEmpty() )
{
ctype = "text/javascript; charset=utf-8";
body.prepend( QString("%1( ").arg( urlQueryItemValue( event->url, "jsonp" ) ).toLatin1() );
body.prepend( QString( "%1( " ).arg( urlQueryItemValue( event->url, "jsonp" ) ).toLatin1() );
body.append( " );" );
}
else
@@ -470,7 +504,7 @@ Api_v1::sendJSON( const QVariantMap& m, QxtWebRequestEvent* event )
ctype = "appplication/json; charset=utf-8";
}
QxtWebPageEvent * e = new QxtWebPageEvent( event->sessionID, event->requestID, body );
QxtWebPageEvent* e = new QxtWebPageEvent( event->sessionID, event->requestID, body );
e->contentType = ctype;
e->headers.insert( "Content-Length", QString::number( body.length() ) );
e->headers.insert( "Access-Control-Allow-Origin", "*" );
@@ -485,19 +519,23 @@ void
Api_v1::sendWebpageWithArgs( QxtWebRequestEvent* event, const QString& filenameSource, const QHash< QString, QString >& args )
{
if ( !QFile::exists( filenameSource ) )
{
qWarning() << "Passed invalid file for html source:" << filenameSource;
}
QFile f( filenameSource );
f.open( QIODevice::ReadOnly );
QByteArray html = f.readAll();
foreach( const QString& param, args.keys() )
foreach( const QString & param, args.keys() )
{
html.replace( QString( "<%%1%>" ).arg( param.toUpper() ), args.value( param ).toUtf8() );
}
// workaround for receiverurl
if ( !args.keys().contains( "URL" ) )
{
html.replace( QString( "<%URL%>" ).toLatin1(), QByteArray() );
}
QxtWebPageEvent* e = new QxtWebPageEvent( event->sessionID, event->requestID, html );
@@ -522,7 +560,7 @@ Api_v1::apiCallFailed( QxtWebRequestEvent* event, const QString& method )
void
Api_v1::sendJsonOk( QxtWebRequestEvent* event )
{
QxtWebPageEvent * e = new QxtWebPageEvent( event->sessionID, event->requestID, "{ \"result\": \"ok\" }" );
QxtWebPageEvent* e = new QxtWebPageEvent( event->sessionID, event->requestID, "{ \"result\": \"ok\" }" );
e->headers.insert( "Access-Control-Allow-Origin", "*" );
e->contentType = "application/json";
postEvent( e );
@@ -532,7 +570,7 @@ Api_v1::sendJsonOk( QxtWebRequestEvent* event )
void
Api_v1::sendJsonError( QxtWebRequestEvent* event, const QString& message )
{
QxtWebPageEvent * e = new QxtWebPageEvent( event->sessionID, event->requestID, QString( "{ \"result\": \"error\", \"error\": \"%1\" }" ).arg( message ).toUtf8().constData() );
QxtWebPageEvent* e = new QxtWebPageEvent( event->sessionID, event->requestID, QString( "{ \"result\": \"error\", \"error\": \"%1\" }" ).arg( message ).toUtf8().constData() );
e->headers.insert( "Access-Control-Allow-Origin", "*" );
e->contentType = "application/json";
e->status = 500;

View File

@@ -43,19 +43,19 @@ class Api_v1_5;
namespace Tomahawk
{
class Result;
typedef QSharedPointer< Result > result_ptr;
class Result;
typedef QSharedPointer< Result > result_ptr;
}
class TOMAHAWK_PLAYDARAPI_EXPORT Api_v1 : public QxtWebSlotService
{
Q_OBJECT
Q_OBJECT
public:
public:
Api_v1( QxtAbstractWebSessionManager* sm, QObject* parent = 0 );
virtual ~Api_v1();
public slots:
public slots:
// authenticating uses /auth_1
// we redirect to /auth_2 for the callback
void auth_1( QxtWebRequestEvent* event, QString unused = QString() );
@@ -63,11 +63,11 @@ public slots:
// all v1 api calls go to /api/
void api( QxtWebRequestEvent* event,
const QString& version = QString(),
const QString& method = QString(),
const QString& arg1 = QString(),
const QString& arg2 = QString(),
const QString& arg3 = QString() );
const QString& version = QString(),
const QString& method = QString(),
const QString& arg1 = QString(),
const QString& arg2 = QString(),
const QString& arg3 = QString() );
// request for stream: /sid/<id>
void sid( QxtWebRequestEvent* event, QString unused = QString() );
@@ -88,11 +88,11 @@ public slots:
void index( QxtWebRequestEvent* event );
protected:
protected:
void apiCallFailed( QxtWebRequestEvent* event, const QString& method );
void sendPlain404( QxtWebRequestEvent* event, const QString& message, const QString& statusmessage );
private:
private:
void processSid( QxtWebRequestEvent* event, Tomahawk::result_ptr&, QSharedPointer< QIODevice >& );
QxtWebRequestEvent* m_storedEvent;

View File

@@ -40,7 +40,7 @@ Api_v1_5::Api_v1_5( Api_v1* parent )
void
Api_v1_5::ping( QxtWebRequestEvent* event )
{
QxtWebPageEvent * e = new QxtWebPageEvent( event->sessionID, event->requestID, "pong" );
QxtWebPageEvent* e = new QxtWebPageEvent( event->sessionID, event->requestID, "pong" );
e->headers.insert( "Access-Control-Allow-Origin", "*" );
e->contentType = "text/plain";
m_service->postEvent( e );
@@ -50,7 +50,7 @@ Api_v1_5::ping( QxtWebRequestEvent* event )
void
Api_v1_5::playback( QxtWebRequestEvent* event, const QString& command )
{
if ( command == "next")
if ( command == "next" )
{
JSON_REPLY( QMetaObject::invokeMethod( AudioEngine::instance(), "next", Qt::QueuedConnection ) , "Skipping to the next track failed." );
}
@@ -110,7 +110,7 @@ Api_v1_5::playback( QxtWebRequestEvent* event, const QString& command )
Q_ASSERT( ok );
}
QxtWebPageEvent * e = new QxtWebPageEvent( event->sessionID, event->requestID, json );
QxtWebPageEvent* e = new QxtWebPageEvent( event->sessionID, event->requestID, json );
e->headers.insert( "Access-Control-Allow-Origin", "*" );
e->contentType = "application/json";
m_service->postEvent( e );
@@ -118,7 +118,7 @@ Api_v1_5::playback( QxtWebRequestEvent* event, const QString& command )
else if ( command == "volume" )
{
QByteArray json = QString( "{ \"result\": \"ok\", \"volume\": %1}" ).arg( AudioEngine::instance()->volume() ).toUtf8();
QxtWebPageEvent * e = new QxtWebPageEvent( event->sessionID, event->requestID, json );
QxtWebPageEvent* e = new QxtWebPageEvent( event->sessionID, event->requestID, json );
e->headers.insert( "Access-Control-Allow-Origin", "*" );
e->contentType = "application/json";
m_service->postEvent( e );

View File

@@ -27,12 +27,12 @@ class QxtWebRequestEvent;
class Api_v1_5 : public QObject
{
Q_OBJECT
public:
public:
Api_v1_5( Api_v1* parent = 0 );
signals:
signals:
public slots:
public slots:
/**
* Simple test to check for API 1.5 support.
*
@@ -45,10 +45,10 @@ public slots:
*/
void playback( QxtWebRequestEvent* event, const QString& command );
protected:
protected:
void jsonReply( QxtWebRequestEvent* event, const char* funcInfo, const QString& errorMessage, bool isError );
private:
private:
Api_v1* m_service;
};

View File

@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
*

View File

@@ -51,9 +51,13 @@ PlaydarApi::start()
if ( d->session.isNull() || d->connector.isNull() )
{
if ( !d->session.isNull() )
{
delete d->session.data();
}
if ( !d->connector.isNull() )
{
delete d->connector.data();
}
tLog() << "Failed to start HTTPd, could not create object";
return;
}

View File

@@ -29,16 +29,16 @@ class PlaydarApiPrivate;
class TOMAHAWK_PLAYDARAPI_EXPORT PlaydarApi : public QObject
{
Q_OBJECT
public:
explicit PlaydarApi( QHostAddress ha, qint16 port, QObject *parent = 0 );
public:
explicit PlaydarApi( QHostAddress ha, qint16 port, QObject* parent = 0 );
virtual ~PlaydarApi();
void start();
protected:
protected:
QScopedPointer<PlaydarApiPrivate> d_ptr;
private:
private:
Q_DECLARE_PRIVATE( PlaydarApi )
};

View File

@@ -25,7 +25,7 @@
class PlaydarApiPrivate
{
public:
public:
PlaydarApiPrivate( PlaydarApi* q )
: q_ptr( q )
{
@@ -34,7 +34,7 @@ public:
PlaydarApi* q_ptr;
Q_DECLARE_PUBLIC( PlaydarApi )
private:
private:
QScopedPointer< Api_v1 > instance;
QScopedPointer< QxtHttpServerConnector > connector;
QScopedPointer< QxtHttpSessionManager > session;

View File

@@ -93,19 +93,27 @@ PlaylistDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
QRect pixmapRect = option.rect.adjusted( 12, 12, -option.rect.width() + option.rect.height() - 12, -12 );
QPixmap avatar = index.data( RecentlyPlayedPlaylistsModel::PlaylistRole ).value< Tomahawk::playlist_ptr >()->author()->avatar( TomahawkUtils::RoundedCorners, pixmapRect.size() );
if ( avatar.isNull() )
{
avatar = TomahawkUtils::defaultPixmap( TomahawkUtils::DefaultSourceAvatar, TomahawkUtils::RoundedCorners, pixmapRect.size() );
}
painter->drawPixmap( pixmapRect, avatar );
pixmapRect = QRect( option.rect.width() - option.fontMetrics.height() * 2.5 - 10, option.rect.top() + option.rect.height() / 4, option.fontMetrics.height() * 2.5, option.fontMetrics.height() * 2.5 );
QPixmap icon;
RecentlyPlayedPlaylistsModel::PlaylistTypes type = (RecentlyPlayedPlaylistsModel::PlaylistTypes)index.data( RecentlyPlayedPlaylistsModel::PlaylistTypeRole ).toInt();
RecentlyPlayedPlaylistsModel::PlaylistTypes type = ( RecentlyPlayedPlaylistsModel::PlaylistTypes )index.data( RecentlyPlayedPlaylistsModel::PlaylistTypeRole ).toInt();
if ( type == RecentlyPlayedPlaylistsModel::StaticPlaylist )
{
icon = TomahawkUtils::defaultPixmap( TomahawkUtils::Playlist, TomahawkUtils::Original, pixmapRect.size() );
}
else if ( type == RecentlyPlayedPlaylistsModel::AutoPlaylist )
{
icon = TomahawkUtils::defaultPixmap( TomahawkUtils::AutomaticPlaylist, TomahawkUtils::Original, pixmapRect.size() );
}
else if ( type == RecentlyPlayedPlaylistsModel::Station )
{
icon = TomahawkUtils::defaultPixmap( TomahawkUtils::Station, TomahawkUtils::Original, pixmapRect.size() );
}
painter->drawPixmap( pixmapRect, icon );
@@ -115,7 +123,7 @@ PlaylistDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
painter->setFont( figFont );
QString tracks = index.data( RecentlyPlayedPlaylistsModel::TrackCountRole ).toString();
int width = painter->fontMetrics().width( tracks );
// int bottomEdge = pixmapRect
// int bottomEdge = pixmapRect
// right edge 10px past right edge of pixmapRect
// bottom edge flush with bottom of pixmap
QRect rect( pixmapRect.right() - width, 0, width - 8, 0 );
@@ -134,13 +142,15 @@ PlaylistDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
painter->setFont( font );
QString author = index.data( RecentlyPlayedPlaylistsModel::PlaylistRole ).value< Tomahawk::playlist_ptr >()->author()->friendlyName();
if ( author.indexOf( '@' ) > 0 )
{
author = author.mid( 0, author.indexOf( '@' ) );
}
/* const int w = painter->fontMetrics().width( author ) + 2;
QRect avatarNameRect( opt.rect.width() - 10 - w, r.bottom(), w, opt.rect.bottom() - r.bottom() );
painter->drawText( avatarNameRect, author, QTextOption( Qt::AlignCenter ) );
/* const int w = painter->fontMetrics().width( author ) + 2;
QRect avatarNameRect( opt.rect.width() - 10 - w, r.bottom(), w, opt.rect.bottom() - r.bottom() );
painter->drawText( avatarNameRect, author, QTextOption( Qt::AlignCenter ) );
const int leftEdge = opt.rect.width() - qMin( avatarNameRect.left(), r.left() );*/
const int leftEdge = opt.rect.width() - qMin( avatarNameRect.left(), r.left() );*/
const int leftEdge = opt.rect.width() - pixmapRect.left();
QString descText;
if ( type == RecentlyPlayedPlaylistsModel::Station )

View File

@@ -32,12 +32,12 @@ namespace Widgets
class TOMAHAWK_WIDGETS_EXPORT PlaylistDelegate : public QStyledItemDelegate
{
Q_OBJECT
Q_OBJECT
public:
public:
PlaylistDelegate();
protected:
protected:
void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const;
};

View File

@@ -51,8 +51,12 @@ void
PlaylistWidget::verifySize()
{
if ( !model() )
{
return;
}
if ( model()->rowCount() > 0 )
{
setFixedHeight( model()->rowCount() * itemDelegate()->sizeHint( QStyleOptionViewItem(), model()->index( 0, 0 ) ).height() + frameWidth() * 2 );
}
}

View File

@@ -28,28 +28,31 @@
namespace Tomahawk
{
namespace Widgets
{
class TOMAHAWK_WIDGETS_EXPORT PlaylistWidget : public QListView
{
Q_OBJECT
Q_OBJECT
public:
public:
PlaylistWidget( QWidget* parent = 0 );
OverlayWidget* overlay() const { return m_overlay; }
OverlayWidget* overlay() const
{
return m_overlay;
}
virtual void setModel( QAbstractItemModel* model );
signals:
signals:
void modelChanged();
private slots:
private slots:
void verifySize();
private:
private:
OverlayWidget* m_overlay;
};

View File

@@ -64,11 +64,11 @@ SocialPlaylistWidget::SocialPlaylistWidget ( QWidget* parent )
TomahawkUtils::unmarginLayout( ui->verticalLayout_3->layout() );
TomahawkUtils::unmarginLayout( ui->verticalLayout_4->layout() );
// ui->mostPlayedPlaylists->setItemDelegate( new PlaylistDelegate() );
// ui->mostPlayedPlaylists->setModel( model );
// ui->mostPlayedPlaylists->overlay()->resize( 380, 86 );
// ui->mostPlayedPlaylists->setItemDelegate( new PlaylistDelegate() );
// ui->mostPlayedPlaylists->setModel( model );
// ui->mostPlayedPlaylists->overlay()->resize( 380, 86 );
// connect( model, SIGNAL( emptinessChanged( bool) ), this, SLOT( updatePlaylists() ) );
// connect( model, SIGNAL( emptinessChanged( bool) ), this, SLOT( updatePlaylists() ) );
m_topForeignTracksModel = new PlaylistModel( ui->newTracksView );
ui->newTracksView->setPlaylistModel( m_topForeignTracksModel );
@@ -78,16 +78,16 @@ SocialPlaylistWidget::SocialPlaylistWidget ( QWidget* parent )
m_popularNewAlbumsModel = new PlayableModel( ui->newAlbumsView );
ui->newAlbumsView->setPlayableModel( m_popularNewAlbumsModel );
// TODO run the genericselect command
// m_recentAlbumsModel->addFilteredCollection( collection_ptr(), 20, DatabaseCommand_AllAlbums::ModificationTime );
/*
m_timer = new QTimer( this );
connect( m_timer, SIGNAL( timeout() ), SLOT( checkQueries() ) );
// m_recentAlbumsModel->addFilteredCollection( collection_ptr(), 20, DatabaseCommand_AllAlbums::ModificationTime );
/*
m_timer = new QTimer( this );
connect( m_timer, SIGNAL( timeout() ), SLOT( checkQueries() ) );
connect( SourceList::instance(), SIGNAL( ready() ), SLOT( updateRecentTracks() ) );
connect( SourceList::instance(), SIGNAL( sourceAdded( Tomahawk::source_ptr ) ), SLOT( onSourceAdded( Tomahawk::source_ptr ) ) );
connect( ui->playlistWidget, SIGNAL( activated( QModelIndex ) ), SLOT( onPlaylistActivated( QModelIndex ) ) );
connect( AudioEngine::instance() ,SIGNAL( playlistChanged( Tomahawk::playlistinterface_ptr ) ), this, SLOT( updatePlaylists() ), Qt::QueuedConnection );
*/
connect( SourceList::instance(), SIGNAL( ready() ), SLOT( updateRecentTracks() ) );
connect( SourceList::instance(), SIGNAL( sourceAdded( Tomahawk::source_ptr ) ), SLOT( onSourceAdded( Tomahawk::source_ptr ) ) );
connect( ui->playlistWidget, SIGNAL( activated( QModelIndex ) ), SLOT( onPlaylistActivated( QModelIndex ) ) );
connect( AudioEngine::instance() ,SIGNAL( playlistChanged( Tomahawk::playlistinterface_ptr ) ), this, SLOT( updatePlaylists() ), Qt::QueuedConnection );
*/
fetchFromDB();
}
@@ -105,9 +105,9 @@ SocialPlaylistWidget::fetchFromDB()
connect( albumsCmd.data(), SIGNAL( albums( QList<Tomahawk::album_ptr> ) ), this, SLOT( popularAlbumsFetched( QList<Tomahawk::album_ptr> ) ) );
Database::instance()->enqueue( Tomahawk::dbcmd_ptr( albumsCmd ) );
// QSharedPointer<DatabaseCommand_GenericSelect> plCmd = QSharedPointer<DatabaseCommand_GenericSelect>( new DatabaseCommand_GenericSelect( s_mostPlayedPlaylistsQuery, DatabaseCommand_GenericSelect::, 30, 0 ) );
// connect( albumsCmd.data(), SIGNAL( albums( QList<Tomahawk::album_ptr> ) ), this, SLOT( popularAlbumsFetched( QList<Tomahawk::album_ptr> ) ) );
// Database::instance()->enqueue( Tomahawk::dbcmd_ptr( albumsCmd ) );
// QSharedPointer<DatabaseCommand_GenericSelect> plCmd = QSharedPointer<DatabaseCommand_GenericSelect>( new DatabaseCommand_GenericSelect( s_mostPlayedPlaylistsQuery, DatabaseCommand_GenericSelect::, 30, 0 ) );
// connect( albumsCmd.data(), SIGNAL( albums( QList<Tomahawk::album_ptr> ) ), this, SLOT( popularAlbumsFetched( QList<Tomahawk::album_ptr> ) ) );
// Database::instance()->enqueue( Tomahawk::dbcmd_ptr( albumsCmd ) );
QSharedPointer<DatabaseCommand_GenericSelect> trackCmd = QSharedPointer<DatabaseCommand_GenericSelect>( new DatabaseCommand_GenericSelect( s_topForeignTracksQuery, DatabaseCommand_GenericSelect::Track, 50, 0 ) );
connect( trackCmd.data(), SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( topForeignTracksFetched( QList<Tomahawk::query_ptr> ) ) );

View File

@@ -56,32 +56,57 @@ class TOMAHAWK_WIDGETS_EXPORT SocialPlaylistWidget : public QWidget, public Toma
{
Q_OBJECT
public:
public:
SocialPlaylistWidget( QWidget* parent = 0 );
~SocialPlaylistWidget();
virtual QWidget* widget() { return this; }
virtual QWidget* widget()
{
return this;
}
virtual Tomahawk::playlistinterface_ptr playlistInterface() const;
virtual QString title() const { return m_title; }
virtual QString description() const { return m_description; }
virtual QString longDescription() const { return m_longDescription; }
virtual QPixmap pixmap() const { if ( m_pixmap.isNull() ) return Tomahawk::ViewPage::pixmap(); else return m_pixmap; }
virtual bool jumpToCurrentTrack() { return false; }
virtual QString title() const
{
return m_title;
}
virtual QString description() const
{
return m_description;
}
virtual QString longDescription() const
{
return m_longDescription;
}
virtual QPixmap pixmap() const
{
if ( m_pixmap.isNull() )
{
return Tomahawk::ViewPage::pixmap();
}
else
{
return m_pixmap;
}
}
virtual bool jumpToCurrentTrack()
{
return false;
}
signals:
signals:
void longDescriptionChanged( const QString& description );
void descriptionChanged( const QString& description );
void pixmapChanged( const QPixmap& pixmap );
private slots:
private slots:
void popularAlbumsFetched( QList<Tomahawk::album_ptr> );
void topForeignTracksFetched( QList<Tomahawk::query_ptr> );
private:
private:
void fetchFromDB();
Ui_SocialPlaylistWidget *ui;
Ui_SocialPlaylistWidget* ui;
PlaylistModel* m_topForeignTracksModel;
PlayableModel* m_popularNewAlbumsModel;

View File

@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
*

View File

@@ -32,7 +32,7 @@
// Forward Declarations breaking QSharedPointer
#if QT_VERSION < QT_VERSION_CHECK( 5, 0, 0 )
#include "Query.h"
#include "Query.h"
#endif
@@ -55,26 +55,26 @@ ActionCollection::~ActionCollection()
{
s_instance = 0;
foreach( QString key, m_actionCollection.keys() )
delete m_actionCollection[ key ];
delete m_actionCollection[ key ];
}
void
ActionCollection::initActions()
{
QAction *latchOn = new QAction( tr( "&Listen Along" ), this );
QAction* latchOn = new QAction( tr( "&Listen Along" ), this );
latchOn->setIcon( ImageRegistry::instance()->icon( RESPATH "images/headphones.svg" ) );
m_actionCollection[ "latchOn" ] = latchOn;
QAction *latchOff = new QAction( tr( "Stop &Listening Along" ), this );
QAction* latchOff = new QAction( tr( "Stop &Listening Along" ), this );
latchOff->setIcon( ImageRegistry::instance()->icon( RESPATH "images/headphones-off.svg" ) );
m_actionCollection[ "latchOff" ] = latchOff;
QAction *realtimeFollowingAlong = new QAction( tr( "&Follow in real-time" ), this );
QAction* realtimeFollowingAlong = new QAction( tr( "&Follow in real-time" ), this );
realtimeFollowingAlong->setCheckable( true );
m_actionCollection[ "realtimeFollowingAlong" ] = realtimeFollowingAlong;
bool isPublic = TomahawkSettings::instance()->privateListeningMode() == TomahawkSettings::PublicListening;
QAction *privacyToggle = new QAction( ( isPublic ? tr( "&Listen Privately" ) : tr( "&Listen Publicly" ) ), this );
QAction* privacyToggle = new QAction( ( isPublic ? tr( "&Listen Privately" ) : tr( "&Listen Publicly" ) ), this );
privacyToggle->setIcon( ImageRegistry::instance()->icon( RESPATH "images/private-listening.svg" ) );
privacyToggle->setIconVisibleInMenu( isPublic );
m_actionCollection[ "togglePrivacy" ] = privacyToggle;
@@ -102,7 +102,7 @@ ActionCollection::initActions()
m_actionCollection[ "quit" ]->setMenuRole( QAction::QuitRole );
// connect actions to AudioEngine
AudioEngine *ae = AudioEngine::instance();
AudioEngine* ae = AudioEngine::instance();
connect( m_actionCollection[ "playPause" ], SIGNAL( triggered() ), ae, SLOT( playPause() ), Qt::UniqueConnection );
connect( m_actionCollection[ "stop" ], SIGNAL( triggered() ), ae, SLOT( stop() ), Qt::UniqueConnection );
connect( m_actionCollection[ "previousTrack" ], SIGNAL( triggered() ), ae, SLOT( previous() ), Qt::UniqueConnection );
@@ -138,7 +138,7 @@ ActionCollection::initActions()
m_actionCollection[ "legalInfo" ]->setMenuRole( QAction::ApplicationSpecificRole );
m_actionCollection[ "openLogfile" ] = new QAction( tr( "&View Logfile" ), this );
m_actionCollection[ "openLogfile" ]->setMenuRole( QAction::ApplicationSpecificRole );
#if defined( Q_OS_MAC ) && defined( HAVE_SPARKLE ) || defined( Q_OS_WIN )
#if defined( Q_OS_MAC ) && defined( HAVE_SPARKLE ) || defined( Q_OS_WIN )
m_actionCollection[ "checkForUpdates" ] = new QAction( tr( "Check For Updates..." ), this );
m_actionCollection[ "checkForUpdates" ]->setMenuRole( QAction::ApplicationSpecificRole );
#endif
@@ -147,7 +147,7 @@ ActionCollection::initActions()
QMenuBar*
ActionCollection::createMenuBar( QWidget *parent )
ActionCollection::createMenuBar( QWidget* parent )
{
QMenuBar* menuBar = new QMenuBar( parent );
@@ -212,7 +212,7 @@ ActionCollection::createMenuBar( QWidget *parent )
QMenu*
ActionCollection::createCompactMenu( QWidget *parent )
ActionCollection::createCompactMenu( QWidget* parent )
{
QMenu* compactMenu = new QMenu( tr( "Main Menu" ), parent );
@@ -273,7 +273,9 @@ ActionCollection::addAction( ActionCollection::ActionDestination category, QActi
m_categoryActions[ category ] = actions;
if ( notify )
{
m_actionNotifiers[ action ] = notify;
}
}
@@ -321,11 +323,15 @@ ActionCollection::togglePrivateListeningMode()
{
tDebug() << Q_FUNC_INFO;
if ( TomahawkSettings::instance()->privateListeningMode() == TomahawkSettings::PublicListening )
{
TomahawkSettings::instance()->setPrivateListeningMode( TomahawkSettings::FullyPrivate );
}
else
{
TomahawkSettings::instance()->setPrivateListeningMode( TomahawkSettings::PublicListening );
}
QAction *privacyToggle = m_actionCollection[ "togglePrivacy" ];
QAction* privacyToggle = m_actionCollection[ "togglePrivacy" ];
bool isPublic = TomahawkSettings::instance()->privateListeningMode() == TomahawkSettings::PublicListening;
privacyToggle->setText( ( isPublic ? tr( "&Listen Privately" ) : tr( "&Listen Publicly" ) ) );
privacyToggle->setIconVisibleInMenu( isPublic );

View File

@@ -30,16 +30,17 @@ class DLLEXPORT ActionCollection : public QObject
{
Q_OBJECT
public:
public:
// Categories for custom-registered actions
enum ActionDestination {
// Tracks, TODO
enum ActionDestination
{
// Tracks, TODO
LocalPlaylists = 0
};
static ActionCollection* instance();
ActionCollection( QObject *parent );
ActionCollection( QObject* parent );
~ActionCollection();
void initActions();
@@ -47,7 +48,7 @@ public:
/**
* This method returns a main menu bar, suitable for Windows, Mac and X11.
*/
QMenuBar *createMenuBar( QWidget *parent );
QMenuBar* createMenuBar( QWidget* parent );
/**
* Returns a QMenu with all the entries that would normally be in the main menu,
@@ -55,7 +56,7 @@ public:
* and fairly little sense on Unity and other X11 desktop configurations which pull
* out the menu bar from the window.
*/
QMenu *createCompactMenu( QWidget *parent );
QMenu* createCompactMenu( QWidget* parent );
QAction* getAction( const QString& name );
QList< QAction* > getAction( ActionDestination category );
@@ -87,13 +88,13 @@ public:
void removeAction( QAction* action );
void removeAction( QAction* action, ActionDestination category );
public slots:
public slots:
void togglePrivateListeningMode();
signals:
signals:
void privacyModeChanged();
private:
private:
static ActionCollection* s_instance;
QHash< QString, QAction* > m_actionCollection;

View File

@@ -63,7 +63,9 @@ album_ptr
Album::get( const Tomahawk::artist_ptr& artist, const QString& name, bool autoCreate )
{
if ( !Database::instance() || !Database::instance()->impl() )
{
return album_ptr();
}
QMutexLocker lock( &s_nameCacheMutex );
const QString key = albumCacheKey( artist, name );
@@ -71,7 +73,9 @@ Album::get( const Tomahawk::artist_ptr& artist, const QString& name, bool autoCr
{
album_wptr album = s_albumsByName.value( key );
if ( album )
{
return album.toStrongRef();
}
}
album_ptr album = album_ptr( new Album( name, artist ), &Album::deleteLater );
@@ -93,7 +97,9 @@ Album::get( unsigned int id, const QString& name, const Tomahawk::artist_ptr& ar
s_idMutex.unlock();
if ( album )
{
return album;
}
}
s_idMutex.unlock();
@@ -103,7 +109,9 @@ Album::get( unsigned int id, const QString& name, const Tomahawk::artist_ptr& ar
{
album_wptr album = s_albumsByName.value( key );
if ( album )
{
return album;
}
}
album_ptr a = album_ptr( new Album( id, name, artist ), &Album::deleteLater );
@@ -213,7 +221,9 @@ Album::id() const
d->waitingForId = false;
if ( d->id > 0 )
{
s_albumsById.insert( d->id, d->ownRef.toStrongRef() );
}
s_idMutex.unlock();
}
@@ -251,7 +261,9 @@ Album::cover( const QSize& size, bool forceLoad ) const
if ( !d->coverLoaded && !d->coverLoading )
{
if ( !forceLoad )
{
return QPixmap();
}
Tomahawk::InfoSystem::InfoStringHash trackInfo;
trackInfo["artist"] = d->artist->name();
@@ -264,12 +276,12 @@ Album::cover( const QSize& size, bool forceLoad ) const
requestData.customData = QVariantMap();
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
SIGNAL( finished( QString ) ),
SLOT( infoSystemFinished( QString ) ) );
SIGNAL( finished( QString ) ),
SLOT( infoSystemFinished( QString ) ) );
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
@@ -300,9 +312,13 @@ Album::cover( const QSize& size, bool forceLoad ) const
}
if ( d->cover )
{
return *d->cover;
}
else
{
return QPixmap();
}
}
bool
@@ -318,7 +334,7 @@ Album::infoSystemInfo( const Tomahawk::InfoSystem::InfoRequestData& requestData,
{
Q_D( Album );
if ( requestData.caller != infoid() ||
requestData.type != Tomahawk::InfoSystem::InfoAlbumCoverArt )
requestData.type != Tomahawk::InfoSystem::InfoAlbumCoverArt )
{
return;
}
@@ -347,7 +363,9 @@ Album::infoSystemFinished( const QString& target )
{
Q_D( Album );
if ( target != infoid() )
{
return;
}
disconnect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
this, SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
@@ -370,7 +388,7 @@ Album::playlistInterface( ModelMode mode, const Tomahawk::collection_ptr& collec
{
pli = Tomahawk::playlistinterface_ptr( new Tomahawk::AlbumPlaylistInterface( this, mode, collection ) );
connect( pli.data(), SIGNAL( tracksLoaded( Tomahawk::ModelMode, Tomahawk::collection_ptr ) ),
SLOT( onTracksLoaded( Tomahawk::ModelMode, Tomahawk::collection_ptr ) ) );
SLOT( onTracksLoaded( Tomahawk::ModelMode, Tomahawk::collection_ptr ) ) );
d->playlistInterface[ mode ][ collection ] = pli;
}
@@ -407,7 +425,9 @@ Album::infoid() const
{
Q_D( const Album );
if ( d->uuid.isEmpty() )
{
d->uuid = uuid();
}
return d->uuid;
}

View File

@@ -27,7 +27,7 @@
// Forward Declarations breaking QSharedPointer
#if QT_VERSION < QT_VERSION_CHECK( 5, 0, 0 )
#include "collection/Collection.h"
#include "collection/Collection.h"
#endif
#include "infosystem/InfoSystem.h"
@@ -43,9 +43,9 @@ class IdThreadWorker;
class DLLEXPORT Album : public QObject
{
Q_OBJECT
Q_OBJECT
public:
public:
static album_ptr get( const Tomahawk::artist_ptr& artist, const QString& name, bool autoCreate = false );
static album_ptr get( unsigned int id, const QString& name, const Tomahawk::artist_ptr& artist );
@@ -69,24 +69,24 @@ public:
void loadId( bool autoCreate );
public slots:
public slots:
void deleteLater();
signals:
signals:
void tracksAdded( const QList<Tomahawk::query_ptr>& tracks, Tomahawk::ModelMode mode, const Tomahawk::collection_ptr& collection );
void updated();
void coverChanged();
protected:
protected:
QScopedPointer<AlbumPrivate> d_ptr;
private slots:
private slots:
void onTracksLoaded( Tomahawk::ModelMode mode, const Tomahawk::collection_ptr& collection );
void infoSystemInfo( const Tomahawk::InfoSystem::InfoRequestData& requestData, const QVariant& output );
void infoSystemFinished( const QString& target );
private:
private:
Q_DECLARE_PRIVATE( Album )
Q_DISABLE_COPY( Album )
QString infoid() const;

View File

@@ -72,15 +72,21 @@ AlbumPlaylistInterface::siblingIndex( int itemsAway, qint64 rootIndex ) const
{
qint64 p = m_currentIndex;
if ( rootIndex >= 0 )
{
p = rootIndex;
}
p += itemsAway;
if ( p < 0 )
{
return -1;
}
if ( p >= m_queries.count() )
{
return -1;
}
return p;
}
@@ -100,13 +106,13 @@ AlbumPlaylistInterface::setCurrentTrack( unsigned int albumpos )
Q_ASSERT( false );
return false;
/* albumpos--;
if ( ( int ) albumpos >= m_queries.count() )
return false;
/* albumpos--;
if ( ( int ) albumpos >= m_queries.count() )
return false;
m_currentTrack = albumpos;
m_currentItem = m_queries.at( albumpos )->results().first();
return true;*/
m_currentTrack = albumpos;
m_currentItem = m_queries.at( albumpos )->results().first();
return true;*/
}
@@ -130,12 +136,12 @@ AlbumPlaylistInterface::tracks() const
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
SIGNAL( finished( QString ) ),
SLOT( infoSystemFinished( QString ) ) );
SIGNAL( finished( QString ) ),
SLOT( infoSystemFinished( QString ) ) );
const_cast< int& >( m_lastQueryTimestamp ) = QDateTime::currentMSecsSinceEpoch();
}
@@ -147,7 +153,7 @@ AlbumPlaylistInterface::tracks() const
cmd->setAlbum( m_album->weakRef() );
cmd->setSortOrder( DatabaseCommand_AllTracks::AlbumPosition );
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr>, QVariant ) ),
SLOT( onTracksLoaded( QList<Tomahawk::query_ptr> ) ) );
SLOT( onTracksLoaded( QList<Tomahawk::query_ptr> ) ) );
Database::instance()->enqueue( Tomahawk::dbcmd_ptr( cmd ) );
}
else
@@ -172,7 +178,9 @@ void
AlbumPlaylistInterface::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
{
if ( requestData.caller != id() )
{
return;
}
switch ( requestData.type )
{
@@ -193,12 +201,14 @@ AlbumPlaylistInterface::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData re
// which should make this easier. --Teo 11/2011
unsigned int trackNo = 1;
foreach ( const QString& trackName, tracks )
foreach ( const QString & trackName, tracks )
{
track_ptr track = Track::get( inputInfo[ "artist" ], trackName, inputInfo[ "album" ], 0, QString(), trackNo++ );
query_ptr query = Query::get( track );
if ( query )
{
ql << query;
}
}
Pipeline::instance()->resolve( ql );
@@ -227,7 +237,9 @@ void
AlbumPlaylistInterface::infoSystemFinished( const QString& infoId )
{
if ( infoId != id() )
{
return;
}
m_infoSystemLoaded = true;
disconnect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
@@ -243,7 +255,7 @@ AlbumPlaylistInterface::infoSystemFinished( const QString& infoId )
cmd->setAlbum( m_album->weakRef() );
cmd->setSortOrder( DatabaseCommand_AllTracks::AlbumPosition );
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr>, QVariant ) ),
SLOT( onTracksLoaded( QList<Tomahawk::query_ptr> ) ) );
SLOT( onTracksLoaded( QList<Tomahawk::query_ptr> ) ) );
Database::instance()->enqueue( Tomahawk::dbcmd_ptr( cmd ) );
}
else
@@ -274,7 +286,9 @@ AlbumPlaylistInterface::onTracksLoaded( const QList< query_ptr >& tracks )
m_queries << filterTracks( tracks );
}
else
{
m_queries << tracks;
}
checkQueries();
@@ -287,10 +301,12 @@ qint64
AlbumPlaylistInterface::indexOfResult( const Tomahawk::result_ptr& result ) const
{
int i = 0;
foreach ( const Tomahawk::query_ptr& query, m_queries )
foreach ( const Tomahawk::query_ptr & query, m_queries )
{
if ( query->numResults() && query->results().contains( result ) )
{
return i;
}
i++;
}
@@ -303,10 +319,12 @@ qint64
AlbumPlaylistInterface::indexOfQuery( const Tomahawk::query_ptr& query ) const
{
int i = 0;
foreach ( const Tomahawk::query_ptr& q, m_queries )
foreach ( const Tomahawk::query_ptr & q, m_queries )
{
if ( q->equals( query ) )
{
return i;
}
i++;
}
@@ -332,7 +350,9 @@ AlbumPlaylistInterface::resultAt( qint64 index ) const
{
Tomahawk::query_ptr query = queryAt( index );
if ( query && query->numResults() )
{
return query->results().first();
}
return Tomahawk::result_ptr();
}
@@ -341,7 +361,7 @@ AlbumPlaylistInterface::resultAt( qint64 index ) const
void
AlbumPlaylistInterface::checkQueries()
{
foreach ( const Tomahawk::query_ptr& query, m_queries )
foreach ( const Tomahawk::query_ptr & query, m_queries )
{
connect( query.data(), SIGNAL( playableStateChanged( bool ) ), SLOT( onItemsChanged() ), Qt::UniqueConnection );
}

View File

@@ -34,15 +34,18 @@ namespace Tomahawk
class DLLEXPORT AlbumPlaylistInterface : public Tomahawk::PlaylistInterface
{
Q_OBJECT
Q_OBJECT
public:
public:
AlbumPlaylistInterface( Tomahawk::Album* album, Tomahawk::ModelMode mode, const Tomahawk::collection_ptr& collection );
virtual ~AlbumPlaylistInterface();
QList<Tomahawk::query_ptr> tracks() const;
virtual int trackCount() const { return m_queries.count(); }
virtual int trackCount() const
{
return m_queries.count();
}
virtual void setCurrentIndex( qint64 index );
virtual qint64 siblingIndex( int itemsAway, qint64 rootIndex = -1 ) const;
@@ -54,22 +57,28 @@ public:
virtual Tomahawk::result_ptr currentItem() const;
virtual PlaylistModes::RepeatMode repeatMode() const { return PlaylistModes::NoRepeat; }
virtual bool shuffled() const { return false; }
virtual PlaylistModes::RepeatMode repeatMode() const
{
return PlaylistModes::NoRepeat;
}
virtual bool shuffled() const
{
return false;
}
virtual void setRepeatMode( PlaylistModes::RepeatMode ) {}
virtual void setShuffled( bool ) {}
virtual bool setCurrentTrack( unsigned int albumpos );
signals:
signals:
void tracksLoaded( Tomahawk::ModelMode mode, const Tomahawk::collection_ptr& collection );
private slots:
private slots:
void onTracksLoaded( const QList< Tomahawk::query_ptr >& tracks );
void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
void infoSystemFinished( const QString& infoId );
private:
private:
void checkQueries();
QList< Tomahawk::query_ptr > m_queries;

View File

@@ -29,7 +29,7 @@ namespace Tomahawk
class AlbumPrivate
{
public:
public:
AlbumPrivate( Album* q, unsigned int _id, const QString& _name, const Tomahawk::artist_ptr& _artist )
: q_ptr( q )
, waitingForId( false )
@@ -58,7 +58,7 @@ public:
Album* q_ptr;
Q_DECLARE_PUBLIC( Album )
private:
private:
mutable bool waitingForId;
mutable QFuture<unsigned int> idFuture;
mutable unsigned int id;

View File

@@ -62,7 +62,9 @@ artist_ptr
Artist::get( const QString& name, bool autoCreate )
{
if ( name.isEmpty() )
{
return artist_ptr();
}
QMutexLocker lock( &s_nameCacheMutex );
const QString key = name.toLower();
@@ -70,11 +72,15 @@ Artist::get( const QString& name, bool autoCreate )
{
artist_wptr artist = s_artistsByName.value( key );
if ( artist )
{
return artist.toStrongRef();
}
}
if ( !Database::instance() || !Database::instance()->impl() )
{
return artist_ptr();
}
artist_ptr artist = artist_ptr( new Artist( name ), &Artist::deleteLater );
artist->setWeakRef( artist.toWeakRef() );
@@ -97,7 +103,9 @@ Artist::get( unsigned int id, const QString& name )
s_idMutex.unlock();
if ( !artist.isNull() )
{
return artist;
}
}
s_idMutex.unlock();
@@ -107,7 +115,9 @@ Artist::get( unsigned int id, const QString& name )
{
artist_wptr artist = s_artistsByName.value( key );
if ( !artist.isNull() )
{
return artist;
}
}
artist_ptr a = artist_ptr( new Artist( id, name ), &Artist::deleteLater );
@@ -217,7 +227,9 @@ Artist::albums( ModelMode mode, const Tomahawk::collection_ptr& collection ) con
bool dbLoaded = m_albumsLoaded.value( DatabaseMode );
const bool infoLoaded = m_albumsLoaded.value( InfoSystemMode );
if ( !collection.isNull() )
{
dbLoaded = false;
}
if ( ( mode == DatabaseMode || mode == Mixed ) && !dbLoaded )
{
@@ -227,7 +239,7 @@ Artist::albums( ModelMode mode, const Tomahawk::collection_ptr& collection ) con
cmd->setData( QVariant( collection.isNull() ) );
connect( cmd, SIGNAL( albums( QList<Tomahawk::album_ptr>, QVariant ) ),
SLOT( onAlbumsFound( QList<Tomahawk::album_ptr>, QVariant ) ) );
SLOT( onAlbumsFound( QList<Tomahawk::album_ptr>, QVariant ) ) );
Database::instance()->enqueue( Tomahawk::dbcmd_ptr( cmd ) );
}
@@ -269,7 +281,9 @@ Artist::albums( ModelMode mode, const Tomahawk::collection_ptr& collection ) con
}
if ( !collection.isNull() )
{
return QList<album_ptr>();
}
switch ( mode )
{
@@ -300,12 +314,12 @@ Artist::similarArtists() const
requestData.requestId = TomahawkUtils::infosystemRequestId();
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
SIGNAL( finished( QString ) ),
SLOT( infoSystemFinished( QString ) ), Qt::UniqueConnection );
SIGNAL( finished( QString ) ),
SLOT( infoSystemFinished( QString ) ), Qt::UniqueConnection );
m_infoJobs++;
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
@@ -341,19 +355,21 @@ Artist::id() const
if ( waiting )
{
// qDebug() << Q_FUNC_INFO << "Asked for artist ID and NOT loaded yet" << m_name << m_idFuture.isFinished();
// qDebug() << Q_FUNC_INFO << "Asked for artist ID and NOT loaded yet" << m_name << m_idFuture.isFinished();
m_idFuture.waitForFinished();
// qDebug() << "DONE WAITING:" << m_idFuture.resultCount() << m_idFuture.isResultReadyAt( 0 ) << m_idFuture.isCanceled() << m_idFuture.isFinished() << m_idFuture.isPaused() << m_idFuture.isRunning() << m_idFuture.isStarted();
// qDebug() << "DONE WAITING:" << m_idFuture.resultCount() << m_idFuture.isResultReadyAt( 0 ) << m_idFuture.isCanceled() << m_idFuture.isFinished() << m_idFuture.isPaused() << m_idFuture.isRunning() << m_idFuture.isStarted();
finalid = m_idFuture.result();
// qDebug() << Q_FUNC_INFO << "Got loaded artist:" << m_name << finalid;
// qDebug() << Q_FUNC_INFO << "Got loaded artist:" << m_name << finalid;
s_idMutex.lockForWrite();
m_id = finalid;
m_waitingForFuture = false;
if ( m_id > 0 )
{
s_artistsById.insert( m_id, m_ownRef.toStrongRef() );
}
s_idMutex.unlock();
}
@@ -377,12 +393,12 @@ Artist::biography() const
requestData.customData = QVariantMap();
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
SIGNAL( finished( QString ) ),
SLOT( infoSystemFinished( QString ) ), Qt::UniqueConnection );
SIGNAL( finished( QString ) ),
SLOT( infoSystemFinished( QString ) ), Qt::UniqueConnection );
m_infoJobs++;
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
@@ -399,13 +415,13 @@ Artist::loadStats()
{
DatabaseCommand_TrackStats* cmd = new DatabaseCommand_TrackStats( a );
Database::instance()->enqueue( Tomahawk::dbcmd_ptr(cmd) );
Database::instance()->enqueue( Tomahawk::dbcmd_ptr( cmd ) );
}
{
DatabaseCommand_ArtistStats* cmd = new DatabaseCommand_ArtistStats( a );
connect( cmd, SIGNAL( done( unsigned int, unsigned int, unsigned int ) ), SLOT( onArtistStatsLoaded( unsigned int, unsigned int, unsigned int ) ) );
Database::instance()->enqueue( Tomahawk::dbcmd_ptr(cmd) );
Database::instance()->enqueue( Tomahawk::dbcmd_ptr( cmd ) );
}
}
@@ -415,7 +431,7 @@ Artist::playbackHistory( const Tomahawk::source_ptr& source ) const
{
QList< Tomahawk::PlaybackLog > history;
foreach ( const PlaybackLog& log, m_playbackHistory )
foreach ( const PlaybackLog & log, m_playbackHistory )
{
if ( source.isNull() || log.source == source )
{
@@ -445,10 +461,12 @@ Artist::playbackCount( const source_ptr& source ) const
QMutexLocker locker( &s_memberMutex );
unsigned int count = 0;
foreach ( const PlaybackLog& log, m_playbackHistory )
foreach ( const PlaybackLog & log, m_playbackHistory )
{
if ( source.isNull() || log.source == source )
{
count++;
}
}
return count;
@@ -486,7 +504,9 @@ void
Artist::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
{
if ( requestData.caller != infoid() )
{
return;
}
QVariantMap returnedData = output.value< QVariantMap >();
switch ( requestData.type )
@@ -498,7 +518,7 @@ Artist::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVari
inputInfo = requestData.input.value< InfoSystem::InfoStringHash >();
QList< album_ptr > albums;
foreach ( const QString& albumName, albumNames )
foreach ( const QString & albumName, albumNames )
{
Tomahawk::album_ptr album = Tomahawk::Album::get( m_ownRef.toStrongRef(), albumName, false );
m_officialAlbums << album;
@@ -507,7 +527,9 @@ Artist::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVari
m_albumsLoaded.insert( InfoSystemMode, true );
if ( m_officialAlbums.count() )
{
emit albumsAdded( albums, InfoSystemMode );
}
break;
}
@@ -536,7 +558,7 @@ Artist::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVari
case InfoSystem::InfoArtistSimilars:
{
const QStringList artists = returnedData["artists"].toStringList();
foreach ( const QString& artist, artists )
foreach ( const QString & artist, artists )
{
m_similarArtists << Artist::get( artist );
}
@@ -550,10 +572,12 @@ Artist::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVari
case InfoSystem::InfoArtistBiography:
{
QVariantMap bmap = output.toMap();
foreach ( const QString& source, bmap.keys() )
foreach ( const QString & source, bmap.keys() )
{
if ( source == "last.fm" )
{
m_biography = bmap[ source ].toHash()[ "text" ].toString();
}
}
m_biographyLoaded = true;
@@ -574,7 +598,9 @@ Artist::infoSystemFinished( QString target )
Q_UNUSED( target );
if ( target != infoid() )
{
return;
}
if ( --m_infoJobs == 0 )
{
@@ -598,7 +624,9 @@ Artist::cover( const QSize& size, bool forceLoad ) const
if ( !m_coverLoaded && !m_coverLoading )
{
if ( !forceLoad )
{
return QPixmap();
}
Tomahawk::InfoSystem::InfoStringHash trackInfo;
trackInfo["artist"] = name();
@@ -610,12 +638,12 @@ Artist::cover( const QSize& size, bool forceLoad ) const
requestData.customData = QVariantMap();
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
SIGNAL( finished( QString ) ),
SLOT( infoSystemFinished( QString ) ), Qt::UniqueConnection );
SIGNAL( finished( QString ) ),
SLOT( infoSystemFinished( QString ) ), Qt::UniqueConnection );
m_infoJobs++;
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
@@ -647,9 +675,13 @@ Artist::cover( const QSize& size, bool forceLoad ) const
}
if ( m_cover )
{
return *m_cover;
}
else
{
return QPixmap();
}
}
#endif
@@ -663,7 +695,7 @@ Artist::playlistInterface( ModelMode mode, const Tomahawk::collection_ptr& colle
{
pli = Tomahawk::playlistinterface_ptr( new Tomahawk::ArtistPlaylistInterface( this, mode, collection ) );
connect( pli.data(), SIGNAL( tracksLoaded( Tomahawk::ModelMode, Tomahawk::collection_ptr ) ),
SLOT( onTracksLoaded( Tomahawk::ModelMode, Tomahawk::collection_ptr ) ) );
SLOT( onTracksLoaded( Tomahawk::ModelMode, Tomahawk::collection_ptr ) ) );
m_playlistInterface[ mode ][ collection ] = pli;
}
@@ -683,7 +715,9 @@ QString
Artist::infoid() const
{
if ( m_uuid.isEmpty() )
{
m_uuid = uuid();
}
return m_uuid;
}

View File

@@ -22,7 +22,7 @@
#include <QtCore/QObject>
#ifndef ENABLE_HEADLESS
#include <QtGui/QPixmap>
#include <QtGui/QPixmap>
#endif
#include <QFuture>
@@ -39,9 +39,9 @@ class IdThreadWorker;
class DLLEXPORT Artist : public QObject
{
Q_OBJECT
Q_OBJECT
public:
public:
static artist_ptr get( const QString& name, bool autoCreate = false );
static artist_ptr get( unsigned int id, const QString& name );
@@ -50,8 +50,14 @@ public:
virtual ~Artist();
unsigned int id() const;
QString name() const { return m_name; }
QString sortname() const { return m_sortname; }
QString name() const
{
return m_name;
}
QString sortname() const
{
return m_sortname;
}
QList<album_ptr> albums( ModelMode mode = Mixed, const Tomahawk::collection_ptr& collection = Tomahawk::collection_ptr() ) const;
QList<artist_ptr> similarArtists() const;
@@ -72,19 +78,28 @@ public:
#ifndef ENABLE_HEADLESS
QPixmap cover( const QSize& size, bool forceLoad = true ) const;
#endif
bool coverLoaded() const { return m_coverLoaded; }
bool coverLoaded() const
{
return m_coverLoaded;
}
Tomahawk::playlistinterface_ptr playlistInterface();
QWeakPointer< Tomahawk::Artist > weakRef() { return m_ownRef; }
void setWeakRef( QWeakPointer< Tomahawk::Artist > weakRef ) { m_ownRef = weakRef; }
QWeakPointer< Tomahawk::Artist > weakRef()
{
return m_ownRef;
}
void setWeakRef( QWeakPointer< Tomahawk::Artist > weakRef )
{
m_ownRef = weakRef;
}
void loadId( bool autoCreate );
public slots:
public slots:
void deleteLater();
signals:
signals:
void tracksAdded( const QList<Tomahawk::query_ptr>& tracks, Tomahawk::ModelMode mode, const Tomahawk::collection_ptr& collection );
void albumsAdded( const QList<Tomahawk::album_ptr>& albums, Tomahawk::ModelMode mode );
@@ -94,7 +109,7 @@ signals:
void biographyLoaded();
void statsLoaded();
private slots:
private slots:
void onArtistStatsLoaded( unsigned int plays, unsigned int chartPos, unsigned int chartCount );
void onTracksLoaded( Tomahawk::ModelMode mode, const Tomahawk::collection_ptr& collection );
void onAlbumsFound( const QList<Tomahawk::album_ptr>& albums, const QVariant& collectionIsNull = QVariant( false ) );
@@ -102,7 +117,7 @@ private slots:
void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
void infoSystemFinished( QString target );
private:
private:
Artist();
QString infoid() const;

View File

@@ -64,15 +64,21 @@ ArtistPlaylistInterface::siblingIndex( int itemsAway, qint64 rootIndex ) const
{
qint64 p = m_currentIndex;
if ( rootIndex >= 0 )
{
p = rootIndex;
}
p += itemsAway;
if ( p < 0 )
{
return -1;
}
if ( p >= m_queries.count() )
{
return -1;
}
return p;
}
@@ -104,12 +110,12 @@ ArtistPlaylistInterface::tracks() const
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
SIGNAL( finished( QString ) ),
SLOT( infoSystemFinished( QString ) ) );
SIGNAL( finished( QString ) ),
SLOT( infoSystemFinished( QString ) ) );
}
else if ( m_mode == DatabaseMode && !m_databaseLoaded )
{
@@ -118,7 +124,7 @@ ArtistPlaylistInterface::tracks() const
cmd->setSortOrder( DatabaseCommand_AllTracks::AlbumPosition );
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr>, QVariant ) ),
SLOT( onTracksLoaded( QList<Tomahawk::query_ptr> ) ) );
SLOT( onTracksLoaded( QList<Tomahawk::query_ptr> ) ) );
Database::instance()->enqueue( Tomahawk::dbcmd_ptr( cmd ) );
}
@@ -132,7 +138,9 @@ void
ArtistPlaylistInterface::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
{
if ( requestData.caller != id() )
{
return;
}
switch ( requestData.type )
{
@@ -153,12 +161,14 @@ ArtistPlaylistInterface::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData r
// which should make this easier. --Teo 11/2011
unsigned int trackNo = 1;
foreach ( const QString& trackName, tracks )
foreach ( const QString & trackName, tracks )
{
track_ptr track = Track::get( inputInfo[ "artist" ], trackName, inputInfo[ "album" ], 0, QString(), trackNo++ );
query_ptr query = Query::get( track );
if ( query )
{
ql << query;
}
}
m_queries << ql;
@@ -176,22 +186,26 @@ ArtistPlaylistInterface::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData r
}
if ( !m_queries.isEmpty() )
{
infoSystemFinished( id() );
}
}
void
ArtistPlaylistInterface::infoSystemFinished( const QString &infoId )
ArtistPlaylistInterface::infoSystemFinished( const QString& infoId )
{
if ( infoId != id() )
{
return;
}
m_infoSystemLoaded = true;
disconnect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
this, SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
disconnect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ),
this, SLOT( infoSystemFinished( QString) ) );
this, SLOT( infoSystemFinished( QString ) ) );
if ( m_queries.isEmpty() && m_mode == Mixed )
{
@@ -201,7 +215,7 @@ ArtistPlaylistInterface::infoSystemFinished( const QString &infoId )
cmd->setSortOrder( DatabaseCommand_AllTracks::AlbumPosition );
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr>, QVariant ) ),
SLOT( onTracksLoaded( QList<Tomahawk::query_ptr> ) ) );
SLOT( onTracksLoaded( QList<Tomahawk::query_ptr> ) ) );
Database::instance()->enqueue( Tomahawk::dbcmd_ptr( cmd ) );
}
@@ -222,7 +236,9 @@ ArtistPlaylistInterface::onTracksLoaded( const QList< query_ptr >& tracks )
m_queries << filterTracks( tracks );
}
else
{
m_queries << tracks;
}
checkQueries();
@@ -235,10 +251,12 @@ qint64
ArtistPlaylistInterface::indexOfResult( const Tomahawk::result_ptr& result ) const
{
int i = 0;
foreach ( const Tomahawk::query_ptr& query, m_queries )
foreach ( const Tomahawk::query_ptr & query, m_queries )
{
if ( query->numResults() && query->results().contains( result ) )
{
return i;
}
i++;
}
@@ -251,10 +269,12 @@ qint64
ArtistPlaylistInterface::indexOfQuery( const Tomahawk::query_ptr& query ) const
{
int i = 0;
foreach ( const Tomahawk::query_ptr& q, m_queries )
foreach ( const Tomahawk::query_ptr & q, m_queries )
{
if ( q->equals( query ) )
{
return i;
}
i++;
}
@@ -280,7 +300,9 @@ ArtistPlaylistInterface::resultAt( qint64 index ) const
{
Tomahawk::query_ptr query = queryAt( index );
if ( query && query->numResults() )
{
return query->results().first();
}
return Tomahawk::result_ptr();
}
@@ -289,7 +311,7 @@ ArtistPlaylistInterface::resultAt( qint64 index ) const
void
ArtistPlaylistInterface::checkQueries()
{
foreach ( const Tomahawk::query_ptr& query, m_queries )
foreach ( const Tomahawk::query_ptr & query, m_queries )
{
connect( query.data(), SIGNAL( playableStateChanged( bool ) ), SLOT( onItemsChanged() ), Qt::UniqueConnection );
}

View File

@@ -33,15 +33,18 @@ namespace Tomahawk
class DLLEXPORT ArtistPlaylistInterface : public Tomahawk::PlaylistInterface
{
Q_OBJECT
Q_OBJECT
public:
public:
ArtistPlaylistInterface( Tomahawk::Artist* artist, Tomahawk::ModelMode mode, const Tomahawk::collection_ptr& collection );
virtual ~ArtistPlaylistInterface();
virtual QList<Tomahawk::query_ptr> tracks() const;
virtual int trackCount() const { return m_queries.count(); }
virtual int trackCount() const
{
return m_queries.count();
}
virtual void setCurrentIndex( qint64 index );
virtual qint64 siblingIndex( int itemsAway, qint64 rootIndex = -1 ) const;
@@ -52,21 +55,27 @@ public:
virtual Tomahawk::result_ptr currentItem() const;
virtual PlaylistModes::RepeatMode repeatMode() const { return PlaylistModes::NoRepeat; }
virtual bool shuffled() const { return false; }
virtual PlaylistModes::RepeatMode repeatMode() const
{
return PlaylistModes::NoRepeat;
}
virtual bool shuffled() const
{
return false;
}
virtual void setRepeatMode( PlaylistModes::RepeatMode ) {}
virtual void setShuffled( bool ) {}
signals:
signals:
void tracksLoaded( Tomahawk::ModelMode mode, const Tomahawk::collection_ptr& collection );
private slots:
private slots:
void onTracksLoaded( const QList< Tomahawk::query_ptr >& tracks );
void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
void infoSystemFinished( const QString& infoId );
private:
private:
Q_DISABLE_COPY( ArtistPlaylistInterface )
void checkQueries();

View File

@@ -52,7 +52,9 @@ bool
resolverSort( const Attica::Content& first, const Attica::Content& second )
{
if ( !first.attribute( "typeid" ).isEmpty() && second.attribute( "typeid" ).isEmpty() )
{
return true;
}
return first.downloads() > second.downloads();
}
@@ -66,14 +68,14 @@ AtticaManager::AtticaManager( QObject* parent )
connect( &m_manager, SIGNAL( providerAdded( Attica::Provider ) ), this, SLOT( providerAdded( Attica::Provider ) ) );
// resolvers
// m_manager.addProviderFile( QUrl( "http://bakery.tomahawk-player.org/resolvers/providers.xml" ) );
// m_manager.addProviderFile( QUrl( "http://bakery.tomahawk-player.org/resolvers/providers.xml" ) );
const QString url = QString( "%1/resolvers/providers.xml?version=%2" ).arg( hostname() ).arg( TomahawkUtils::appFriendlyVersion() );
QNetworkReply* reply = Tomahawk::Utils::nam()->get( QNetworkRequest( QUrl( url ) ) );
NewClosure( reply, SIGNAL( finished() ), this, SLOT( providerFetched( QNetworkReply* ) ), reply );
connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( providerError( QNetworkReply::NetworkError ) ) );
// m_manager.addProviderFile( QUrl( "http://lycophron/resolvers/providers.xml" ) );
// m_manager.addProviderFile( QUrl( "http://lycophron/resolvers/providers.xml" ) );
qRegisterMetaType< Attica::Content >( "Attica::Content" );
}
@@ -84,10 +86,12 @@ AtticaManager::~AtticaManager()
savePixmapsToCache();
foreach( const QString& id, m_resolverStates.keys() )
foreach( const QString & id, m_resolverStates.keys() )
{
if ( !m_resolverStates[ id ].pixmap )
{
continue;
}
delete m_resolverStates[ id ].pixmap;
}
@@ -100,7 +104,9 @@ AtticaManager::fetchMissingIcons()
foreach ( Content resolver, m_resolvers )
{
if ( !m_resolverStates.contains( resolver.id() ) )
{
m_resolverStates.insert( resolver.id(), Resolver() );
}
if ( !m_resolverStates.value( resolver.id() ).pixmap && !resolver.icons().isEmpty() && !resolver.icons().first().url().isEmpty() )
{
@@ -124,11 +130,13 @@ AtticaManager::loadPixmapsFromCache()
{
QDir cacheDir = TomahawkUtils::appDataDir();
if ( !cacheDir.cd( "atticacache" ) ) // doesn't exist, no cache
{
return;
}
qDebug() << "Loading resolvers from cache dir:" << cacheDir.absolutePath();
qDebug() << "Currently we know about these resolvers:" << m_resolverStates.keys();
foreach ( const QString& file, cacheDir.entryList( QStringList() << "*.png", QDir::Files | QDir::NoSymLinks ) )
foreach ( const QString & file, cacheDir.entryList( QStringList() << "*.png", QDir::Files | QDir::NoSymLinks ) )
{
// load all the pixmaps
QFileInfo info( file );
@@ -157,10 +165,12 @@ AtticaManager::savePixmapsToCache()
cacheDir.cd( "atticache" );
}
foreach( const QString& id, m_resolverStates.keys() )
foreach( const QString & id, m_resolverStates.keys() )
{
if ( !m_resolverStates[ id ].pixmap || !m_resolverStates[ id ].pixmapDirty )
{
continue;
}
const QString filename = cacheDir.absoluteFilePath( QString( "%1.png" ).arg( id ) );
QFile f( filename );
@@ -183,7 +193,9 @@ QPixmap
AtticaManager::iconForResolver( const Content& resolver )
{
if ( !m_resolverStates[ resolver.id() ].pixmap )
{
return QPixmap();
}
return *m_resolverStates.value( resolver.id() ).pixmap;
}
@@ -199,10 +211,12 @@ AtticaManager::resolvers() const
Content
AtticaManager::resolverForId( const QString& id ) const
{
foreach ( const Attica::Content& c, m_resolvers )
foreach ( const Attica::Content & c, m_resolvers )
{
if ( c.id() == id )
{
return c;
}
}
return Content();
@@ -233,7 +247,9 @@ QString
AtticaManager::pathFromId( const QString& resolverId ) const
{
if ( !m_resolverStates.contains( resolverId ) )
{
return QString();
}
return m_resolverStates.value( resolverId ).scriptPath;
}
@@ -257,7 +273,7 @@ AtticaManager::uploadRating( const Content& c )
TomahawkSettingsGui::instanceGui()->setAtticaResolverStates( m_resolverStates );
PostJob* job = m_resolverProvider.voteForContent( c.id(), (uint)c.rating() );
PostJob* job = m_resolverProvider.voteForContent( c.id(), ( uint )c.rating() );
connect( job, SIGNAL( finished( Attica::BaseJob* ) ), job, SLOT( deleteLater() ) );
job->start();
@@ -274,28 +290,28 @@ AtticaManager::userHasRated( const Content& c ) const
bool
AtticaManager::hasCustomAccountForAttica( const QString &id ) const
AtticaManager::hasCustomAccountForAttica( const QString& id ) const
{
return m_customAccounts.keys().contains( id );
}
Tomahawk::Accounts::Account*
AtticaManager::customAccountForAttica( const QString &id ) const
AtticaManager::customAccountForAttica( const QString& id ) const
{
return m_customAccounts.value( id );
}
void
AtticaManager::registerCustomAccount( const QString &atticaId, Tomahawk::Accounts::Account *account )
AtticaManager::registerCustomAccount( const QString& atticaId, Tomahawk::Accounts::Account* account )
{
m_customAccounts.insert( atticaId, account );
}
AtticaManager::Resolver
AtticaManager::resolverData(const QString &atticaId) const
AtticaManager::resolverData( const QString& atticaId ) const
{
return m_resolverStates.value( atticaId );
}
@@ -316,7 +332,9 @@ AtticaManager::providerFetched( QNetworkReply* reply )
{
Q_ASSERT( reply );
if ( !reply )
{
return;
}
m_manager.addProviderFromXml( reply->readAll() );
}
@@ -345,14 +363,18 @@ AtticaManager::categoriesReturned( BaseJob* j )
ListJob< Category >* job = static_cast< ListJob< Category >* >( j );
Category::List categories = job->itemList();
foreach ( const Category& category, categories )
foreach ( const Category & category, categories )
{
ListJob< Content >* job = m_resolverProvider.searchContents( Category::List() << category, QString(), Provider::Downloads, 0, 50 );
if ( category.name() == "Resolver" )
{
connect( job, SIGNAL( finished( Attica::BaseJob* ) ), this, SLOT( resolversList( Attica::BaseJob* ) ) );
}
else if ( category.name() == "BinaryResolver" )
{
connect( job, SIGNAL( finished( Attica::BaseJob* ) ), this, SLOT( binaryResolversList( Attica::BaseJob* ) ) );
}
job->start();
}
@@ -367,13 +389,15 @@ AtticaManager::resolversList( BaseJob* j )
m_resolvers.append( job->itemList() );
// Sanity check. if any resolvers are installed that don't exist on the hd, remove them.
foreach ( const QString& rId, m_resolverStates.keys() )
foreach ( const QString & rId, m_resolverStates.keys() )
{
if ( m_resolverStates[ rId ].state == Installed ||
m_resolverStates[ rId ].state == NeedsUpgrade )
m_resolverStates[ rId ].state == NeedsUpgrade )
{
if ( m_resolverStates[ rId ].binary )
{
continue;
}
// Guess location on disk
QDir dir( QString( "%1/atticaresolvers/%2" ).arg( TomahawkUtils::appDataDir().absolutePath() ).arg( rId ) );
@@ -425,7 +449,7 @@ AtticaManager::binaryResolversList( BaseJob* j )
platform = QString();
#endif
foreach ( const Content& c, binaryResolvers )
foreach ( const Content & c, binaryResolvers )
{
if ( !c.attribute( "typeid" ).isEmpty() && c.attribute( "typeid" ) == platform )
{
@@ -439,7 +463,8 @@ AtticaManager::binaryResolversList( BaseJob* j )
m_resolverStates.insert( c.id(), r );
}
else if ( m_resolverStates[ c.id() ].binary != true )
{ // HACK workaround... why is this not set in the first place sometimes? Migration issue?
{
// HACK workaround... why is this not set in the first place sometimes? Migration issue?
m_resolverStates[ c.id() ].binary = true;
}
@@ -486,7 +511,7 @@ AtticaManager::syncServerData()
// look for any newer. m_resolvers has list from server, and m_resolverStates will contain any locally installed ones
// also update ratings
tLog() << "Syncing server data!";
foreach ( const QString& id, m_resolverStates.keys() )
foreach ( const QString & id, m_resolverStates.keys() )
{
Resolver r = m_resolverStates[ id ];
for ( int i = 0; i < m_resolvers.size(); i++ )
@@ -494,7 +519,9 @@ AtticaManager::syncServerData()
Attica::Content upstream = m_resolvers[ i ];
// same resolver
if ( id != upstream.id() )
{
continue;
}
// Update our rating with the server's idea of rating if we haven't rated it
if ( m_resolverStates[ id ].userRating != -1 )
@@ -506,7 +533,7 @@ AtticaManager::syncServerData()
// DO we need to upgrade?
tDebug( LOGVERBOSE ) << "Upgrade check for" << upstream.id() << "local is" << r.version << "upstream is" << upstream.version() << "and state is: " << r.state;
if ( ( r.state == Installed || r.state == NeedsUpgrade ) &&
!upstream.version().isEmpty() )
!upstream.version().isEmpty() )
{
if ( TomahawkUtils::newerVersion( r.version, upstream.version() ) )
{
@@ -541,13 +568,15 @@ void AtticaManager::doInstallResolver( const Content& resolver, bool autoCreate,
emit startedInstalling( resolver.id() );
if ( m_resolverStates[ resolver.id() ].state != Upgrading )
{
m_resolverStates[ resolver.id() ].state = Installing;
}
m_resolverStates[ resolver.id() ].scriptPath = resolver.attribute( "mainscript" );
m_resolverStates[ resolver.id() ].version = resolver.version();
emit resolverStateChanged( resolver.id() );
// ItemJob< DownloadItem >* job = m_resolverProvider.downloadLink( resolver.id() );
// ItemJob< DownloadItem >* job = m_resolverProvider.downloadLink( resolver.id() );
QUrl url( QString( "%1/resolvers/v1/content/download/%2/1" ).arg( hostname() ).arg( resolver.id() ) );
TomahawkUtils::urlAddQueryItem( url, "tomahawkversion", TomahawkUtils::appFriendlyVersion() );
@@ -556,7 +585,7 @@ void AtticaManager::doInstallResolver( const Content& resolver, bool autoCreate,
r->setProperty( "resolverId", resolver.id() );
r->setProperty( "createAccount", autoCreate );
r->setProperty( "handler", QVariant::fromValue< QObject* >( handler ) );
r->setProperty( "binarySignature", resolver.attribute("signature"));
r->setProperty( "binarySignature", resolver.attribute( "signature" ) );
}
@@ -568,7 +597,9 @@ AtticaManager::upgradeResolver( const Content& resolver )
Q_ASSERT( m_resolverStates[ resolver.id() ].state == NeedsUpgrade );
if ( !m_resolverStates.contains( resolver.id() ) || m_resolverStates[ resolver.id() ].state != NeedsUpgrade )
{
return;
}
m_resolverStates[ resolver.id() ].state = Upgrading;
emit resolverStateChanged( resolver.id() );
@@ -579,45 +610,47 @@ AtticaManager::upgradeResolver( const Content& resolver )
void
AtticaManager::resolverDownloadFinished ( QNetworkReply *j )
AtticaManager::resolverDownloadFinished ( QNetworkReply* j )
{
Q_ASSERT( j );
if ( !j )
{
return;
}
if ( j->error() == QNetworkReply::NoError )
{
QDomDocument doc;
doc.setContent( j );
const QDomNodeList nodes = doc.documentElement().elementsByTagName( "downloadlink" );
if ( nodes.length() < 1 )
{
tLog() << "Found no download link for resolver:" << doc.toString();
return;
}
const QDomNodeList nodes = doc.documentElement().elementsByTagName( "downloadlink" );
if ( nodes.length() < 1 )
{
tLog() << "Found no download link for resolver:" << doc.toString();
return;
}
QUrl url( nodes.item( 0 ).toElement().text() );
// download the resolver itself :)
tDebug() << "Downloading resolver from url:" << url.toString();
QUrl url( nodes.item( 0 ).toElement().text() );
// download the resolver itself :)
tDebug() << "Downloading resolver from url:" << url.toString();
const QDomNodeList signatures = doc.documentElement().elementsByTagName( "signature" );
const QDomNodeList signatures = doc.documentElement().elementsByTagName( "signature" );
// Use the original signature provided
QString signature = j->property( "binarySignature" ).toString();
if ( signatures.size() > 0 )
{
// Use the original signature provided
QString signature = j->property( "binarySignature" ).toString();
if ( signatures.size() > 0 )
{
// THis download has an overriding signature. Take that one instead
const QString sig = signatures.item( 0 ).toElement().text();
tLog() << "Found overridden signature in binary download:" << sig;
signature = sig;
}
QNetworkReply* reply = Tomahawk::Utils::nam()->get( QNetworkRequest( url ) );
connect( reply, SIGNAL( finished() ), this, SLOT( payloadFetched() ) );
reply->setProperty( "resolverId", j->property( "resolverId" ) );
reply->setProperty( "createAccount", j->property( "createAccount" ) );
reply->setProperty( "handler", j->property( "handler" ) );
reply->setProperty( "binarySignature", signature );
const QString sig = signatures.item( 0 ).toElement().text();
tLog() << "Found overridden signature in binary download:" << sig;
signature = sig;
}
QNetworkReply* reply = Tomahawk::Utils::nam()->get( QNetworkRequest( url ) );
connect( reply, SIGNAL( finished() ), this, SLOT( payloadFetched() ) );
reply->setProperty( "resolverId", j->property( "resolverId" ) );
reply->setProperty( "createAccount", j->property( "createAccount" ) );
reply->setProperty( "handler", j->property( "handler" ) );
reply->setProperty( "binarySignature", signature );
}
else
{
@@ -654,7 +687,9 @@ AtticaManager::payloadFetched()
// Must have a signature for binary resolvers...
Q_ASSERT( !signature.isEmpty() );
if ( signature.isEmpty() )
{
return;
}
if ( !TomahawkUtils::verifyFile( f->fileName(), signature ) )
{
qWarning() << "FILE SIGNATURE FAILED FOR BINARY RESOLVER! WARNING! :" << f->fileName() << signature;
@@ -723,7 +758,7 @@ void
AtticaManager::uninstallResolver( const QString& pathToResolver )
{
// when is this used? find and fix
Q_ASSERT(false);
Q_ASSERT( false );
// User manually removed a resolver not through attica dialog, simple remove
QRegExp r( ".*([^/]*)/contents/code/main.js" );
@@ -732,7 +767,7 @@ AtticaManager::uninstallResolver( const QString& pathToResolver )
tDebug() << "Got resolver ID to remove:" << atticaId;
if ( !atticaId.isEmpty() ) // this is an attica-installed resolver, mark as uninstalled
{
foreach ( const Content& resolver, m_resolvers )
foreach ( const Content & resolver, m_resolvers )
{
if ( resolver.id() == atticaId ) // this is the one
{
@@ -773,21 +808,29 @@ AtticaManager::doResolverRemove( const QString& id ) const
// uninstalling is easy... just delete it! :)
QDir resolverDir = TomahawkUtils::appDataDir();
if ( !resolverDir.cd( QString( "atticaresolvers/%1" ).arg( id ) ) )
{
return;
}
if ( id.isEmpty() )
{
return;
}
// sanity check
if ( !resolverDir.absolutePath().contains( "atticaresolvers" ) ||
!resolverDir.absolutePath().contains( id ) )
!resolverDir.absolutePath().contains( id ) )
{
return;
}
TomahawkUtils::removeDirectory( resolverDir.absolutePath() );
QDir cacheDir = TomahawkUtils::appDataDir();
if ( !cacheDir.cd( "atticacache" ) )
{
return;
}
const bool removed = cacheDir.remove( id + ".png" );
tDebug() << "Tried to remove cached image, succeeded?" << removed << cacheDir.filePath( id );

View File

@@ -31,8 +31,10 @@
#include <attica/providermanager.h>
#include <attica/content.h>
namespace Tomahawk {
namespace Accounts {
namespace Tomahawk
{
namespace Accounts
{
class AtticaResolverAccount;
}
}
@@ -42,8 +44,9 @@ class BinaryInstallerHelper;
class DLLEXPORT AtticaManager : public QObject
{
Q_OBJECT
public:
enum ResolverState {
public:
enum ResolverState
{
Uninstalled = 0,
Installing,
Installed,
@@ -52,7 +55,8 @@ public:
Failed
};
struct Resolver {
struct Resolver
{
QString version, scriptPath;
int userRating; // 0-100
ResolverState state;
@@ -74,7 +78,9 @@ public:
static AtticaManager* instance()
{
if ( !s_instance )
{
s_instance = new AtticaManager();
}
return s_instance;
}
@@ -107,13 +113,13 @@ public:
AtticaManager::Resolver resolverData( const QString& atticaId ) const;
public slots:
public slots:
void installResolver( const Attica::Content& resolver, bool autoCreateAccount = true );
void installResolverWithHandler( const Attica::Content& resolver, Tomahawk::Accounts::AtticaResolverAccount* handler );
void upgradeResolver( const Attica::Content& resolver );
signals:
signals:
void resolversLoaded( const Attica::Content::List& resolvers );
void resolverStateChanged( const QString& resolverId );
@@ -125,7 +131,7 @@ signals:
void startedInstalling( const QString& resolverId );
private slots:
private slots:
void providerFetched( QNetworkReply* reply );
void providerError( QNetworkReply::NetworkError );
void providerAdded( const Attica::Provider& );
@@ -141,7 +147,7 @@ private slots:
void syncServerData();
private:
private:
void doResolverRemove( const QString& id ) const;
void doInstallResolver( const Attica::Content& resolver, bool autoCreate, Tomahawk::Accounts::AtticaResolverAccount* handler );
void fetchMissingIcons();
@@ -164,12 +170,12 @@ private:
class DLLEXPORT CustomAtticaAccount : public Tomahawk::Accounts::Account
{
Q_OBJECT
public:
public:
virtual ~CustomAtticaAccount() {}
virtual Attica::Content atticaContent() const = 0;
protected:
protected:
// No, you can't.
CustomAtticaAccount( const QString& id ) : Tomahawk::Accounts::Account( id ) {}
};

View File

@@ -70,7 +70,7 @@ ContextMenu::clear()
unsigned int
ContextMenu::itemCount() const
{
return m_queries.count() + m_artists.count() + m_albums.count();
return m_queries.count() + m_artists.count() + m_albums.count();
}
@@ -85,7 +85,7 @@ ContextMenu::addToPlaylist( int playlistIdx )
void
ContextMenu::sendToSource( int sourceIdx )
{
const Tomahawk::source_ptr &src = m_sources.at( sourceIdx );
const Tomahawk::source_ptr& src = m_sources.at( sourceIdx );
foreach ( Tomahawk::query_ptr query, m_queries )
{
query->queryTrack()->share( src );
@@ -111,17 +111,23 @@ void
ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
{
if ( queries.isEmpty() )
{
return;
}
QMenu::clear();
m_queries.clear();
m_queries << queries;
if ( m_supportedActions & ActionPlay && itemCount() == 1 )
{
m_sigmap->setMapping( addAction( tr( "&Play" ) ), ActionPlay );
}
if ( m_supportedActions & ActionQueue )
{
m_sigmap->setMapping( addAction( tr( "Add to &Queue" ) ), ActionQueue );
}
if ( m_supportedActions & ActionPlaylist )
{
@@ -130,7 +136,9 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
// Sort the playlist
qSort( m_playlists.begin(), m_playlists.end(), playlistsLessThan );
if ( m_playlists_sigmap != 0 )
{
m_playlists_sigmap->deleteLater();
}
m_playlists_sigmap = new QSignalMapper( this );
// Build the menu listing all available playlists
@@ -138,7 +146,7 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
for ( int i = 0; i < m_playlists.length(); ++i )
{
QAction* action = new QAction( m_playlists.at( i )->title() , this );
playlistMenu->addAction(action);
playlistMenu->addAction( action );
m_playlists_sigmap->setMapping( action, i );
connect( action, SIGNAL( triggered() ), m_playlists_sigmap, SLOT( map() ) );
}
@@ -152,7 +160,9 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
qSort( m_sources.begin(), m_sources.end(), sourcesLessThan );
if ( m_sources_sigmap != 0 )
{
m_sources_sigmap->deleteLater();
}
m_sources_sigmap = new QSignalMapper( this );
QMenu* sourcesMenu = addMenu( tr( "Send to &Friend" ) );
@@ -169,9 +179,13 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
if ( m_supportedActions & ActionStopAfter && itemCount() == 1 )
{
if ( AudioEngine::instance()->stopAfterTrack() == queries.first() )
{
m_sigmap->setMapping( addAction( tr( "Continue Playback after this &Track" ) ), ActionStopAfter );
}
else
{
m_sigmap->setMapping( addAction( tr( "Stop Playback after this &Track" ) ), ActionStopAfter );
}
}
addSeparator();
@@ -207,17 +221,21 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
addSeparator();
if ( m_supportedActions & ActionCopyLink && itemCount() == 1 )
{
m_sigmap->setMapping( addAction( tr( "&Copy Track Link" ) ), ActionCopyLink );
}
if ( m_supportedActions & ActionEditMetadata && itemCount() == 1 )
{
m_sigmap->setMapping( addAction( tr( "Properties..." ) ), ActionEditMetadata );
}
addSeparator();
if ( m_supportedActions & ActionMarkListened )
{
bool thereAreUnlistenedTracks = false;
foreach ( const Tomahawk::query_ptr& query, m_queries )
foreach ( const Tomahawk::query_ptr & query, m_queries )
{
if ( !query->queryTrack()->isListened() )
{
@@ -227,13 +245,17 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
}
if ( thereAreUnlistenedTracks )
{
m_sigmap->setMapping( addAction( tr( "Mark as &Listened" ) ), ActionMarkListened );
}
}
if ( m_supportedActions & ActionDelete )
{
m_sigmap->setMapping( addAction( queries.count() > 1 ? tr( "&Remove Items" ) : tr( "&Remove Item" ) ), ActionDelete );
}
foreach ( QAction* action, actions() )
foreach ( QAction * action, actions() )
{
connect( action, SIGNAL( triggered() ), m_sigmap, SLOT( map() ) );
}
@@ -244,7 +266,9 @@ void
ContextMenu::setQuery( const Tomahawk::query_ptr& query )
{
if ( query.isNull() )
{
return;
}
QList<query_ptr> queries;
queries << query;
@@ -256,14 +280,18 @@ void
ContextMenu::setAlbums( const QList<Tomahawk::album_ptr>& albums )
{
if ( albums.isEmpty() )
{
return;
}
QMenu::clear();
m_albums.clear();
m_albums << albums;
if ( m_supportedActions & ActionQueue )
{
m_sigmap->setMapping( addAction( tr( "Add to &Queue" ) ), ActionQueue );
}
addSeparator();
@@ -282,9 +310,11 @@ ContextMenu::setAlbums( const QList<Tomahawk::album_ptr>& albums )
addSeparator();
if ( m_supportedActions & ActionCopyLink && itemCount() == 1 )
{
m_sigmap->setMapping( addAction( tr( "Copy Album &Link" ) ), ActionCopyLink );
}
foreach ( QAction* action, actions() )
foreach ( QAction * action, actions() )
{
connect( action, SIGNAL( triggered() ), m_sigmap, SLOT( map() ) );
}
@@ -304,17 +334,21 @@ void
ContextMenu::setArtists( const QList<Tomahawk::artist_ptr>& artists )
{
if ( artists.isEmpty() )
{
return;
}
QMenu::clear();
m_artists.clear();
m_artists << artists;
/* if ( m_supportedActions & ActionPlay && itemCount() == 1 )
m_sigmap->setMapping( addAction( tr( "Show &Artist Page" ) ), ActionPlay );*/
/* if ( m_supportedActions & ActionPlay && itemCount() == 1 )
m_sigmap->setMapping( addAction( tr( "Show &Artist Page" ) ), ActionPlay );*/
if ( m_supportedActions & ActionQueue )
{
m_sigmap->setMapping( addAction( tr( "Add to &Queue" ) ), ActionQueue );
}
addSeparator();
@@ -330,9 +364,11 @@ ContextMenu::setArtists( const QList<Tomahawk::artist_ptr>& artists )
addSeparator();
if ( m_supportedActions & ActionCopyLink && itemCount() == 1 )
{
m_sigmap->setMapping( addAction( tr( "Copy Artist &Link" ) ), ActionCopyLink );
}
foreach ( QAction* action, actions() )
foreach ( QAction * action, actions() )
{
connect( action, SIGNAL( triggered() ), m_sigmap, SLOT( map() ) );
}
@@ -364,7 +400,7 @@ ContextMenu::onTriggered( int action )
case ActionTrackPage:
case ActionArtistPage:
case ActionAlbumPage:
openPage( (MenuActions)action );
openPage( ( MenuActions )action );
break;
case ActionLove:
@@ -373,17 +409,21 @@ ContextMenu::onTriggered( int action )
case ActionStopAfter:
if ( m_queries.first()->equals( AudioEngine::instance()->stopAfterTrack() ) )
{
AudioEngine::instance()->setStopAfterTrack( query_ptr() );
}
else
{
AudioEngine::instance()->setStopAfterTrack( m_queries.first() );
}
break;
case ActionEditMetadata:
{
MetadataEditor* d = new MetadataEditor( m_queries.first(), m_interface, this );
d->show();
}
break;
{
MetadataEditor* d = new MetadataEditor( m_queries.first(), m_interface, this );
d->show();
}
break;
default:
emit triggered( action );
@@ -397,15 +437,15 @@ ContextMenu::onTriggered( int action )
void
ContextMenu::addToQueue()
{
foreach ( const query_ptr& query, m_queries )
foreach ( const query_ptr & query, m_queries )
{
ViewManager::instance()->queue()->model()->appendQuery( query );
}
foreach ( const artist_ptr& artist, m_artists )
foreach ( const artist_ptr & artist, m_artists )
{
ViewManager::instance()->queue()->model()->appendArtist( artist );
}
foreach ( const album_ptr& album, m_albums )
foreach ( const album_ptr & album, m_albums )
{
ViewManager::instance()->queue()->model()->appendAlbum( album );
}
@@ -475,7 +515,9 @@ void
ContextMenu::onSocialActionsLoaded()
{
if ( m_queries.isEmpty() || m_queries.first().isNull() )
{
return;
}
if ( m_loveAction && m_queries.first()->track()->loved() )
{

Some files were not shown because too many files have changed in this diff Show More