From 7914fc955130f1620732dea2620503ea3dff9bd9 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Sun, 8 Apr 2012 14:36:06 -0400 Subject: [PATCH 01/14] Initial work on notification cleanup --- src/libtomahawk/audio/audioengine.cpp | 96 ++++++------------- src/libtomahawk/audio/audioengine.h | 10 +- .../infoplugins/unix/fdonotifyplugin.cpp | 83 +++++++++++++--- .../infoplugins/unix/fdonotifyplugin.h | 5 + .../infoplugins/unix/mprisplugin.cpp | 12 ++- src/libtomahawk/infosystem/infosystem.h | 1 + src/libtomahawk/tomahawksettings.h | 1 + src/tomahawkapp.cpp | 2 + 8 files changed, 123 insertions(+), 87 deletions(-) diff --git a/src/libtomahawk/audio/audioengine.cpp b/src/libtomahawk/audio/audioengine.cpp index cfa7ceb66..69ab13adc 100644 --- a/src/libtomahawk/audio/audioengine.cpp +++ b/src/libtomahawk/audio/audioengine.cpp @@ -31,6 +31,7 @@ #include "database/databasecommand_logplayback.h" #include "network/servent.h" #include "utils/qnr_iodevicestream.h" +#include "utils/closure.h" #include "headlesscheck.h" #include "infosystem/infosystem.h" #include "album.h" @@ -77,8 +78,6 @@ AudioEngine::AudioEngine() connect( m_audioOutput, SIGNAL( volumeChanged( qreal ) ), SLOT( onVolumeChanged( qreal ) ) ); - connect( this, SIGNAL( sendWaitingNotification() ), SLOT( sendWaitingNotificationSlot() ), Qt::QueuedConnection ); - onVolumeChanged( m_audioOutput->volume() ); #ifndef Q_WS_X11 @@ -137,23 +136,7 @@ AudioEngine::play() setVolume( m_volume ); emit resumed(); - if ( TomahawkSettings::instance()->privateListeningMode() != TomahawkSettings::FullyPrivate ) - { - Tomahawk::InfoSystem::InfoStringHash trackInfo; - - trackInfo["title"] = m_currentTrack->track(); - trackInfo["artist"] = m_currentTrack->artist()->name(); - trackInfo["album"] = m_currentTrack->album()->name(); - trackInfo["albumpos"] = QString::number( m_currentTrack->albumpos() ); - trackInfo["duration"] = QString::number( m_currentTrack->duration() ); - - Tomahawk::InfoSystem::InfoPushData pushData ( - s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNowResumed, - QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( trackInfo ), - Tomahawk::InfoSystem::PushNoFlag ); - - Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( pushData ); - } + sendNowPlayingNotification( Tomahawk::InfoSystem::InfoNowResumed ); } else next(); @@ -192,19 +175,12 @@ AudioEngine::stop() setCurrentTrack( Tomahawk::result_ptr() ); - Tomahawk::InfoSystem::InfoTypeMap map; - map[ Tomahawk::InfoSystem::InfoNowStopped ] = QVariant(); - if ( m_waitingOnNewTrack ) - emit sendWaitingNotification(); - else if ( TomahawkSettings::instance()->verboseNotifications() ) - { - QVariantMap stopInfo; - stopInfo["message"] = tr( "Tomahawk is stopped." ); - map[ Tomahawk::InfoSystem::InfoNotifyUser ] = QVariant::fromValue< QVariantMap >( stopInfo ); - } + sendWaitingNotification(); - Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( s_aeInfoIdentifier, map, Tomahawk::InfoSystem::PushNoFlag ); + Tomahawk::InfoSystem::InfoPushData pushData( s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNowStopped, QVariant(), Tomahawk::InfoSystem::PushNoFlag ); + + Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( pushData ); } @@ -326,18 +302,16 @@ AudioEngine::mute() void -AudioEngine::sendWaitingNotificationSlot() const +AudioEngine::sendWaitingNotification() const { tDebug( LOGVERBOSE ) << Q_FUNC_INFO; //since it's async, after this is triggered our result could come in, so don't show the popup in that case if ( !m_playlist.isNull() && m_playlist->hasNextItem() ) return; - QVariantMap retryInfo; - retryInfo["message"] = QString( "The current track could not be resolved. Tomahawk will pick back up with the next resolvable track from this source." ); Tomahawk::InfoSystem::InfoPushData pushData ( - s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNotifyUser, - QVariant::fromValue< QVariantMap >( retryInfo ), + s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoTrackUnresolved, + QVariant(), Tomahawk::InfoSystem::PushNoFlag ); Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( pushData ); @@ -345,14 +319,15 @@ AudioEngine::sendWaitingNotificationSlot() const void -AudioEngine::sendNowPlayingNotification() +AudioEngine::sendNowPlayingNotification( const Tomahawk::InfoSystem::InfoType type ) { #ifndef ENABLE_HEADLESS if ( m_currentTrack->album().isNull() || m_currentTrack->album()->infoLoaded() ) - onNowPlayingInfoReady(); + onNowPlayingInfoReady( type ); else { - connect( m_currentTrack->album().data(), SIGNAL( updated() ), SLOT( onNowPlayingInfoReady() ), Qt::UniqueConnection ); + _detail::Closure* closure = NewClosure( m_currentTrack->album().data(), SIGNAL( updated() ), const_cast(this), SLOT( onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType ) ), type ); + closure->setAutoDelete( false ); m_currentTrack->album()->cover( QSize( 0, 0 ) ); } #endif @@ -360,7 +335,7 @@ AudioEngine::sendNowPlayingNotification() void -AudioEngine::onNowPlayingInfoReady() +AudioEngine::onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType type ) { tDebug( LOGVERBOSE ) << Q_FUNC_INFO; if ( m_currentTrack.isNull() || @@ -370,26 +345,29 @@ AudioEngine::onNowPlayingInfoReady() if ( !m_currentTrack->album().isNull() && sender() && m_currentTrack->album().data() != sender() ) return; - + QVariantMap playInfo; - playInfo["message"] = tr( "Tomahawk is playing \"%1\" by %2%3." ) - .arg( m_currentTrack->track() ) - .arg( m_currentTrack->artist()->name() ) - .arg( m_currentTrack->album().isNull() ? QString() : QString( " %1" ).arg( tr( "on album %1" ).arg( m_currentTrack->album()->name() ) ) ); if ( !m_currentTrack->album().isNull() ) { #ifndef ENABLE_HEADLESS QImage cover; cover = m_currentTrack->album()->cover( QSize( 0, 0 ) ).toImage(); - playInfo["image"] = QVariant( cover ); + playInfo["cover"] = QVariant( cover ); #endif } - Tomahawk::InfoSystem::InfoPushData pushData ( - s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNotifyUser, - QVariant::fromValue< QVariantMap >( playInfo ), - Tomahawk::InfoSystem::PushNoFlag ); + Tomahawk::InfoSystem::InfoStringHash trackInfo; + trackInfo["title"] = m_currentTrack->track(); + trackInfo["artist"] = m_currentTrack->artist()->name(); + trackInfo["album"] = m_currentTrack->album()->name(); + trackInfo["duration"] = QString::number( m_currentTrack->duration() ); + trackInfo["albumpos"] = QString::number( m_currentTrack->albumpos() ); + + playInfo["trackinfo"] = QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( trackInfo ); + playInfo["private"] = TomahawkSettings::instance()->privateListeningMode(); + + Tomahawk::InfoSystem::InfoPushData pushData ( s_aeInfoIdentifier, type, playInfo, Tomahawk::InfoSystem::PushShortUrlFlag ); Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( pushData ); } @@ -468,29 +446,13 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result ) m_mediaObject->play(); emit started( m_currentTrack ); - if ( TomahawkSettings::instance()->verboseNotifications() ) - sendNowPlayingNotification(); - if ( TomahawkSettings::instance()->privateListeningMode() != TomahawkSettings::FullyPrivate ) { DatabaseCommand_LogPlayback* cmd = new DatabaseCommand_LogPlayback( m_currentTrack, DatabaseCommand_LogPlayback::Started ); Database::instance()->enqueue( QSharedPointer(cmd) ); - - Tomahawk::InfoSystem::InfoStringHash trackInfo; - trackInfo["title"] = m_currentTrack->track(); - trackInfo["artist"] = m_currentTrack->artist()->name(); - trackInfo["album"] = m_currentTrack->album()->name(); - trackInfo["duration"] = QString::number( m_currentTrack->duration() ); - trackInfo["albumpos"] = QString::number( m_currentTrack->albumpos() ); - - Tomahawk::InfoSystem::InfoPushData pushData ( - s_aeInfoIdentifier, - Tomahawk::InfoSystem::InfoNowPlaying, - QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( trackInfo ), - Tomahawk::InfoSystem::PushShortUrlFlag ); - - Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( pushData ); } + + sendNowPlayingNotification( Tomahawk::InfoSystem::InfoNowPlaying ); } } diff --git a/src/libtomahawk/audio/audioengine.h b/src/libtomahawk/audio/audioengine.h index 345572401..227f5d7bf 100644 --- a/src/libtomahawk/audio/audioengine.h +++ b/src/libtomahawk/audio/audioengine.h @@ -27,6 +27,8 @@ #include #include +#include "libtomahawk/infosystem/infosystem.h" + #include "result.h" #include "typedefs.h" #include "playlistinterface.h" @@ -117,8 +119,6 @@ signals: void error( AudioEngine::AudioErrorCode errorCode ); - void sendWaitingNotification(); - private slots: bool loadTrack( const Tomahawk::result_ptr& result ); void loadPreviousTrack(); @@ -130,10 +130,10 @@ private slots: void timerTriggered( qint64 time ); void setCurrentTrack( const Tomahawk::result_ptr& result ); - void onNowPlayingInfoReady(); + void onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType type ); void onPlaylistNextTrackReady(); - void sendWaitingNotificationSlot() const; + void sendWaitingNotification() const; private: void setState( AudioState state ); @@ -141,7 +141,7 @@ private: bool isHttpResult( const QString& ) const; bool isLocalResult( const QString& ) const; - void sendNowPlayingNotification(); + void sendNowPlayingNotification( const Tomahawk::InfoSystem::InfoType type ); QSharedPointer m_input; diff --git a/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp b/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp index b62ffc6e7..43b4e4582 100644 --- a/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp +++ b/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp @@ -54,43 +54,100 @@ FdoNotifyPlugin::FdoNotifyPlugin() : InfoPlugin() { qDebug() << Q_FUNC_INFO; - m_supportedPushTypes << Tomahawk::InfoSystem::InfoNotifyUser; + m_supportedPushTypes << InfoNotifyUser << InfoNowPlaying << InfoTrackUnresolved << InfoNowStopped; } + FdoNotifyPlugin::~FdoNotifyPlugin() { qDebug() << Q_FUNC_INFO; } + void FdoNotifyPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData ) { qDebug() << Q_FUNC_INFO; QVariant inputData = pushData.infoPair.second; - if ( pushData.type != Tomahawk::InfoSystem::InfoNotifyUser || !inputData.canConvert< QVariantMap >() ) + + switch ( pushData.type ) { - qDebug() << Q_FUNC_INFO << " not the right type or could not convert the hash"; - return; - } - QVariantMap hash = inputData.value< QVariantMap >(); - if ( !hash.contains( "message" ) ) - { - qDebug() << Q_FUNC_INFO << " hash did not contain a message"; - return; + case Tomahawk::InfoSystem::InfoTrackUnresolved: + notifyUser( "The current track could not be resolved. Tomahawk will pick back up with the next resolvable track from this source." ); + return; + + case Tomahawk::InfoSystem::InfoNotifyUser: + notifyUser( pushData.infoPair.second.toString() ); + return; + + case Tomahawk::InfoSystem::InfoNowStopped: + notifyUser( "Tomahawk is stopped." ); + return; + + case Tomahawk::InfoSystem::InfoNowPlaying: + nowPlaying( pushData.infoPair.second ); + return; + + default: + return; } +} + + +void +FdoNotifyPlugin::notifyUser( const QString &messageText ) +{ QDBusMessage message = QDBusMessage::createMethodCall( "org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.Notifications", "Notify" ); QList arguments; arguments << QString( "Tomahawk" ); //app_name arguments << quint32( 0 ); //notification_id arguments << QString(); //app_icon arguments << QString( "Tomahawk" ); //summary - arguments << hash[ "message" ].toString(); //body + arguments << messageText; //body arguments << QStringList(); //actions QVariantMap dict; dict["desktop-entry"] = QString( "tomahawk" ); - if ( hash.contains( "image" ) && hash[ "image" ].canConvert< QImage >() ) - dict[ "image_data" ] = ImageConverter::variantForImage( hash[ "image" ].value< QImage >() ); + dict[ "image_data" ] = ImageConverter::variantForImage( QImage( RESPATH "icons/tomahawk-icon-128x128.png" ) ); + arguments << dict; //hints + arguments << qint32( -1 ); //expire_timeout + message.setArguments( arguments ); + QDBusConnection::sessionBus().send( message ); +} + + +void +FdoNotifyPlugin::nowPlaying( 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; + + QString messageText = tr( "Tomahawk is playing \"%1\" by %2%3." ) + .arg( hash[ "title" ] ) + .arg( hash[ "artist" ] ) + .arg( hash[ "album" ].isEmpty() ? QString() : QString( " %1" ).arg( tr( "on album %1" ).arg( hash[ "album" ] ) ) ); + + QDBusMessage message = QDBusMessage::createMethodCall( "org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.Notifications", "Notify" ); + QList arguments; + arguments << QString( "Tomahawk" ); //app_name + arguments << quint32( 0 ); //notification_id + arguments << QString(); //app_icon + arguments << QString( "Tomahawk" ); //summary + arguments << messageText; //body + arguments << QStringList(); //actions + QVariantMap dict; + dict["desktop-entry"] = QString( "tomahawk" ); + if ( map.contains( "cover" ) && map[ "cover" ].canConvert< QImage >() ) + dict[ "image_data" ] = ImageConverter::variantForImage( map[ "cover" ].value< QImage >() ); else dict[ "image_data" ] = ImageConverter::variantForImage( QImage( RESPATH "icons/tomahawk-icon-128x128.png" ) ); arguments << dict; //hints diff --git a/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.h b/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.h index de24f8dda..c12621ff3 100644 --- a/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.h +++ b/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.h @@ -49,6 +49,11 @@ protected slots: Q_UNUSED( criteria ); Q_UNUSED( requestData ); } + +private: + void notifyUser( const QString &messageText ); + + void nowPlaying( const QVariant &input ); }; } diff --git a/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp b/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp index 9db9f72f7..bc94222d9 100644 --- a/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp +++ b/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp @@ -513,10 +513,18 @@ MprisPlugin::stateChanged( AudioState newState, AudioState oldState ) void MprisPlugin::audioStarted( const QVariant& input ) { - if ( !input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() ) + if ( !input.canConvert< QVariantMap >() ) return; - InfoStringHash hash = input.value< Tomahawk::InfoSystem::InfoStringHash >(); + QVariantMap map = input.toMap(); + + if ( map.contains( "private" ) && map[ "private" ].value< TomahawkSettings::PrivateListeningMode >() == 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" ) || !hash.contains( "album" ) ) return; diff --git a/src/libtomahawk/infosystem/infosystem.h b/src/libtomahawk/infosystem/infosystem.h index dacbae5a7..9f0d8a811 100644 --- a/src/libtomahawk/infosystem/infosystem.h +++ b/src/libtomahawk/infosystem/infosystem.h @@ -122,6 +122,7 @@ enum InfoType { // as items are saved in cache, mark them here to not change the InfoNowPaused = 81, InfoNowResumed = 82, InfoNowStopped = 83, + InfoTrackUnresolved = 84, InfoLove = 90, InfoUnLove = 91, diff --git a/src/libtomahawk/tomahawksettings.h b/src/libtomahawk/tomahawksettings.h index 5200bc524..6fc844be3 100644 --- a/src/libtomahawk/tomahawksettings.h +++ b/src/libtomahawk/tomahawksettings.h @@ -212,5 +212,6 @@ private: static TomahawkSettings* s_instance; }; +Q_DECLARE_METATYPE( TomahawkSettings::PrivateListeningMode ); #endif diff --git a/src/tomahawkapp.cpp b/src/tomahawkapp.cpp index 81aa452bf..dbd1ab4b7 100644 --- a/src/tomahawkapp.cpp +++ b/src/tomahawkapp.cpp @@ -450,6 +450,8 @@ TomahawkApp::registerMetaTypes() qRegisterMetaType< Tomahawk::InfoSystem::InfoPlugin* >( "Tomahawk::InfoSystem::InfoPlugin*" ); qRegisterMetaType< QList< Tomahawk::InfoSystem::InfoStringHash > >("QList< Tomahawk::InfoSystem::InfoStringHash > "); + qRegisterMetaType< TomahawkSettings::PrivateListeningMode >( "TomahawkSettings::PrivateListeningMode" ); + qRegisterMetaTypeStreamOperators< QList< Tomahawk::InfoSystem::InfoStringHash > >("QList< Tomahawk::InfoSystem::InfoStringHash > "); qRegisterMetaType< QPersistentModelIndex >( "QPersistentModelIndex" ); From 3f39b0a95fa064b827b36eb76e42881ccb3bfd81 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Sun, 8 Apr 2012 19:52:17 -0400 Subject: [PATCH 02/14] Some cleanup --- src/libtomahawk/audio/audioengine.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libtomahawk/audio/audioengine.cpp b/src/libtomahawk/audio/audioengine.cpp index 69ab13adc..4c9e09454 100644 --- a/src/libtomahawk/audio/audioengine.cpp +++ b/src/libtomahawk/audio/audioengine.cpp @@ -326,8 +326,7 @@ AudioEngine::sendNowPlayingNotification( const Tomahawk::InfoSystem::InfoType ty onNowPlayingInfoReady( type ); else { - _detail::Closure* closure = NewClosure( m_currentTrack->album().data(), SIGNAL( updated() ), const_cast(this), SLOT( onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType ) ), type ); - closure->setAutoDelete( false ); + _detail::Closure* closure = NewClosure( m_currentTrack->album().data(), SIGNAL( updated() ), const_cast< AudioEngine* >( this ), SLOT( onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType ) ), type ); m_currentTrack->album()->cover( QSize( 0, 0 ) ); } #endif @@ -353,7 +352,7 @@ AudioEngine::onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType type ) #ifndef ENABLE_HEADLESS QImage cover; cover = m_currentTrack->album()->cover( QSize( 0, 0 ) ).toImage(); - playInfo["cover"] = QVariant( cover ); + playInfo["cover"] = cover; #endif } From ca375bcc7614a9725a4bb230a7a3e19edaaf7240 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Sun, 8 Apr 2012 20:07:07 -0400 Subject: [PATCH 03/14] Remove privacy for mpris; we want to keep local info updated, it's up to the user to configure how programs proxy mpris information --- src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp b/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp index bc94222d9..58511f8cd 100644 --- a/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp +++ b/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp @@ -517,9 +517,6 @@ MprisPlugin::audioStarted( const QVariant& input ) return; QVariantMap map = input.toMap(); - - if ( map.contains( "private" ) && map[ "private" ].value< TomahawkSettings::PrivateListeningMode >() == TomahawkSettings::FullyPrivate ) - return; if ( !map.contains( "trackinfo" ) || !map[ "trackinfo" ].canConvert< Tomahawk::InfoSystem::InfoStringHash >() ) return; From 651bde6b4aba94703af38315a7e4f9735664a9fd Mon Sep 17 00:00:00 2001 From: Dominik Schmidt Date: Mon, 9 Apr 2012 12:45:39 +0200 Subject: [PATCH 04/14] Don't make the context menus transparent as well. Thanks to nowrep for the hint --- src/libtomahawk/context/ContextWidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libtomahawk/context/ContextWidget.cpp b/src/libtomahawk/context/ContextWidget.cpp index ec11afaaf..e09d02b67 100644 --- a/src/libtomahawk/context/ContextWidget.cpp +++ b/src/libtomahawk/context/ContextWidget.cpp @@ -76,7 +76,7 @@ ContextWidget::ContextWidget( QWidget* parent ) ui->contextView->setScene( m_scene ); ui->contextView->setFrameShape( QFrame::NoFrame ); - ui->contextView->setStyleSheet( "background: transparent" ); + ui->contextView->setStyleSheet( "QGraphicsView { background: transparent; }" ); ui->contextView->setAttribute( Qt::WA_MacShowFocusRect, 0 ); ui->contextView->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); From b6cd43d25f77a2eaf5ac78acb6f0ab8f6618cebe Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Mon, 9 Apr 2012 12:03:12 -0400 Subject: [PATCH 05/14] Vastly simplify mpris plugin by getting rid of unnecessary info system call --- src/libtomahawk/audio/audioengine.cpp | 20 +++ .../infoplugins/unix/mprisplugin.cpp | 123 ++---------------- .../infosystem/infoplugins/unix/mprisplugin.h | 10 +- 3 files changed, 33 insertions(+), 120 deletions(-) diff --git a/src/libtomahawk/audio/audioengine.cpp b/src/libtomahawk/audio/audioengine.cpp index 4c9e09454..36681e8ab 100644 --- a/src/libtomahawk/audio/audioengine.cpp +++ b/src/libtomahawk/audio/audioengine.cpp @@ -23,6 +23,7 @@ #include #include +#include #include "playlistinterface.h" #include "sourceplaylistinterface.h" @@ -353,6 +354,25 @@ AudioEngine::onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType type ) QImage cover; cover = m_currentTrack->album()->cover( QSize( 0, 0 ) ).toImage(); playInfo["cover"] = cover; + + QTemporaryFile coverTempFile( QDir::toNativeSeparators( QDir::tempPath() + "/" + m_currentTrack->artist()->name() + "_" + m_currentTrack->album()->name() + "_tomahawk_cover.png" ) ); + if ( !coverTempFile.open() ) + { + tDebug() << "WARNING: could not write temporary file for cover art!"; + } + + // Finally, save the image to the new temp file + if ( cover.save( &coverTempFile, "PNG" ) ) + { + tDebug( LOGVERBOSE ) << "Saving cover image to:" << QFileInfo( coverTempFile ).absoluteFilePath(); + coverTempFile.close(); + playInfo["coveruri"] = QFileInfo( coverTempFile ).absoluteFilePath(); + } + else + { + tDebug() << Q_FUNC_INFO << "failed to save cover image!"; + coverTempFile.close(); + } #endif } diff --git a/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp b/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp index 58511f8cd..09c643697 100644 --- a/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp +++ b/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp @@ -41,7 +41,6 @@ static QString s_mpInfoIdentifier = QString( "MPRISPLUGIN" ); MprisPlugin::MprisPlugin() : InfoPlugin() - , m_coverTempFile( 0 ) { // init m_playbackStatus = "Stopped"; @@ -75,22 +74,11 @@ MprisPlugin::MprisPlugin() // Connect to AudioEngine's seeked signal connect( AudioEngine::instance(), SIGNAL( seeked( qint64 ) ), SLOT( onSeeked( qint64 ) ) ); - - // Connect to the InfoSystem (we need to get album covers via getInfo) - - connect( Tomahawk::InfoSystem::InfoSystem::instance(), - SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), - SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) ); - - connect( Tomahawk::InfoSystem::InfoSystem::instance(), - SIGNAL( finished( QString ) ), - SLOT( infoSystemFinished( QString ) ) ); } MprisPlugin::~MprisPlugin() { - delete m_coverTempFile; } @@ -273,26 +261,11 @@ MprisPlugin::metadata() const metadataMap.insert( "xesam:title", track->track() ); // Only return art if tempfile exists, and if its name contains the same "artist_album_tomahawk_cover.png" - if ( m_coverTempFile && m_coverTempFile->exists() && - m_coverTempFile->fileName().contains( track->artist()->name() + "_" + track->album()->name() + "_tomahawk_cover.png" ) ) + if ( !m_coverTempFile.isEmpty() ) { - metadataMap.insert( "mpris:artUrl", QString( QUrl::fromLocalFile( QFileInfo( *m_coverTempFile ).absoluteFilePath() ).toEncoded() ) ); - } - else - { - // Need to fetch the album cover - - Tomahawk::InfoSystem::InfoStringHash trackInfo; - trackInfo["artist"] = track->artist()->name(); - trackInfo["album"] = track->album()->name(); - - Tomahawk::InfoSystem::InfoRequestData requestData; - requestData.caller = s_mpInfoIdentifier; - requestData.type = Tomahawk::InfoSystem::InfoAlbumCoverArt; - requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( trackInfo ); - requestData.customData = QVariantMap(); - - Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData ); + QFile coverFile( m_coverTempFile ); + if ( coverFile.exists() && coverFile.fileName().contains( track->artist()->name() + "_" + track->album()->name() + "_tomahawk_cover.png" ) ) + metadataMap.insert( "mpris:artUrl", QString( QUrl::fromLocalFile( m_coverTempFile ).toEncoded() ) ); } } @@ -458,16 +431,6 @@ MprisPlugin::Stop() // InfoPlugin Methods - -void -MprisPlugin::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData ) -{ - Q_UNUSED( requestData ); - - return; -} - - void MprisPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData ) { @@ -526,6 +489,10 @@ MprisPlugin::audioStarted( const QVariant& input ) return; m_playbackStatus = "Playing"; + + if ( map.contains( "coveruri" ) ) + m_coverTempFile = map[ "coveruri" ].toString(); + notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Metadata" ); } @@ -601,80 +568,6 @@ MprisPlugin::onSeeked( qint64 ms ) } -void -MprisPlugin::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output ) -{ - // If the caller for the request was not us, or not the type of info we are seeking, ignore it - if ( requestData.caller != s_mpInfoIdentifier || requestData.type != Tomahawk::InfoSystem::InfoAlbumCoverArt ) - { - //notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Metadata" ); - return; - } - - if ( !output.canConvert< QVariantMap >() ) - { - //notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Metadata" ); - tDebug( LOGINFO ) << "Cannot convert fetched art from a QByteArray"; - return; - } - - // Pull image data into byte array - QVariantMap returnedData = output.value< QVariantMap >(); - const QByteArray ba = returnedData["imgbytes"].toByteArray(); - if ( ba.length() ) - { - // Load from byte array to image - QImage image; - image.loadFromData( ba ); - - // Pull out request data for album+artist - if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() ) - { - qDebug() << "Cannot convert metadata input to album cover retrieval"; - return; - } - - Tomahawk::InfoSystem::InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash>(); - - // delete the old tempfile and make new one, to avoid caching of filename by mpris clients - if ( m_coverTempFile ) - { - delete m_coverTempFile; - m_coverTempFile = 0; - } - - if ( image.isNull() ) - return; - - m_coverTempFile = new QTemporaryFile( QDir::toNativeSeparators( QDir::tempPath() + "/" + hash["artist"] + "_" + hash["album"] + "_tomahawk_cover.png" ) ); - if ( !m_coverTempFile->open() ) - { - qDebug() << "WARNING: could not write temporary file for cover art!"; - } - - // Finally, save the image to the new temp file - if ( image.save( m_coverTempFile, "PNG" ) ) - { - qDebug() << "Saving cover image to:" << QFileInfo( *m_coverTempFile ).absoluteFilePath(); - m_coverTempFile->close(); - notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Metadata" ); - } - else - { - tDebug() << Q_FUNC_INFO << "failed to save cover image!"; - m_coverTempFile->close(); - } - } -} - - -void -MprisPlugin::infoSystemFinished( QString target ) -{ - Q_UNUSED( target ); -} - - void MprisPlugin::notifyPropertyChanged( const QString& interface, const QString& propertyName ) { diff --git a/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.h b/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.h index 33155cfc1..92b8a9e3b 100644 --- a/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.h +++ b/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.h @@ -140,7 +140,10 @@ public slots: void Stop(); protected slots: - void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData ); + virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData ) + { + Q_UNUSED( requestData ); + } void pushInfo( Tomahawk::InfoSystem::InfoPushData pushData ); private slots: @@ -150,9 +153,6 @@ private slots: void onTrackCountChanged( unsigned int tracks ); void onSeeked( qint64 ms ); - void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output ); - void infoSystemFinished( QString target ); - signals: void Seeked( qlonglong Position ); @@ -169,7 +169,7 @@ private: // DBus void notifyPropertyChanged( const QString& interface, const QString& propertyName ); QString m_playbackStatus; - QTemporaryFile* m_coverTempFile; + QString m_coverTempFile; }; }; From bb0e24f07476c10226b889b418ef1482750fc135 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Mon, 9 Apr 2012 12:19:25 -0400 Subject: [PATCH 06/14] Fix up xmpp info plugin. This plugin respects private listening settings, since unlike mpris and fdo it isn't designed to display locally --- src/accounts/xmpp/XmppInfoPlugin.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/accounts/xmpp/XmppInfoPlugin.cpp b/src/accounts/xmpp/XmppInfoPlugin.cpp index cebd181e1..728ba4cf5 100644 --- a/src/accounts/xmpp/XmppInfoPlugin.cpp +++ b/src/accounts/xmpp/XmppInfoPlugin.cpp @@ -99,13 +99,27 @@ Tomahawk::InfoSystem::XmppInfoPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushDa void Tomahawk::InfoSystem::XmppInfoPlugin::audioStarted( const Tomahawk::InfoSystem::PushInfoPair &pushInfoPair ) { - if ( !pushInfoPair.second.canConvert< Tomahawk::InfoSystem::InfoStringHash >() ) + if ( !pushInfoPair.second.canConvert< QVariantMap >() ) + { + tDebug() << Q_FUNC_INFO << "Failed to convert data to a QVariantMap"; + return; + } + + QVariantMap map = pushInfoPair.second.toMap(); + if ( map.contains( "private" ) && map[ "private" ] == TomahawkSettings::FullyPrivate ) + { + Jreen::Tune::Ptr tune( new Jreen::Tune() ); + m_pubSubManager->publishItems( QList() << tune, Jreen::JID() ); + return; + } + + if ( !map.contains( "trackinfo" ) || !map[ "trackinfo" ].canConvert< Tomahawk::InfoSystem::InfoStringHash >() ) { tDebug() << Q_FUNC_INFO << "did not find an infostringhash"; return; } - Tomahawk::InfoSystem::InfoStringHash info = pushInfoPair.second.value< Tomahawk::InfoSystem::InfoStringHash >(); + Tomahawk::InfoSystem::InfoStringHash info = map[ "trackinfo" ].value< Tomahawk::InfoSystem::InfoStringHash >(); tDebug() << Q_FUNC_INFO << m_sipPlugin->m_client->jid().full() << info; Jreen::Tune::Ptr tune( new Jreen::Tune() ); From 80a1009aa2e517bbc211d37dfa3905d2ac1945b6 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Mon, 9 Apr 2012 12:52:43 -0400 Subject: [PATCH 07/14] Update text in notification --- src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp b/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp index 43b4e4582..4cc973270 100644 --- a/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp +++ b/src/libtomahawk/infosystem/infoplugins/unix/fdonotifyplugin.cpp @@ -134,7 +134,7 @@ FdoNotifyPlugin::nowPlaying( const QVariant &input ) QString messageText = tr( "Tomahawk is playing \"%1\" by %2%3." ) .arg( hash[ "title" ] ) .arg( hash[ "artist" ] ) - .arg( hash[ "album" ].isEmpty() ? QString() : QString( " %1" ).arg( tr( "on album %1" ).arg( hash[ "album" ] ) ) ); + .arg( hash[ "album" ].isEmpty() ? QString() : QString( " %1" ).arg( tr( "on \"%1\"" ).arg( hash[ "album" ] ) ) ); QDBusMessage message = QDBusMessage::createMethodCall( "org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.Notifications", "Notify" ); QList arguments; From bfdc7a3d6757d25aa9126d14e495005ee57e6d73 Mon Sep 17 00:00:00 2001 From: Jeff Mitchell Date: Mon, 9 Apr 2012 13:11:35 -0400 Subject: [PATCH 08/14] Fix Adium plugin with updated notfications --- .../infosystem/infoplugins/mac/adiumplugin.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libtomahawk/infosystem/infoplugins/mac/adiumplugin.cpp b/src/libtomahawk/infosystem/infoplugins/mac/adiumplugin.cpp index ca3180619..aa8e57270 100644 --- a/src/libtomahawk/infosystem/infoplugins/mac/adiumplugin.cpp +++ b/src/libtomahawk/infosystem/infoplugins/mac/adiumplugin.cpp @@ -136,13 +136,16 @@ AdiumPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData ) void AdiumPlugin::audioStarted( const Tomahawk::InfoSystem::PushInfoPair pushInfoPair ) { - if ( !pushInfoPair.second.canConvert< Tomahawk::InfoSystem::InfoStringHash >() ) + if ( !pushInfoPair.second.canConvert< QVariantMap >() ) return; - Tomahawk::InfoSystem::InfoStringHash hash = pushInfoPair.second.value< Tomahawk::InfoSystem::InfoStringHash >(); + QVariantMap map = pushInfoPair.second.toMap(); - qDebug() << Q_FUNC_INFO; + 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; From feedb1450ce3f15757dd9f7f471933245bff3d5f Mon Sep 17 00:00:00 2001 From: Jason Herskowitz Date: Mon, 9 Apr 2012 14:46:36 -0400 Subject: [PATCH 09/14] Make capitalization of Stop Playback after this Track consistent with other context menu items --- src/libtomahawk/contextmenu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libtomahawk/contextmenu.cpp b/src/libtomahawk/contextmenu.cpp index fcba90360..baafe07f5 100644 --- a/src/libtomahawk/contextmenu.cpp +++ b/src/libtomahawk/contextmenu.cpp @@ -84,9 +84,9 @@ ContextMenu::setQueries( const QList& queries ) if ( m_supportedActions & ActionStopAfter && itemCount() == 1 ) { if ( AudioEngine::instance()->stopAfterTrack() == queries.first() ) - m_sigmap->setMapping( addAction( tr( "&Continue playback after this track" ) ), ActionStopAfter ); + m_sigmap->setMapping( addAction( tr( "&Continue Playback after this Track" ) ), ActionStopAfter ); else - m_sigmap->setMapping( addAction( tr( "&Stop playback after this track" ) ), ActionStopAfter ); + m_sigmap->setMapping( addAction( tr( "&Stop Playback after this Track" ) ), ActionStopAfter ); } addSeparator(); From 6a88aefadc07f84a0b8d5c07e28a60a06de8ec9a Mon Sep 17 00:00:00 2001 From: Tomahawk CI Date: Mon, 9 Apr 2012 22:16:19 +0000 Subject: [PATCH 10/14] Automatic merge of Transifex translations --- lang/tomahawk_bg.ts | 55 +++++++++++++++++++----------------------- lang/tomahawk_de.ts | 53 ++++++++++++++++++---------------------- lang/tomahawk_en.ts | 53 ++++++++++++++++++---------------------- lang/tomahawk_es.ts | 53 ++++++++++++++++++---------------------- lang/tomahawk_ja.ts | 53 ++++++++++++++++++---------------------- lang/tomahawk_pl.ts | 53 ++++++++++++++++++---------------------- lang/tomahawk_pt_BR.ts | 53 ++++++++++++++++++---------------------- lang/tomahawk_ru.ts | 53 ++++++++++++++++++---------------------- lang/tomahawk_sv.ts | 53 ++++++++++++++++++---------------------- 9 files changed, 217 insertions(+), 262 deletions(-) diff --git a/lang/tomahawk_bg.ts b/lang/tomahawk_bg.ts index 49fabc310..e9fc9303d 100644 --- a/lang/tomahawk_bg.ts +++ b/lang/tomahawk_bg.ts @@ -196,7 +196,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have After you have scanned your music collection you will find your latest album additions right here. - След като сканирате музикалната ви колекция, ще откриете най-скоро добавените албуми тук. + След като бъде сканирана музикалната ти колекция, ще откриеш тук най-скоро добавените албуми. @@ -330,24 +330,6 @@ Remember: Only allow peers to connect if you trust who they are and if you have 100% - - AudioEngine - - - Tomahawk is stopped. - Tomahawk е спрян - - - - Tomahawk is playing "%1" by %2%3. - Tomahawk изпълнява "%1" от %2%3. - - - - on album %1 - от албум %1 - - CategoryAddItem @@ -1716,16 +1698,6 @@ You may wish to try re-authenticating. Add to &Queue Добави към &опашката - - - &Continue playback after this track - &Продължи възпроизвеждането след тази песен - - - - &Stop playback after this track - &Спри възпроизвеждането след тази песен - @@ -1757,6 +1729,16 @@ You may wish to try re-authenticating. &Delete Items &Изтрий позициите + + + &Continue Playback after this Track + + + + + &Stop Playback after this Track + + &Delete Item @@ -2308,6 +2290,19 @@ Try tweaking the filters for a new set of songs to play. Песни + + Tomahawk::InfoSystem::FdoNotifyPlugin + + + Tomahawk is playing "%1" by %2%3. + + + + + on "%1" + + + Tomahawk::InfoSystem::LastFmPlugin @@ -2485,7 +2480,7 @@ Try tweaking the filters for a new set of songs to play. TomahawkApp - + My Collection Моята колекция diff --git a/lang/tomahawk_de.ts b/lang/tomahawk_de.ts index b8063ff10..c4cc5e7bd 100644 --- a/lang/tomahawk_de.ts +++ b/lang/tomahawk_de.ts @@ -330,24 +330,6 @@ Denk dran: Erlaube das nur, wenn du dem Anderen vertraust und du die Rechte zum Hoch - - AudioEngine - - - Tomahawk is stopped. - Tomahawk ist gestoppt. - - - - Tomahawk is playing "%1" by %2%3. - Tomahawk spielt "%1" von %2%3. - - - - on album %1 - auf dem Album %1 - - CategoryAddItem @@ -1706,16 +1688,6 @@ You may wish to try re-authenticating. Add to &Queue In &Warteschlange einreihen - - - &Continue playback after this track - - - - - &Stop playback after this track - &Beende Wiedergabe nach diesem Stück - @@ -1747,6 +1719,16 @@ You may wish to try re-authenticating. &Delete Items Elemente &entfernen + + + &Continue Playback after this Track + + + + + &Stop Playback after this Track + + &Delete Item @@ -2299,6 +2281,19 @@ Versuch die Filter anzupassen für neue Lieder. Stücke + + Tomahawk::InfoSystem::FdoNotifyPlugin + + + Tomahawk is playing "%1" by %2%3. + + + + + on "%1" + + + Tomahawk::InfoSystem::LastFmPlugin @@ -2476,7 +2471,7 @@ Versuch die Filter anzupassen für neue Lieder. TomahawkApp - + My Collection Meine Sammlung diff --git a/lang/tomahawk_en.ts b/lang/tomahawk_en.ts index f2eb5b6fb..f84149a1c 100644 --- a/lang/tomahawk_en.ts +++ b/lang/tomahawk_en.ts @@ -330,24 +330,6 @@ Remember: Only allow peers to connect if you trust who they are and if you have High - - AudioEngine - - - Tomahawk is stopped. - Tomahawk is stopped. - - - - Tomahawk is playing "%1" by %2%3. - Tomahawk is playing "%1" by %2%3. - - - - on album %1 - on album %1 - - CategoryAddItem @@ -1713,16 +1695,6 @@ You may wish to try re-authenticating. Add to &Queue Add to &Queue - - - &Continue playback after this track - &Continue playback after this track - - - - &Stop playback after this track - &Stop playback after this track - @@ -1754,6 +1726,16 @@ You may wish to try re-authenticating. &Delete Items &Delete Items + + + &Continue Playback after this Track + &Continue Playback after this Track + + + + &Stop Playback after this Track + &Stop Playback after this Track + &Delete Item @@ -2306,6 +2288,19 @@ Try tweaking the filters for a new set of songs to play. Tracks + + Tomahawk::InfoSystem::FdoNotifyPlugin + + + Tomahawk is playing "%1" by %2%3. + Tomahawk is playing "%1" by %2%3. + + + + on "%1" + on "%1" + + Tomahawk::InfoSystem::LastFmPlugin @@ -2483,7 +2478,7 @@ Try tweaking the filters for a new set of songs to play. TomahawkApp - + My Collection My Collection diff --git a/lang/tomahawk_es.ts b/lang/tomahawk_es.ts index d30c86425..74aa6b86b 100644 --- a/lang/tomahawk_es.ts +++ b/lang/tomahawk_es.ts @@ -328,24 +328,6 @@ Remember: Only allow peers to connect if you trust who they are and if you have Subir volumen - - AudioEngine - - - Tomahawk is stopped. - Tomahawk está parado. - - - - Tomahawk is playing "%1" by %2%3. - Tomahawk está reproduciendo "%1" de %2%3. - - - - on album %1 - - - CategoryAddItem @@ -1707,16 +1689,6 @@ You may wish to try re-authenticating. Add to &Queue Añadir a la &cola - - - &Continue playback after this track - - - - - &Stop playback after this track - - @@ -1748,6 +1720,16 @@ You may wish to try re-authenticating. &Delete Items &Eliminar de la cola + + + &Continue Playback after this Track + + + + + &Stop Playback after this Track + + &Delete Item @@ -2298,6 +2280,19 @@ Try tweaking the filters for a new set of songs to play. Pistas + + Tomahawk::InfoSystem::FdoNotifyPlugin + + + Tomahawk is playing "%1" by %2%3. + + + + + on "%1" + + + Tomahawk::InfoSystem::LastFmPlugin @@ -2475,7 +2470,7 @@ Try tweaking the filters for a new set of songs to play. TomahawkApp - + My Collection Mi colección diff --git a/lang/tomahawk_ja.ts b/lang/tomahawk_ja.ts index 1a37a2084..f3fdaa4dc 100644 --- a/lang/tomahawk_ja.ts +++ b/lang/tomahawk_ja.ts @@ -328,24 +328,6 @@ Remember: Only allow peers to connect if you trust who they are and if you have - - AudioEngine - - - Tomahawk is stopped. - Tomahawkは中止しています。 - - - - Tomahawk is playing "%1" by %2%3. - - - - - on album %1 - - - CategoryAddItem @@ -1706,16 +1688,6 @@ You may wish to try re-authenticating. Add to &Queue - - - &Continue playback after this track - - - - - &Stop playback after this track - - @@ -1747,6 +1719,16 @@ You may wish to try re-authenticating. &Delete Items 項目を削除 + + + &Continue Playback after this Track + + + + + &Stop Playback after this Track + + &Delete Item @@ -2295,6 +2277,19 @@ Try tweaking the filters for a new set of songs to play. + + Tomahawk::InfoSystem::FdoNotifyPlugin + + + Tomahawk is playing "%1" by %2%3. + + + + + on "%1" + + + Tomahawk::InfoSystem::LastFmPlugin @@ -2472,7 +2467,7 @@ Try tweaking the filters for a new set of songs to play. TomahawkApp - + My Collection diff --git a/lang/tomahawk_pl.ts b/lang/tomahawk_pl.ts index 9fceb0e0b..36ad68d04 100644 --- a/lang/tomahawk_pl.ts +++ b/lang/tomahawk_pl.ts @@ -328,24 +328,6 @@ Remember: Only allow peers to connect if you trust who they are and if you have Wysoko - - AudioEngine - - - Tomahawk is stopped. - Tomahawk jest zatrzymany. - - - - Tomahawk is playing "%1" by %2%3. - Tomahawk odtwarza "%1" wykonawcy %2%3. - - - - on album %1 - z albumu %1 - - CategoryAddItem @@ -1708,16 +1690,6 @@ You may wish to try re-authenticating. Add to &Queue Dodaj do &Kolejki - - - &Continue playback after this track - - - - - &Stop playback after this track - - @@ -1749,6 +1721,16 @@ You may wish to try re-authenticating. &Delete Items &Usuń pozycje + + + &Continue Playback after this Track + + + + + &Stop Playback after this Track + + &Delete Item @@ -2299,6 +2281,19 @@ Try tweaking the filters for a new set of songs to play. Utwory + + Tomahawk::InfoSystem::FdoNotifyPlugin + + + Tomahawk is playing "%1" by %2%3. + + + + + on "%1" + + + Tomahawk::InfoSystem::LastFmPlugin @@ -2476,7 +2471,7 @@ Try tweaking the filters for a new set of songs to play. TomahawkApp - + My Collection Moja Kolekcja diff --git a/lang/tomahawk_pt_BR.ts b/lang/tomahawk_pt_BR.ts index a5e9aaf1e..5075b0e7d 100644 --- a/lang/tomahawk_pt_BR.ts +++ b/lang/tomahawk_pt_BR.ts @@ -328,24 +328,6 @@ Remember: Only allow peers to connect if you trust who they are and if you have Aumentar - - AudioEngine - - - Tomahawk is stopped. - Tomahawk está inativo. - - - - Tomahawk is playing "%1" by %2%3. - Tomahawk está reproduzindo "%1" por %2%3. - - - - on album %1 - - - CategoryAddItem @@ -1707,16 +1689,6 @@ You may wish to try re-authenticating. Add to &Queue Adicionar à &lista - - - &Continue playback after this track - - - - - &Stop playback after this track - - @@ -1748,6 +1720,16 @@ You may wish to try re-authenticating. &Delete Items &Eliminar itens + + + &Continue Playback after this Track + + + + + &Stop Playback after this Track + + &Delete Item @@ -2298,6 +2280,19 @@ Try tweaking the filters for a new set of songs to play. Faixas + + Tomahawk::InfoSystem::FdoNotifyPlugin + + + Tomahawk is playing "%1" by %2%3. + + + + + on "%1" + + + Tomahawk::InfoSystem::LastFmPlugin @@ -2475,7 +2470,7 @@ Try tweaking the filters for a new set of songs to play. TomahawkApp - + My Collection Minha biblioteca diff --git a/lang/tomahawk_ru.ts b/lang/tomahawk_ru.ts index 04d9c9b0a..21b1eb9b0 100644 --- a/lang/tomahawk_ru.ts +++ b/lang/tomahawk_ru.ts @@ -328,24 +328,6 @@ Remember: Only allow peers to connect if you trust who they are and if you have Громче - - AudioEngine - - - Tomahawk is stopped. - Tomahawk остановлен. - - - - Tomahawk is playing "%1" by %2%3. - Tomahawk играет "%1" by %2%3. - - - - on album %1 - на альбом %1 - - CategoryAddItem @@ -1704,16 +1686,6 @@ You may wish to try re-authenticating. Add to &Queue Добавить В &Очередь - - - &Continue playback after this track - - - - - &Stop playback after this track - - @@ -1745,6 +1717,16 @@ You may wish to try re-authenticating. &Delete Items &Удалить Песни + + + &Continue Playback after this Track + + + + + &Stop Playback after this Track + + &Delete Item @@ -2295,6 +2277,19 @@ Try tweaking the filters for a new set of songs to play. Песни + + Tomahawk::InfoSystem::FdoNotifyPlugin + + + Tomahawk is playing "%1" by %2%3. + + + + + on "%1" + + + Tomahawk::InfoSystem::LastFmPlugin @@ -2472,7 +2467,7 @@ Try tweaking the filters for a new set of songs to play. TomahawkApp - + My Collection Моя коллекция diff --git a/lang/tomahawk_sv.ts b/lang/tomahawk_sv.ts index 31368009f..3b3be3ab1 100644 --- a/lang/tomahawk_sv.ts +++ b/lang/tomahawk_sv.ts @@ -330,24 +330,6 @@ Kom ihåg: Tillåt endast anslutning från klienter du litar på, och som har la Hög - - AudioEngine - - - Tomahawk is stopped. - Tomahawk är stoppad. - - - - Tomahawk is playing "%1" by %2%3. - Tomahawk spelar upp "%1" av %2%3. - - - - on album %1 - på album %1 - - CategoryAddItem @@ -1707,16 +1689,6 @@ You may wish to try re-authenticating. Add to &Queue Lägg till i &kö - - - &Continue playback after this track - - - - - &Stop playback after this track - - @@ -1748,6 +1720,16 @@ You may wish to try re-authenticating. &Delete Items &Ta bort objekt + + + &Continue Playback after this Track + + + + + &Stop Playback after this Track + + &Delete Item @@ -2296,6 +2278,19 @@ Try tweaking the filters for a new set of songs to play. Spår + + Tomahawk::InfoSystem::FdoNotifyPlugin + + + Tomahawk is playing "%1" by %2%3. + + + + + on "%1" + + + Tomahawk::InfoSystem::LastFmPlugin @@ -2473,7 +2468,7 @@ Try tweaking the filters for a new set of songs to play. TomahawkApp - + My Collection From 4b38bbff30d44ae1a526726f924e45aab6bf2007 Mon Sep 17 00:00:00 2001 From: Artem Gluvchynsky Date: Wed, 11 Apr 2012 00:19:08 +0300 Subject: [PATCH 11/14] Changed xesam:artist to a list of strings according to the Xesam spec --- src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp b/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp index 09c643697..56cb4a753 100644 --- a/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp +++ b/src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp @@ -257,7 +257,7 @@ MprisPlugin::metadata() const metadataMap.insert( "mpris:trackid", QString( "/track/" ) + track->id().replace( "-", "" ) ); metadataMap.insert( "mpris:length", track->duration() ); metadataMap.insert( "xesam:album", track->album()->name() ); - metadataMap.insert( "xesam:artist", track->artist()->name() ); + metadataMap.insert( "xesam:artist", QStringList( track->artist()->name() ) ); metadataMap.insert( "xesam:title", track->track() ); // Only return art if tempfile exists, and if its name contains the same "artist_album_tomahawk_cover.png" From 35c56395da292beaf2688b35cec354f83fc05c77 Mon Sep 17 00:00:00 2001 From: Tomahawk CI Date: Tue, 10 Apr 2012 22:16:55 +0000 Subject: [PATCH 12/14] Automatic merge of Transifex translations --- lang/tomahawk_bg.ts | 13 +++++++------ lang/tomahawk_de.ts | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/lang/tomahawk_bg.ts b/lang/tomahawk_bg.ts index e9fc9303d..e36a5aa44 100644 --- a/lang/tomahawk_bg.ts +++ b/lang/tomahawk_bg.ts @@ -243,7 +243,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have After you have scanned your music collection you will find your tracks right here. - След като приключи сканирането на музикалната ти колекция, ще откриеш твоята музика тук. + След като приключи сканирането на музикалната ти колекция, ще откриеш музиката си тук. @@ -716,7 +716,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have A playlist by %1, created %2 - Списък за изпълнение от %1, създаден %2 + A playlist by %1, created %2 @@ -1309,7 +1309,7 @@ Remember: Only allow peers to connect if you trust who they are and if you have This product uses SPOTIFY(R) CORE but is not endorsed, certified or otherwise approved in any way by Spotify. Spotify is the registered trade mark of the Spotify Group. - Този продукт ползва ядрото на SPOTIFY(R), но не е поддържан, сертифицират или одобрен по какъвто и да е начин от Spotify. + Този продукт ползва ядрото на SPOTIFY(R), но не е поддържан, сертифициран или одобрен по какъвто и да е начин от Spotify. Spotify e TM на Spotify Group. @@ -2738,7 +2738,8 @@ enter the displayed PIN number here: Some tracks in the playlist do not contain an artist and a title. They will be ignored. - Някои от песните в този списък нямат артист и заглавие. Те ще бъдат игнорирани. + Някои от песните в този списък нямат артист и заглавие. +Те ще бъдат игнорирани. @@ -3132,7 +3133,7 @@ You can re-send a sync message at any time simply by sending another tweet using Combined libraries of all your online friends - Комбинирани библиотеки от всичките ти приятели на линия + Комбинирани библиотеки от всичките ми приятели на линия @@ -3496,7 +3497,7 @@ Lyrics for "%1" by %2: I'm sorry -- I'm just an automatic presence used by Tomahawk Player (http://gettomahawk.com). If you are getting this message, the person you are trying to reach is probably not signed on, so please try again later! - Извинявай.. Аз съм режимът за автоматични отговори изпълзван от Tomahawk. (http://gettomahawk.com) Щом получаваш това съобщение, този с който се опитваш да се свържеш вероятно не е на линия. Моля, потай отново по-късно. + Извинявай.. Аз съм режимът за автоматични отговори изпълзван от Tomahawk. ( http://gettomahawk.com ) Щом получаваш това съобщение, този с който се опитваш да се свържеш вероятно не е на линия. Моля, опитай отново по-късно. diff --git a/lang/tomahawk_de.ts b/lang/tomahawk_de.ts index c4cc5e7bd..ef267e174 100644 --- a/lang/tomahawk_de.ts +++ b/lang/tomahawk_de.ts @@ -1154,7 +1154,7 @@ Denk dran: Erlaube das nur, wenn du dem Anderen vertraust und du die Rechte zum Recently Played - Kürzlich gehörte Lieder + Kürzlich gehörte Lieder FOO @@ -1255,7 +1255,7 @@ Denk dran: Erlaube das nur, wenn du dem Anderen vertraust und du die Rechte zum Recently Played - + Kürzlich gehörte Lieder From 06fbb9e0dc2b8e7ca8c89424f7a8a7ab4334989c Mon Sep 17 00:00:00 2001 From: Christian Muehlhaeuser Date: Wed, 11 Apr 2012 07:14:30 +0200 Subject: [PATCH 13/14] * Added SocialWidget, tweet or share your latest music obsessions. --- resources.qrc | 1 + src/CMakeLists.txt | 4 +- src/SocialWidget.cpp | 262 +++++++++++++++++ src/SocialWidget.h | 84 ++++++ src/SocialWidget.ui | 118 ++++++++ src/audiocontrols.cpp | 23 +- src/audiocontrols.h | 5 +- src/audiocontrols.ui | 16 ++ src/libtomahawk/globalactionmanager.cpp | 358 ++++++++++++++++-------- src/libtomahawk/globalactionmanager.h | 3 +- 10 files changed, 744 insertions(+), 130 deletions(-) create mode 100644 src/SocialWidget.cpp create mode 100644 src/SocialWidget.h create mode 100644 src/SocialWidget.ui diff --git a/resources.qrc b/resources.qrc index 333b83349..5f43a73b5 100644 --- a/resources.qrc +++ b/resources.qrc @@ -136,6 +136,7 @@ data/images/grooveshark.png data/images/lastfm-icon.png data/images/playlist-header-tiled.png + data/images/share.png data/sql/dbmigrate-27_to_28.sql data/images/process-stop.png data/icons/tomahawk-icon-128x128-grayscale.png diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bc677d1e4..a2aba674d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -87,6 +87,7 @@ SET( tomahawkSourcesGui ${tomahawkSourcesGui} LoadXSPFDialog.cpp AccountFactoryWrapper.cpp AccountFactoryWrapperDelegate.cpp + SocialWidget.cpp ) IF( WITH_BREAKPAD ) @@ -102,10 +103,9 @@ SET( tomahawkUI ${tomahawkUI} accounts/lastfm/LastFmConfig.ui audiocontrols.ui - LoadXSPFDialog.ui - AccountFactoryWrapper.ui + SocialWidget.ui ) INCLUDE_DIRECTORIES( diff --git a/src/SocialWidget.cpp b/src/SocialWidget.cpp new file mode 100644 index 000000000..0b491e0cf --- /dev/null +++ b/src/SocialWidget.cpp @@ -0,0 +1,262 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2012, Christian Muehlhaeuser + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#include "SocialWidget.h" +#include "ui_SocialWidget.h" + +#include +#include +#include + +#include "globalactionmanager.h" +#include "utils/logger.h" + +#define CORNER_ROUNDNESS 8.0 +#define FADING_DURATION 500 +#define FONT_SIZE 16 +#define OPACITY 0.70 + + +SocialWidget::SocialWidget( QWidget* parent ) + : QWidget( parent ) // this is on purpose! + , ui( new Ui::SocialWidget ) + , m_opacity( 0.00 ) + , m_parent( parent ) + , m_parentRect( parent->rect() ) +{ + ui->setupUi( this ); + + setAttribute( Qt::WA_TranslucentBackground, true ); + setOpacity( m_opacity ); + + m_timer.setSingleShot( true ); + connect( &m_timer, SIGNAL( timeout() ), this, SLOT( hide() ) ); + +#ifdef Q_WS_MAC + QFont f( font() ); + f.setPointSize( f.pointSize() - 2 ); + setFont( f ); +#endif + + ui->charsLeftLabel->setForegroundRole( QPalette::HighlightedText ); + + m_parent->installEventFilter( this ); + + connect( ui->buttonBox, SIGNAL( accepted() ), SLOT( accept() ) ); + connect( ui->buttonBox, SIGNAL( rejected() ), SLOT( deleteLater() ) ); + connect( ui->textEdit, SIGNAL( textChanged() ), SLOT( onChanged() ) ); + connect( ui->facebookButton, SIGNAL( clicked( bool ) ), SLOT( onChanged() ) ); + connect( ui->twitterButton, SIGNAL( clicked( bool ) ), SLOT( onChanged() ) ); + connect( GlobalActionManager::instance(), SIGNAL( shortLinkReady( QUrl, QUrl, QVariant ) ), SLOT( onShortLinkReady( QUrl, QUrl, QVariant ) ) ); + + onChanged(); +} + + +SocialWidget::~SocialWidget() +{ + delete ui; +} + + +void +SocialWidget::setOpacity( qreal opacity ) +{ + m_opacity = opacity; + + if ( m_opacity == 0.00 && !isHidden() ) + { + QWidget::hide(); + } + else if ( m_opacity > 0.00 && isHidden() ) + { + QWidget::show(); + } + + repaint(); +} + + +void +SocialWidget::show( int timeoutSecs ) +{ + if ( !isEnabled() ) + return; + + QPropertyAnimation* animation = new QPropertyAnimation( this, "opacity" ); + animation->setDuration( FADING_DURATION ); + animation->setEndValue( 1.0 ); + animation->start(); + + if( timeoutSecs > 0 ) + m_timer.start( timeoutSecs * 1000 ); +} + + +void +SocialWidget::hide() +{ + if ( !isEnabled() ) + return; + + QPropertyAnimation* animation = new QPropertyAnimation( this, "opacity" ); + animation->setDuration( FADING_DURATION ); + animation->setEndValue( 0.00 ); + animation->start(); +} + + +bool +SocialWidget::shown() const +{ + if ( !isEnabled() ) + return false; + + return m_opacity == OPACITY; +} + + +void +SocialWidget::paintEvent( QPaintEvent* event ) +{ + Q_UNUSED( event ); + + QPoint position( m_position - QPoint( size().width(), size().height() ) ); + if ( position != pos() ) + { + move( position ); + return; + } + + QPainter p( this ); + QRect r = contentsRect(); + + p.setBackgroundMode( Qt::TransparentMode ); + p.setRenderHint( QPainter::Antialiasing ); + p.setOpacity( m_opacity ); + + QPen pen( palette().dark().color(), .5 ); + p.setPen( pen ); + p.setBrush( QColor( 30, 30, 30, 255.0 * OPACITY ) ); + + p.drawRoundedRect( r, CORNER_ROUNDNESS, CORNER_ROUNDNESS ); + + QWidget::paintEvent( event ); + return; + + QTextOption to( Qt::AlignCenter ); + to.setWrapMode( QTextOption::WrapAtWordBoundaryOrAnywhere ); + + // shrink to fit if needed + QFont f( font() ); + f.setPointSize( FONT_SIZE ); + f.setBold( true ); + + QRectF textRect = r.adjusted( 8, 8, -8, -8 ); + qreal availHeight = textRect.height(); + + QFontMetricsF fm( f ); + qreal textHeight = fm.boundingRect( textRect, Qt::AlignCenter | Qt::TextWordWrap, "SocialWidget" ).height(); + while( textHeight > availHeight ) + { + if( f.pointSize() <= 4 ) // don't try harder + break; + + f.setPointSize( f.pointSize() - 1 ); + fm = QFontMetricsF( f ); + textHeight = fm.boundingRect( textRect, Qt::AlignCenter | Qt::TextWordWrap, "SocialWidget" ).height(); + } + + p.setFont( f ); + p.setPen( palette().highlightedText().color() ); + p.drawText( r.adjusted( 8, 8, -8, -8 ), "SocialWidget", to ); +} + + +void +SocialWidget::onShortLinkReady( const QUrl& longUrl, const QUrl& shortUrl, const QVariant& callbackObj ) +{ + ui->textEdit->setText( tr( "Listening to \"%1\" by %2 on \"%3\" and loving it! %4" ).arg( m_query->track() ).arg( m_query->artist() ).arg( m_query->album() ).arg( shortUrl.toString() ) ); +} + + +void +SocialWidget::setQuery( const Tomahawk::query_ptr& query ) +{ + m_query = query; + ui->coverImage->setPixmap( query->cover( ui->coverImage->size() ) ); + onChanged(); + + QUrl longUrl = GlobalActionManager::instance()->openLinkFromQuery( query ); + GlobalActionManager::instance()->shortenLink( longUrl ); +} + + +void +SocialWidget::onChanged() +{ + const int remaining = charsAvailable() - ui->textEdit->toPlainText().length(); + ui->charsLeftLabel->setText( tr( "%1 characters left" ).arg( remaining ) ); + ui->buttonBox->button( QDialogButtonBox::Ok )->setEnabled( remaining >= 0 && ( ui->facebookButton->isChecked() || ui->twitterButton->isChecked() ) ); +} + + +void +SocialWidget::accept() +{ + tDebug() << "Sharing social link!"; + + deleteLater(); +} + + +unsigned int +SocialWidget::charsAvailable() const +{ + if ( ui->twitterButton->isChecked() ) + return 140; + + return 420; // facebook max length +} + + +void +SocialWidget::onGeometryUpdate() +{ + QPoint p( m_parent->rect().width() - m_parentRect.width(), m_parent->rect().height() - m_parentRect.height() ); + m_position += p; + m_parentRect = m_parent->rect(); + + QPoint position( m_position - QPoint( size().width(), size().height() ) ); + if ( position != pos() ) + { + move( position ); + } +} + + +bool +SocialWidget::eventFilter( QObject* object, QEvent* event ) +{ + if ( event->type() == QEvent::Resize ) + { + onGeometryUpdate(); + } + + return QObject::eventFilter( object, event ); +} diff --git a/src/SocialWidget.h b/src/SocialWidget.h new file mode 100644 index 000000000..57f57b2af --- /dev/null +++ b/src/SocialWidget.h @@ -0,0 +1,84 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2012, Christian Muehlhaeuser + * + * Tomahawk is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Tomahawk is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Tomahawk. If not, see . + */ + +#ifndef SOCIALWIDGET_H +#define SOCIALWIDGET_H + +#include +#include +#include + +#include "query.h" + +namespace Ui +{ + class SocialWidget; +} + +class SocialWidget : public QWidget +{ +Q_OBJECT +Q_PROPERTY( qreal opacity READ opacity WRITE setOpacity ) + +public: + SocialWidget( QWidget* parent ); + ~SocialWidget(); + + Tomahawk::query_ptr query() const { return m_query; } + void setQuery( const Tomahawk::query_ptr& query ); + + qreal opacity() const { return m_opacity; } + void setOpacity( qreal opacity ); + + QPoint position() const { return m_position; } + void setPosition( QPoint position ) { m_position = position; } + + bool shown() const; + +public slots: + void show( int timeoutSecs = 0 ); + void hide(); + +protected: +// void changeEvent( QEvent* e ); + void paintEvent( QPaintEvent* event ); + bool eventFilter( QObject* object, QEvent* event ); + +private slots: + void accept(); + void onChanged(); + void onShortLinkReady( const QUrl& longUrl, const QUrl& shortUrl, const QVariant& callbackObj ); + + void onGeometryUpdate(); + +private: + unsigned int charsAvailable() const; + + Ui::SocialWidget* ui; + + Tomahawk::query_ptr m_query; + + qreal m_opacity; + QPoint m_position; + + QWidget* m_parent; + QRect m_parentRect; + QTimer m_timer; +}; + +#endif // SOCIALWIDGET_H diff --git a/src/SocialWidget.ui b/src/SocialWidget.ui new file mode 100644 index 000000000..d8da77af0 --- /dev/null +++ b/src/SocialWidget.ui @@ -0,0 +1,118 @@ + + + SocialWidget + + + + 0 + 0 + 365 + 190 + + + + Form + + + + 8 + + + 8 + + + 8 + + + + + + + Facebook + + + true + + + + + + + Twitter + + + true + + + + + + + + + + + + 96 + 96 + + + + + 96 + 96 + + + + Cover + + + + + + + + 16777215 + 96 + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + TextLabel + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + diff --git a/src/audiocontrols.cpp b/src/audiocontrols.cpp index 6a54e9144..d981f67ce 100644 --- a/src/audiocontrols.cpp +++ b/src/audiocontrols.cpp @@ -32,6 +32,7 @@ #include "utils/logger.h" #include "album.h" #include "dropjob.h" +#include "SocialWidget.h" #include "globalactionmanager.h" #include "viewmanager.h" @@ -44,6 +45,7 @@ AudioControls::AudioControls( QWidget* parent ) , m_repeatMode( PlaylistInterface::NoRepeat ) , m_shuffled( false ) , m_lastSliderCheck( 0 ) + , m_parent( parent ) { ui->setupUi( this ); setAcceptDrops( true ); @@ -82,6 +84,7 @@ AudioControls::AudioControls( QWidget* parent ) ui->repeatButton->setPixmap( RESPATH "images/repeat-off-pressed.png", QIcon::Off, QIcon::Active ); ui->volumeLowButton->setPixmap( RESPATH "images/volume-icon-muted.png" ); ui->volumeHighButton->setPixmap( RESPATH "images/volume-icon-full.png" ); + ui->socialButton->setPixmap( RESPATH "images/share.png" ); ui->loveButton->setPixmap( RESPATH "images/not-loved.png" ); ui->loveButton->setCheckable( true ); @@ -118,8 +121,9 @@ AudioControls::AudioControls( QWidget* parent ) connect( ui->shuffleButton, SIGNAL( clicked() ), SLOT( onShuffleClicked() ) ); connect( ui->artistTrackLabel, SIGNAL( clickedArtist() ), SLOT( onArtistClicked() ) ); - connect( ui->artistTrackLabel, SIGNAL( clickedTrack() ), SLOT( onTrackClicked() ) ); - connect( ui->albumLabel, SIGNAL( clickedAlbum() ), SLOT( onAlbumClicked() ) ); + connect( ui->artistTrackLabel, SIGNAL( clickedTrack() ), SLOT( onTrackClicked() ) ); + connect( ui->albumLabel, SIGNAL( clickedAlbum() ), SLOT( onAlbumClicked() ) ); + connect( ui->socialButton, SIGNAL( clicked() ), SLOT( onSocialButtonClicked() ) ); connect( ui->loveButton, SIGNAL( clicked( bool ) ), SLOT( onLoveButtonClicked( bool ) ) ); // @@ -247,6 +251,8 @@ AudioControls::onPlaybackLoading( const Tomahawk::result_ptr& result ) ui->loveButton->setEnabled( true ); ui->loveButton->setVisible( true ); + ui->socialButton->setEnabled( true ); + ui->socialButton->setVisible( true ); setCover(); setSocialActions(); @@ -319,7 +325,6 @@ AudioControls::onPlaybackResumed() { tDebug( LOGEXTRA ) << Q_FUNC_INFO; ui->stackedLayout->setCurrentWidget( ui->pauseButton ); - ui->loveButton->setVisible( true ); m_sliderTimeLine.resume(); } @@ -354,6 +359,8 @@ AudioControls::onPlaybackStopped() ui->stackedLayout->setCurrentWidget( ui->playPauseButton ); ui->loveButton->setEnabled( false ); ui->loveButton->setVisible( false ); + ui->socialButton->setEnabled( false ); + ui->socialButton->setVisible( false ); } @@ -590,6 +597,16 @@ AudioControls::droppedTracks( QList< query_ptr > tracks ) } +void +AudioControls::onSocialButtonClicked() +{ + SocialWidget* sw = new SocialWidget( m_parent ); + sw->setPosition( QCursor::pos() ); + sw->setQuery( m_currentTrack->toQuery() ); + sw->show(); +} + + void AudioControls::onLoveButtonClicked( bool checked ) { diff --git a/src/audiocontrols.h b/src/audiocontrols.h index b7adf31b8..a5eac1554 100644 --- a/src/audiocontrols.h +++ b/src/audiocontrols.h @@ -78,6 +78,7 @@ private slots: void onArtistClicked(); void onAlbumClicked(); void onTrackClicked(); + void onSocialButtonClicked(); void onLoveButtonClicked( bool ); void droppedTracks( QList ); @@ -89,7 +90,7 @@ private: void setCover(); void setSocialActions(); - Ui::AudioControls *ui; + Ui::AudioControls* ui; Tomahawk::result_ptr m_currentTrack; Tomahawk::PlaylistInterface::RepeatMode m_repeatMode; @@ -101,6 +102,8 @@ private: qint64 m_lastSliderCheck; bool m_noTimeChange; qint64 m_lastTextSecondShown; + + QWidget* m_parent; }; #endif // AUDIOCONTROLS_H diff --git a/src/audiocontrols.ui b/src/audiocontrols.ui index f07c1d784..fd4f871a3 100644 --- a/src/audiocontrols.ui +++ b/src/audiocontrols.ui @@ -287,6 +287,22 @@ + + + + + 0 + 0 + + + + PointingHandCursor + + + social + + + diff --git a/src/libtomahawk/globalactionmanager.cpp b/src/libtomahawk/globalactionmanager.cpp index ffde78745..e42c2f953 100644 --- a/src/libtomahawk/globalactionmanager.cpp +++ b/src/libtomahawk/globalactionmanager.cpp @@ -1,6 +1,7 @@ /* Copyright (C) 2011 Leo Franchi Copyright (C) 2011, Jeff Mitchell + Copyright (C) 2011-2012, Christian Muehlhaeuser 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 @@ -45,7 +46,6 @@ #include "playlist/topbar/topbar.h" #include "playlist/playlistview.h" - #include #include @@ -123,7 +123,7 @@ GlobalActionManager::openLink( const QString& title, const QString& artist, cons void -GlobalActionManager::shortenLink( const QUrl& url, const QVariant &callbackObj ) +GlobalActionManager::shortenLink( const QUrl& url, const QVariant& callbackObj ) { if ( QThread::currentThread() != thread() ) { @@ -148,7 +148,8 @@ GlobalActionManager::copyPlaylistToClipboard( const dynplaylist_ptr& playlist ) { QUrl link( QString( "%1/%2/create/" ).arg( hostname() ).arg( playlist->mode() == OnDemand ? "station" : "autoplaylist" ) ); - if( playlist->generator()->type() != "echonest" ) { + if ( playlist->generator()->type() != "echonest" ) + { tLog() << "Only echonest generators are supported"; return QString(); } @@ -157,19 +158,25 @@ GlobalActionManager::copyPlaylistToClipboard( const dynplaylist_ptr& playlist ) link.addQueryItem( "title", playlist->title() ); QList< dyncontrol_ptr > controls = playlist->generator()->controls(); - foreach( const dyncontrol_ptr& c, controls ) { - if( c->selectedType() == "Artist" ) { - if( c->match().toInt() == Echonest::DynamicPlaylist::ArtistType ) + foreach ( const dyncontrol_ptr& c, controls ) + { + if ( c->selectedType() == "Artist" ) + { + if ( c->match().toInt() == Echonest::DynamicPlaylist::ArtistType ) link.addQueryItem( "artist_limitto", c->input() ); else link.addQueryItem( "artist", c->input() ); - } else if( c->selectedType() == "Artist Description" ) { + } + else if ( c->selectedType() == "Artist Description" ) + { link.addQueryItem( "description", c->input() ); - } else { + } + else + { QString name = c->selectedType().toLower().replace( " ", "_" ); Echonest::DynamicPlaylist::PlaylistParam p = static_cast< Echonest::DynamicPlaylist::PlaylistParam >( c->match().toInt() ); // if it is a max, set that too - if( p == Echonest::DynamicPlaylist::MaxTempo || p == Echonest::DynamicPlaylist::MaxDuration || p == Echonest::DynamicPlaylist::MaxLoudness + if ( p == Echonest::DynamicPlaylist::MaxTempo || p == Echonest::DynamicPlaylist::MaxDuration || p == Echonest::DynamicPlaylist::MaxLoudness || p == Echonest::DynamicPlaylist::MaxDanceability || p == Echonest::DynamicPlaylist::MaxEnergy || p == Echonest::DynamicPlaylist::ArtistMaxFamiliarity || p == Echonest::DynamicPlaylist::ArtistMaxHotttnesss || p == Echonest::DynamicPlaylist::SongMaxHotttnesss || p == Echonest::DynamicPlaylist::ArtistMaxLatitude || p == Echonest::DynamicPlaylist::ArtistMaxLongitude ) @@ -204,7 +211,8 @@ GlobalActionManager::xspfCreated( const QByteArray& xspf ) QString filename = sender()->property( "filename" ).toString(); QFile f( filename ); - if( !f.open( QIODevice::WriteOnly ) ) { + if ( !f.open( QIODevice::WriteOnly ) ) + { qWarning() << "Failed to open file to save XSPF:" << filename; return; } @@ -220,7 +228,7 @@ void GlobalActionManager::copyToClipboard( const query_ptr& query ) { m_clipboardLongUrl = openLinkFromQuery( query ); - GlobalActionManager::instance()->shortenLink( m_clipboardLongUrl ); + shortenLink( m_clipboardLongUrl ); } @@ -228,10 +236,11 @@ bool GlobalActionManager::parseTomahawkLink( const QString& urlIn ) { QString url = urlIn; - if( urlIn.startsWith( "http://toma.hk" ) ) + if ( urlIn.startsWith( "http://toma.hk" ) ) url.replace( "http://toma.hk/", "tomahawk://" ); - if( url.contains( "tomahawk://" ) ) { + if ( url.contains( "tomahawk://" ) ) + { QString cmd = url.mid( 11 ); cmd.replace( "%2B", "%20" ); tLog() << "Parsing tomahawk link command" << cmd; @@ -240,8 +249,10 @@ GlobalActionManager::parseTomahawkLink( const QString& urlIn ) QUrl u = QUrl::fromEncoded( cmd.toUtf8() ); // for backwards compatibility - if( cmdType == "load" ) { - if( u.hasQueryItem( "xspf" ) ) { + if ( cmdType == "load" ) + { + if ( u.hasQueryItem( "xspf" ) ) + { QUrl xspf = QUrl::fromUserInput( u.queryItemValue( "xspf" ) ); XSPFLoader* l = new XSPFLoader( true, this ); tDebug() << "Loading spiff:" << xspf.toString(); @@ -249,7 +260,9 @@ GlobalActionManager::parseTomahawkLink( const QString& urlIn ) connect( l, SIGNAL( ok( Tomahawk::playlist_ptr ) ), ViewManager::instance(), SLOT( show( Tomahawk::playlist_ptr ) ) ); return true; - } else if( u.hasQueryItem( "jspf" ) ) { + } + else if ( u.hasQueryItem( "jspf" ) ) + { QUrl jspf = QUrl::fromUserInput( u.queryItemValue( "jspf" ) ); JSPFLoader* l = new JSPFLoader( true, this ); @@ -261,31 +274,54 @@ GlobalActionManager::parseTomahawkLink( const QString& urlIn ) } } - if( cmdType == "playlist" ) { + if ( cmdType == "playlist" ) + { return handlePlaylistCommand( u ); - } else if( cmdType == "collection" ) { + } + else if ( cmdType == "collection" ) + { return handleCollectionCommand( u ); - } else if( cmdType == "queue" ) { + } + else if ( cmdType == "queue" ) + { return handleQueueCommand( u ); - } else if( cmdType == "station" ) { + } + else if ( cmdType == "station" ) + { return handleStationCommand( u ); - } else if( cmdType == "autoplaylist" ) { + } + else if ( cmdType == "autoplaylist" ) + { return handleAutoPlaylistCommand( u ); - } else if( cmdType == "search" ) { + } + else if ( cmdType == "search" ) + { return handleSearchCommand( u ); - } else if( cmdType == "play" ) { + } + else if ( cmdType == "play" ) + { return handlePlayCommand( u ); - } else if( cmdType == "bookmark" ) { + } + else if ( cmdType == "bookmark" ) + { return handlePlayCommand( u ); - } else if( cmdType == "open" ) { + } + else if ( cmdType == "open" ) + { return handleOpenCommand( u ); - } else if( cmdType == "view" ) { + } + else if ( cmdType == "view" ) + { return handleViewCommand( u ); - } else { + } + else + { tLog() << "Tomahawk link not supported, command not known!" << cmdType << u.path(); return false; } - } else { + } + else + { tLog() << "Not a tomahawk:// link!"; return false; } @@ -296,13 +332,16 @@ bool GlobalActionManager::handlePlaylistCommand( const QUrl& url ) { QStringList parts = url.path().split( "/" ).mid( 1 ); // get the rest of the command - if( parts.isEmpty() ) { + if ( parts.isEmpty() ) + { tLog() << "No specific playlist command:" << url.toString(); return false; } - if( parts[ 0 ] == "import" ) { - if( !url.hasQueryItem( "xspf" ) ) { + if ( parts[ 0 ] == "import" ) + { + if ( !url.hasQueryItem( "xspf" ) ) + { tDebug() << "No xspf to load..."; return false; } @@ -313,15 +352,21 @@ GlobalActionManager::handlePlaylistCommand( const QUrl& url ) l->load( xspf ); connect( l, SIGNAL( ok( Tomahawk::playlist_ptr ) ), this, SLOT( playlistCreatedToShow( Tomahawk::playlist_ptr) ) ); - } else if( parts [ 0 ] == "new" ) { - if( !url.hasQueryItem( "title" ) ) { + } + else if ( parts [ 0 ] == "new" ) + { + if ( !url.hasQueryItem( "title" ) ) + { tLog() << "New playlist command needs a title..."; return false; } playlist_ptr pl = Playlist::create( SourceList::instance()->getLocal(), uuid(), url.queryItemValue( "title" ), QString(), QString(), false ); ViewManager::instance()->show( pl ); - } else if( parts[ 0 ] == "add" ) { - if( !url.hasQueryItem( "playlistid" ) || !url.hasQueryItem( "title" ) || !url.hasQueryItem( "artist" ) ) { + } + else if ( parts[ 0 ] == "add" ) + { + if ( !url.hasQueryItem( "playlistid" ) || !url.hasQueryItem( "title" ) || !url.hasQueryItem( "artist" ) ) + { tLog() << "Add to playlist command needs playlistid, track, and artist..." << url.toString(); return false; } @@ -353,12 +398,14 @@ bool GlobalActionManager::handleCollectionCommand( const QUrl& url ) { QStringList parts = url.path().split( "/" ).mid( 1 ); // get the rest of the command - if( parts.isEmpty() ) { + if ( parts.isEmpty() ) + { tLog() << "No specific collection command:" << url.toString(); return false; } - if( parts[ 0 ] == "add" ) { + if ( parts[ 0 ] == "add" ) + { // TODO implement } @@ -370,7 +417,8 @@ bool GlobalActionManager::handleOpenCommand(const QUrl& url) { QStringList parts = url.path().split( "/" ).mid( 1 ); - if( parts.isEmpty() ) { + if ( parts.isEmpty() ) + { tLog() << "No specific type to open:" << url.toString(); return false; } @@ -385,7 +433,8 @@ GlobalActionManager::handleOpenTrack ( const query_ptr& q ) ViewManager::instance()->queue()->model()->append( q ); ViewManager::instance()->showQueue(); - if( !AudioEngine::instance()->isPlaying() && !AudioEngine::instance()->isPaused() ) { + if ( !AudioEngine::instance()->isPlaying() && !AudioEngine::instance()->isPaused() ) + { connect( q.data(), SIGNAL( resolvingFinished( bool ) ), this, SLOT( waitingForResolved( bool ) ) ); m_waitingToPlay = q; } @@ -403,14 +452,18 @@ bool GlobalActionManager::handleQueueCommand( const QUrl& url ) { QStringList parts = url.path().split( "/" ).mid( 1 ); // get the rest of the command - if( parts.isEmpty() ) { + if ( parts.isEmpty() ) + { tLog() << "No specific queue command:" << url.toString(); return false; } - if( parts[ 0 ] == "add" ) { + if ( parts[ 0 ] == "add" ) + { doQueueAdd( parts.mid( 1 ), url.queryItems() ); - } else { + } + else + { tLog() << "Only queue/add/track is support at the moment, got:" << parts; return false; } @@ -422,46 +475,55 @@ GlobalActionManager::handleQueueCommand( const QUrl& url ) bool GlobalActionManager::doQueueAdd( const QStringList& parts, const QList< QPair< QString, QString > >& queryItems ) { - if( parts.size() && parts[ 0 ] == "track" ) { + if ( parts.size() && parts[ 0 ] == "track" ) + { - if( queueSpotify( parts, queryItems ) ) + if ( queueSpotify( parts, queryItems ) ) return true; - else if( queueRdio( parts, queryItems ) ) + else if ( queueRdio( parts, queryItems ) ) return true; QPair< QString, QString > pair; QString title, artist, album, urlStr; - foreach( pair, queryItems ) { + foreach ( pair, queryItems ) { pair.second = pair.second.replace( "+", " " ); // QUrl::queryItems doesn't decode + to a space :( - if( pair.first == "title" ) + if ( pair.first == "title" ) title = pair.second; - else if( pair.first == "artist" ) + else if ( pair.first == "artist" ) artist = pair.second; - else if( pair.first == "album" ) + else if ( pair.first == "album" ) album = pair.second; - else if( pair.first == "url" ) + else if ( pair.first == "url" ) urlStr = pair.second; } - if( !title.isEmpty() || !artist.isEmpty() || !album.isEmpty() ) { // an individual; query to add to queue + if ( !title.isEmpty() || !artist.isEmpty() || !album.isEmpty() ) + { + // an individual; query to add to queue query_ptr q = Query::get( artist, title, album, uuid(), false ); - if( !urlStr.isEmpty() ) + if ( !urlStr.isEmpty() ) q->setResultHint( urlStr ); Pipeline::instance()->resolve( q, true ); handleOpenTrack( q ); return true; - - } else { // a list of urls to add to the queue - foreach( pair, queryItems ) { - if( pair.first != "url" ) + } + else + { // a list of urls to add to the queue + foreach ( pair, queryItems ) + { + if ( pair.first != "url" ) continue; QUrl track = QUrl::fromUserInput( pair.second ); //FIXME: isLocalFile is Qt 4.8 - if( track.toString().startsWith( "file://" ) ) { // it's local, so we see if it's in the DB and load it if so + if ( track.toString().startsWith( "file://" ) ) + { + // it's local, so we see if it's in the DB and load it if so // TODO - } else { // give it a web result hint + } + else + { // give it a web result hint QFileInfo info( track.path() ); query_ptr q = Query::get( QString(), info.baseName(), QString(), uuid(), false ); q->setResultHint( track.toString() ); @@ -485,14 +547,15 @@ GlobalActionManager::queueSpotify( const QStringList& , const QList< QPair< QStr QString url; QPair< QString, QString > pair; - foreach( pair, queryItems ) { - if( pair.first == "spotifyURL" ) + foreach ( pair, queryItems ) + { + if ( pair.first == "spotifyURL" ) url = pair.second; - else if( pair.first == "spotifyURI" ) + else if ( pair.first == "spotifyURI" ) url = pair.second; } - if( url.isEmpty() ) + if ( url.isEmpty() ) return false; openSpotifyLink( url ); @@ -507,14 +570,15 @@ GlobalActionManager::queueRdio( const QStringList& , const QList< QPair< QString QString url; QPair< QString, QString > pair; - foreach( pair, queryItems ) { - if( pair.first == "rdioURL" ) + foreach ( pair, queryItems ) + { + if ( pair.first == "rdioURL" ) url = pair.second; - else if( pair.first == "rdioURI" ) + else if ( pair.first == "rdioURI" ) url = pair.second; } - if( url.isEmpty() ) + if ( url.isEmpty() ) return false; openRdioLink( url ); @@ -533,16 +597,16 @@ GlobalActionManager::handleSearchCommand( const QUrl& url ) else { QStringList query; - if( url.hasQueryItem( "artist" ) ) + if ( url.hasQueryItem( "artist" ) ) query << url.queryItemValue( "artist" ); - if( url.hasQueryItem( "album" ) ) + if ( url.hasQueryItem( "album" ) ) query << url.queryItemValue( "album" ); - if( url.hasQueryItem( "title" ) ) + if ( url.hasQueryItem( "title" ) ) query << url.queryItemValue( "title" ); queryStr = query.join( " " ); } - if( queryStr.trimmed().isEmpty() ) + if ( queryStr.trimmed().isEmpty() ) return false; ViewManager::instance()->show( new SearchWidget( queryStr.trimmed() ) ); @@ -554,7 +618,7 @@ bool GlobalActionManager::handleViewCommand( const QUrl& url ) { QStringList parts = url.path().split( "/" ).mid( 1 ); // get the rest of the command - if( parts.isEmpty() ) { + if ( parts.isEmpty() ) { tLog() << "No specific view command:" << url.toString(); return false; } @@ -604,135 +668,177 @@ Tomahawk::dynplaylist_ptr GlobalActionManager::loadDynamicPlaylist( const QUrl& url, bool station ) { QStringList parts = url.path().split( "/" ).mid( 1 ); // get the rest of the command - if( parts.isEmpty() ) { + if ( parts.isEmpty() ) + { tLog() << "No specific station command:" << url.toString(); return Tomahawk::dynplaylist_ptr(); } - if( parts[ 0 ] == "create" ) { - if( !url.hasQueryItem( "title" ) || !url.hasQueryItem( "type" ) ) { + if ( parts[ 0 ] == "create" ) + { + if ( !url.hasQueryItem( "title" ) || !url.hasQueryItem( "type" ) ) + { tLog() << "Station create command needs title and type..." << url.toString(); return Tomahawk::dynplaylist_ptr(); } QString title = url.queryItemValue( "title" ); QString type = url.queryItemValue( "type" ); GeneratorMode m = Static; - if( station ) + if ( station ) m = OnDemand; dynplaylist_ptr pl = DynamicPlaylist::create( SourceList::instance()->getLocal(), uuid(), title, QString(), QString(), m, false, type ); pl->setMode( m ); QList< dyncontrol_ptr > controls; QPair< QString, QString > param; - foreach( param, url.queryItems() ) { - if( param.first == "artist" ) { + foreach ( param, url.queryItems() ) + { + if ( param.first == "artist" ) + { dyncontrol_ptr c = pl->generator()->createControl( "Artist" ); c->setInput( param.second ); c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistRadioType ) ); controls << c; - } else if( param.first == "artist_limitto" ) { + } + else if ( param.first == "artist_limitto" ) + { dyncontrol_ptr c = pl->generator()->createControl( "Artist" ); c->setInput( param.second ); c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistType ) ); controls << c; - } else if( param.first == "description" ) { + } + else if ( param.first == "description" ) + { dyncontrol_ptr c = pl->generator()->createControl( "Artist Description" ); c->setInput( param.second ); c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistDescriptionType ) ); controls << c; - } else if( param.first == "variety" ) { + } + else if ( param.first == "variety" ) + { dyncontrol_ptr c = pl->generator()->createControl( "Variety" ); c->setInput( param.second ); c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::Variety ) ); controls << c; - } else if( param.first.startsWith( "tempo" ) ) { + } + else if ( param.first.startsWith( "tempo" ) ) + { dyncontrol_ptr c = pl->generator()->createControl( "Tempo" ); int extra = param.first.endsWith( "_max" ) ? -1 : 0; c->setInput( param.second ); c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::MinTempo + extra ) ); controls << c; - } else if( param.first.startsWith( "duration" ) ) { + } + else if ( param.first.startsWith( "duration" ) ) + { dyncontrol_ptr c = pl->generator()->createControl( "Duration" ); int extra = param.first.endsWith( "_max" ) ? -1 : 0; c->setInput( param.second ); c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::MinDuration + extra ) ); controls << c; - } else if( param.first.startsWith( "loudness" ) ) { + } + else if ( param.first.startsWith( "loudness" ) ) + { dyncontrol_ptr c = pl->generator()->createControl( "Loudness" ); int extra = param.first.endsWith( "_max" ) ? -1 : 0; c->setInput( param.second ); c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::MinLoudness + extra ) ); controls << c; - } else if( param.first.startsWith( "danceability" ) ) { + } + else if ( param.first.startsWith( "danceability" ) ) + { dyncontrol_ptr c = pl->generator()->createControl( "Danceability" ); int extra = param.first.endsWith( "_max" ) ? 1 : 0; c->setInput( param.second ); c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::MinDanceability + extra ) ); controls << c; - } else if( param.first.startsWith( "energy" ) ) { + } + else if ( param.first.startsWith( "energy" ) ) + { dyncontrol_ptr c = pl->generator()->createControl( "Energy" ); int extra = param.first.endsWith( "_max" ) ? 1 : 0; c->setInput( param.second ); c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::MinEnergy + extra ) ); controls << c; - } else if( param.first.startsWith( "artist_familiarity" ) ) { + } + else if ( param.first.startsWith( "artist_familiarity" ) ) + { dyncontrol_ptr c = pl->generator()->createControl( "Artist Familiarity" ); int extra = param.first.endsWith( "_max" ) ? -1 : 0; c->setInput( param.second ); c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistMinFamiliarity + extra ) ); controls << c; - } else if( param.first.startsWith( "artist_hotttnesss" ) ) { + } + else if ( param.first.startsWith( "artist_hotttnesss" ) ) + { dyncontrol_ptr c = pl->generator()->createControl( "Artist Hotttnesss" ); int extra = param.first.endsWith( "_max" ) ? -1 : 0; c->setInput( param.second ); c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistMinHotttnesss + extra ) ); controls << c; - } else if( param.first.startsWith( "song_hotttnesss" ) ) { + } + else if ( param.first.startsWith( "song_hotttnesss" ) ) + { dyncontrol_ptr c = pl->generator()->createControl( "Song Hotttnesss" ); int extra = param.first.endsWith( "_max" ) ? -1 : 0; c->setInput( param.second ); c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::SongMinHotttnesss + extra ) ); controls << c; - } else if( param.first.startsWith( "longitude" ) ) { + } + else if ( param.first.startsWith( "longitude" ) ) + { dyncontrol_ptr c = pl->generator()->createControl( "Longitude" ); int extra = param.first.endsWith( "_max" ) ? 1 : 0; c->setInput( param.second ); c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistMinLongitude + extra ) ); controls << c; - } else if( param.first.startsWith( "latitude" ) ) { + } + else if ( param.first.startsWith( "latitude" ) ) + { dyncontrol_ptr c = pl->generator()->createControl( "Latitude" ); int extra = param.first.endsWith( "_max" ) ? 1 : 0; c->setInput( param.second ); c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistMinLatitude + extra ) ); controls << c; - } else if( param.first == "key" ) { + } + else if ( param.first == "key" ) + { dyncontrol_ptr c = pl->generator()->createControl( "Key" ); c->setInput( param.second ); c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::Key ) ); controls << c; - } else if( param.first == "mode" ) { + } + else if ( param.first == "mode" ) + { dyncontrol_ptr c = pl->generator()->createControl( "Mode" ); c->setInput( param.second ); c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::Mode ) ); controls << c; - } else if( param.first == "mood" ) { + } + else if ( param.first == "mood" ) + { dyncontrol_ptr c = pl->generator()->createControl( "Mood" ); c->setInput( param.second ); c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::Mood ) ); controls << c; - } else if( param.first == "style" ) { + } + else if ( param.first == "style" ) + { dyncontrol_ptr c = pl->generator()->createControl( "Style" ); c->setInput( param.second ); c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::Style ) ); controls << c; - } else if( param.first == "song" ) { + } + else if ( param.first == "song" ) + { dyncontrol_ptr c = pl->generator()->createControl( "Song" ); c->setInput( param.second ); c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::SongRadioType ) ); controls << c; } } - if( m == OnDemand ) + + if ( m == OnDemand ) pl->createNewRevision( uuid(), pl->currentrevision(), type, controls ); else pl->createNewRevision( uuid(), pl->currentrevision(), type, controls, pl->entries() ); @@ -756,31 +862,35 @@ bool GlobalActionManager::handlePlayCommand( const QUrl& url ) { QStringList parts = url.path().split( "/" ).mid( 1 ); // get the rest of the command - if( parts.isEmpty() ) { + if ( parts.isEmpty() ) + { tLog() << "No specific play command:" << url.toString(); return false; } - if( parts[ 0 ] == "track" ) { - if( playSpotify( url ) ) + if ( parts[ 0 ] == "track" ) + { + if ( playSpotify( url ) ) return true; - else if( playRdio( url ) ) + else if ( playRdio( url ) ) return true; QPair< QString, QString > pair; QString title, artist, album, urlStr; - foreach( pair, url.queryItems() ) { - if( pair.first == "title" ) + foreach ( pair, url.queryItems() ) + { + if ( pair.first == "title" ) title = pair.second; - else if( pair.first == "artist" ) + else if ( pair.first == "artist" ) artist = pair.second; - else if( pair.first == "album" ) + else if ( pair.first == "album" ) album = pair.second; - else if( pair.first == "url" ) + else if ( pair.first == "url" ) urlStr = pair.second; } + query_ptr q = Query::get( artist, title, album ); - if( !urlStr.isEmpty() ) + if ( !urlStr.isEmpty() ) q->setResultHint( urlStr ); playNow( q ); @@ -794,7 +904,7 @@ GlobalActionManager::handlePlayCommand( const QUrl& url ) bool GlobalActionManager::playSpotify( const QUrl& url ) { - if( !url.hasQueryItem( "spotifyURI" ) && !url.hasQueryItem( "spotifyURL" ) ) + if ( !url.hasQueryItem( "spotifyURI" ) && !url.hasQueryItem( "spotifyURL" ) ) return false; QString spotifyUrl = url.hasQueryItem( "spotifyURI" ) ? url.queryItemValue( "spotifyURI" ) : url.queryItemValue( "spotifyURL" ); @@ -829,10 +939,9 @@ GlobalActionManager::playOrQueueNow( const query_ptr& q ) bool GlobalActionManager::playRdio( const QUrl& url ) { - if( !url.hasQueryItem( "rdioURI" ) && !url.hasQueryItem( "rdioURL" ) ) + if ( !url.hasQueryItem( "rdioURI" ) && !url.hasQueryItem( "rdioURL" ) ) return false; - QString rdioUrl = url.hasQueryItem( "rdioURI" ) ? url.queryItemValue( "spotifyURI" ) : url.queryItemValue( "rdioURL" ); RdioParser* p = new RdioParser( this ); p->parse( rdioUrl ); @@ -845,33 +954,36 @@ GlobalActionManager::playRdio( const QUrl& url ) bool GlobalActionManager::handleBookmarkCommand(const QUrl& url) { QStringList parts = url.path().split( "/" ).mid( 1 ); // get the rest of the command - if( parts.isEmpty() ) { + if ( parts.isEmpty() ) + { tLog() << "No specific bookmark command:" << url.toString(); return false; } - if( parts[ 0 ] == "track" ) { + if ( parts[ 0 ] == "track" ) + { QPair< QString, QString > pair; QString title, artist, album, urlStr; - foreach( pair, url.queryItems() ) { - if( pair.first == "title" ) + foreach ( pair, url.queryItems() ) + { + if ( pair.first == "title" ) title = pair.second; - else if( pair.first == "artist" ) + else if ( pair.first == "artist" ) artist = pair.second; - else if( pair.first == "album" ) + else if ( pair.first == "album" ) album = pair.second; - else if( pair.first == "url" ) + else if ( pair.first == "url" ) urlStr = pair.second; } query_ptr q = Query::get( artist, title, album ); - if( !urlStr.isEmpty() ) + if ( !urlStr.isEmpty() ) q->setResultHint( urlStr ); Pipeline::instance()->resolve( q, true ); // now we add it to the special "bookmarks" playlist, creating it if it doesn't exist. if nothing is playing, start playing the track QSharedPointer< LocalCollection > col = SourceList::instance()->getLocal()->collection().dynamicCast< LocalCollection >(); playlist_ptr bookmarkpl = col->bookmarksPlaylist(); - if( bookmarkpl.isNull() ) { // create it and do the deed then + if ( bookmarkpl.isNull() ) { // create it and do the deed then m_waitingToBookmark = q; col->createBookmarksPlaylist(); connect( col.data(), SIGNAL( bookmarkPlaylistCreated( Tomahawk::playlist_ptr ) ), this, SLOT( bookmarkPlaylistCreated( Tomahawk::playlist_ptr ) ), Qt::UniqueConnection ); @@ -894,7 +1006,7 @@ GlobalActionManager::shortenLinkRequestFinished() bool error = false; // NOTE: this should never happen - if( !reply ) + if ( !reply ) { emit shortLinkReady( QUrl( "" ), QUrl( "" ), QVariantMap() ); return; @@ -908,14 +1020,14 @@ GlobalActionManager::shortenLinkRequestFinished() QVariant urlVariant = reply->attribute( QNetworkRequest::RedirectionTargetAttribute ); // NOTE: this should never happen - if( urlVariant.isNull() || !urlVariant.isValid() ) + if ( urlVariant.isNull() || !urlVariant.isValid() ) error = true; QUrl longUrl = reply->request().url(); QUrl shortUrl = urlVariant.toUrl(); // NOTE: this should never happen - if( !shortUrl.isValid() ) + if ( !shortUrl.isValid() ) error = true; // Success! Here is the short link @@ -950,7 +1062,7 @@ GlobalActionManager::shortenLinkRequestError( QNetworkReply::NetworkError error QNetworkReply *reply = qobject_cast( sender() ); // NOTE: this should never happen - if( !reply ) + if ( !reply ) { emit shortLinkReady( QUrl( "" ), QUrl( "" ), QVariantMap() ); return; @@ -999,7 +1111,7 @@ GlobalActionManager::doBookmark( const playlist_ptr& pl, const query_ptr& q ) void GlobalActionManager::showPlaylist() { - if( m_toShow.isNull() ) + if ( m_toShow.isNull() ) return; ViewManager::instance()->show( m_toShow ); diff --git a/src/libtomahawk/globalactionmanager.h b/src/libtomahawk/globalactionmanager.h index 5b0a72017..6a3f1b304 100644 --- a/src/libtomahawk/globalactionmanager.h +++ b/src/libtomahawk/globalactionmanager.h @@ -67,7 +67,7 @@ public slots: void handlePlayTrack( const Tomahawk::query_ptr& qry ); signals: - void shortLinkReady( QUrl longUrl, QUrl shortUrl, QVariant callbackObj ) const; + void shortLinkReady( const QUrl& longUrl, const QUrl& shortUrl, const QVariant& callbackObj ); private slots: void shortenLinkRequestFinished(); @@ -83,6 +83,7 @@ private slots: void playlistCreatedToShow( const Tomahawk::playlist_ptr& pl ); void playlistReadyToShow(); + private: explicit GlobalActionManager( QObject* parent = 0 ); void doBookmark( const Tomahawk::playlist_ptr& pl, const Tomahawk::query_ptr& q ); From c5eb71d0deb800e7f1aea049e06fe8b2299eb96f Mon Sep 17 00:00:00 2001 From: Christian Muehlhaeuser Date: Wed, 11 Apr 2012 07:35:01 +0200 Subject: [PATCH 14/14] * Small tweaks to the SocialWidget. --- src/SocialWidget.cpp | 21 +++++++++++++-------- src/SocialWidget.h | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/SocialWidget.cpp b/src/SocialWidget.cpp index 0b491e0cf..e5c2394da 100644 --- a/src/SocialWidget.cpp +++ b/src/SocialWidget.cpp @@ -92,6 +92,14 @@ SocialWidget::setOpacity( qreal opacity ) } +void +SocialWidget::setPosition( QPoint position ) +{ + m_position = position; + onGeometryUpdate(); +} + + void SocialWidget::show( int timeoutSecs ) { @@ -136,13 +144,6 @@ SocialWidget::paintEvent( QPaintEvent* event ) { Q_UNUSED( event ); - QPoint position( m_position - QPoint( size().width(), size().height() ) ); - if ( position != pos() ) - { - move( position ); - return; - } - QPainter p( this ); QRect r = contentsRect(); @@ -191,7 +192,10 @@ SocialWidget::paintEvent( QPaintEvent* event ) void SocialWidget::onShortLinkReady( const QUrl& longUrl, const QUrl& shortUrl, const QVariant& callbackObj ) { - ui->textEdit->setText( tr( "Listening to \"%1\" by %2 on \"%3\" and loving it! %4" ).arg( m_query->track() ).arg( m_query->artist() ).arg( m_query->album() ).arg( shortUrl.toString() ) ); + if ( m_query->album().isEmpty() ) + ui->textEdit->setText( tr( "Listening to \"%1\" by %2 and loving it! %4" ).arg( m_query->track() ).arg( m_query->artist() ).arg( shortUrl.toString() ) ); + else + ui->textEdit->setText( tr( "Listening to \"%1\" by %2 on \"%3\" and loving it! %4" ).arg( m_query->track() ).arg( m_query->artist() ).arg( m_query->album() ).arg( shortUrl.toString() ) ); } @@ -200,6 +204,7 @@ SocialWidget::setQuery( const Tomahawk::query_ptr& query ) { m_query = query; ui->coverImage->setPixmap( query->cover( ui->coverImage->size() ) ); + onShortLinkReady( QString(), QString(), QVariant() ); onChanged(); QUrl longUrl = GlobalActionManager::instance()->openLinkFromQuery( query ); diff --git a/src/SocialWidget.h b/src/SocialWidget.h index 57f57b2af..437bcd3ad 100644 --- a/src/SocialWidget.h +++ b/src/SocialWidget.h @@ -46,7 +46,7 @@ public: void setOpacity( qreal opacity ); QPoint position() const { return m_position; } - void setPosition( QPoint position ) { m_position = position; } + void setPosition( QPoint position ); bool shown() const;