mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-09-19 02:11:32 +02:00
Compare commits
127 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
292f395c47 | ||
|
047f3cc2d4 | ||
|
97681ace31 | ||
|
6be5257bc0 | ||
|
8cfbe1f38b | ||
|
8db8e42ec4 | ||
|
9492055fc6 | ||
|
3dc624858b | ||
|
f154c2bbcd | ||
|
e9127ae3ec | ||
|
c7d9d8e5b7 | ||
|
e525291213 | ||
|
44269ee8f6 | ||
|
53c4a2d675 | ||
|
ebfc53e009 | ||
|
190845a86e | ||
|
25af4f4275 | ||
|
bca64a70ed | ||
|
10462ee257 | ||
|
ba4532593b | ||
|
c84fd28dd2 | ||
|
dbbb491a81 | ||
|
bab5e27673 | ||
|
17f71bd366 | ||
|
e96bbc11e1 | ||
|
d492ba0317 | ||
|
b6466a6027 | ||
|
6b5d391cde | ||
|
0680dec5df | ||
|
a4e8f4216c | ||
|
355c95e068 | ||
|
da07361ec0 | ||
|
aafe8797ad | ||
|
95343ca024 | ||
|
f85bcc1c64 | ||
|
e53e51aefc | ||
|
d22b33bc50 | ||
|
c36414bb4c | ||
|
a78349f9f1 | ||
|
fa41b96260 | ||
|
7f2bf85663 | ||
|
85fe824df3 | ||
|
c37bbb4deb | ||
|
1a9bf84ab4 | ||
|
a283ea1ed0 | ||
|
d27dd0785a | ||
|
5e1f808d28 | ||
|
aba78c7a24 | ||
|
f45e92a24d | ||
|
5ae04043d4 | ||
|
5f521a6cf5 | ||
|
a4b30dcecd | ||
|
700394a054 | ||
|
819ee17b74 | ||
|
79c55f1699 | ||
|
f42696de23 | ||
|
adfaf5ce53 | ||
|
32aca98a97 | ||
|
294809debb | ||
|
e4593079f3 | ||
|
cfa4210854 | ||
|
91084885fb | ||
|
0b7f420bef | ||
|
046237f009 | ||
|
85d9755a47 | ||
|
98bd7b1857 | ||
|
37510fc2d7 | ||
|
a91ad7dd5f | ||
|
2cc85c8f4f | ||
|
19625fffd4 | ||
|
a98cab55b7 | ||
|
ec7b98e589 | ||
|
1262dcb60a | ||
|
fc9c6e6017 | ||
|
fa4463dc88 | ||
|
3fb403c695 | ||
|
fdb1d1b621 | ||
|
127da50144 | ||
|
5640923d51 | ||
|
4a2ef91638 | ||
|
012556ca0a | ||
|
8d0a51cc64 | ||
|
253120a35c | ||
|
671bd5361b | ||
|
3dc969a31f | ||
|
64a70f5073 | ||
|
1911d4b8a0 | ||
|
92229ce3e2 | ||
|
7df3f867ea | ||
|
6e66c4a192 | ||
|
49fe0f945e | ||
|
0d915513b9 | ||
|
6c69edd0e7 | ||
|
23c2c77869 | ||
|
cd7c64ac0a | ||
|
0637ee7338 | ||
|
7765aa116b | ||
|
c46ed53930 | ||
|
22105d448a | ||
|
4f4efdfbab | ||
|
686730e27c | ||
|
fdfe4d12d4 | ||
|
669e7550f2 | ||
|
d4a2294963 | ||
|
66b0ecc846 | ||
|
c3563a2449 | ||
|
05efe29a67 | ||
|
3480690479 | ||
|
a1fb66e024 | ||
|
02e9f99ce4 | ||
|
95c74fe370 | ||
|
358226bdb1 | ||
|
a2d81d0099 | ||
|
292e97fcee | ||
|
6dafcf3c80 | ||
|
ee1b13aee6 | ||
|
ce8eecd40f | ||
|
f674b3b751 | ||
|
44cd64a8b6 | ||
|
a9418fc8aa | ||
|
44546763b9 | ||
|
66a74ad6e2 | ||
|
6aae2dd96f | ||
|
ffd2cee2ff | ||
|
438f8444c3 | ||
|
b55be311b4 | ||
|
7a4d113af6 |
@@ -13,7 +13,7 @@ SET( TOMAHAWK_DESCRIPTION_SUMMARY "The social media player" )
|
||||
|
||||
SET( TOMAHAWK_VERSION_MAJOR 0 )
|
||||
SET( TOMAHAWK_VERSION_MINOR 5 )
|
||||
SET( TOMAHAWK_VERSION_PATCH 0 )
|
||||
SET( TOMAHAWK_VERSION_PATCH 3 )
|
||||
|
||||
#SET( TOMAHAWK_VERSION_RC 0 )
|
||||
|
||||
@@ -35,8 +35,11 @@ IF( CMAKE_SYSTEM_PROCESSOR MATCHES "arm" )
|
||||
ENDIF()
|
||||
|
||||
# add definitions based on build options
|
||||
IF(WITH_BREAKPAD)
|
||||
IF( WITH_BREAKPAD )
|
||||
message(STATUS "Build with support for breakpad.")
|
||||
IF( CMAKE_COMPILER_IS_GNUCXX )
|
||||
ADD_DEFINITIONS( -DSTDC_HEADERS -std=gnu++98 )
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# generate version string
|
||||
@@ -157,8 +160,8 @@ SET( LIBPORTFWD_LIBRARIES ${LIBPORTFWD_LIBRARY} )
|
||||
ADD_SUBDIRECTORY( ${THIRDPARTY_DIR}/libportfwd )
|
||||
|
||||
# we need pthreads too
|
||||
#macro_optional_find_package(Threads)
|
||||
#macro_log_feature(THREADS_FOUND "Threads" "Threading Library" "" TRUE "" "Platform specific library for threading")
|
||||
macro_optional_find_package(Threads)
|
||||
macro_log_feature(THREADS_FOUND "Threads" "Threading Library" "" TRUE "" "Platform specific library for threading")
|
||||
|
||||
macro_optional_find_package(KDE4)
|
||||
macro_optional_find_package(KDE4Installed)
|
||||
|
25
ChangeLog
25
ChangeLog
@@ -1,3 +1,20 @@
|
||||
Version 0.5.3:
|
||||
* Fixed broken artist names when importing Last.fm playback history.
|
||||
* Fixed crash when filtering collections.
|
||||
|
||||
Version 0.5.2:
|
||||
* Fixed a crash when invalid results are coming back from a resolver or
|
||||
are found in a playlist.
|
||||
|
||||
Version 0.5.1:
|
||||
* Fixed a few issues with automatic downloading and launching
|
||||
of the Spotify account.
|
||||
* Show an error message when not able to resolve a requested song.
|
||||
* Fixed a few crash and freeze issues.
|
||||
* Better detection of local networks for the Local Network connector.
|
||||
* Don't prompt for access permission for your own accounts.
|
||||
* (OS X) Fixed not being able to connect to Last.fm.
|
||||
|
||||
Version 0.5.0:
|
||||
* SOCKS5 proxy support improvements for resolvers and more.
|
||||
* Initial Access Control support, allowing users to define who is able to
|
||||
@@ -52,7 +69,7 @@ Version 0.4.0:
|
||||
* Fixed bug where filter text would be one step behind filter value.
|
||||
* Fixed bug where resolvers would enable themselves after auto-updating.
|
||||
* Fixed occasional crash when dropping tracks onto New Station item.
|
||||
* Added jump-to-current-track support for search results page.
|
||||
* Added jump-to-current-track support for search results page.
|
||||
* Fixed non-resolving tracks when dragging from album view.
|
||||
* Fixed fetching album covers for albums with special characters.
|
||||
* Show errors and continue gracefully when resolved audio is not available.
|
||||
@@ -77,7 +94,7 @@ Version 0.4.0:
|
||||
* Fixed out of sync Show/Hide menu items on OS X when hidden with cmd-h.
|
||||
* Fixed /Volumes directory not showing up on OS X.
|
||||
* Fixed startup crash on OS X.
|
||||
|
||||
|
||||
Version 0.3.3:
|
||||
* Automatically load Super Collection tracks when no official release
|
||||
information is available.
|
||||
@@ -89,7 +106,7 @@ Version 0.3.3:
|
||||
* Fixed dupe menu entry appearing on OS X.
|
||||
* Fixed invisible sidebar items on Linux.
|
||||
|
||||
Version 0.3.2:
|
||||
Version 0.3.2:
|
||||
* Improved syncing process, it's faster and more reliable now.
|
||||
* Fixed UPnP issues.
|
||||
* Fixed not updating collections and views after a collection changes.
|
||||
@@ -143,7 +160,7 @@ Version 0.3.0:
|
||||
* Added YouTube resolver.
|
||||
* Fixed bug where going offline then online would not re-connect to many
|
||||
peers.
|
||||
* Added support for auto-updating live XSPF playlists.
|
||||
* Added support for auto-updating live XSPF playlists.
|
||||
* Don't show an age of 41 years for tracks that have no age information.
|
||||
* Show config UI for resolvers that have them as soon as you add them.
|
||||
* Add support for Echo Nest Personal Catalogs and User Radio. Synchronize
|
||||
|
@@ -28,9 +28,6 @@ FRAMEWORK_SEARCH_PATH=[
|
||||
|
||||
LIBRARY_SEARCH_PATH=['/usr/local/lib', '/usr/local/Cellar/gettext/0.18.1.1/lib', '.']
|
||||
|
||||
LIBSPOTIFY_VERSION = commands.getoutput("brew ls -version libspotify | tr -s \" \" \"\\\\012\" | tail -n 1").strip()
|
||||
LIBSPOTIFY_PATH = "/usr/local/lib/libspotify.%s.dylib" % LIBSPOTIFY_VERSION
|
||||
|
||||
VLC_PLUGINS=[
|
||||
'libaccess_attachment_plugin.dylib',
|
||||
#'libaccess_avio_plugin.dylib',
|
||||
@@ -512,11 +509,6 @@ try:
|
||||
except:
|
||||
print 'Failed to find tomahawk_crash_reporter'
|
||||
|
||||
try:
|
||||
FixPlugin(LIBSPOTIFY_PATH, "../Frameworks")
|
||||
except:
|
||||
print "Failed to copy libspotify from os: %s" % LIBSPOTIFY_PATH
|
||||
|
||||
for plugin in QT_PLUGINS:
|
||||
FixPlugin(FindQtPlugin(plugin), os.path.dirname(plugin))
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -85,7 +85,7 @@ AudioControls::AudioControls( QWidget* parent )
|
||||
ui->socialButton->setPixmap( RESPATH "images/share.png" );
|
||||
ui->loveButton->setPixmap( RESPATH "images/not-loved.png" );
|
||||
ui->loveButton->setCheckable( true );
|
||||
|
||||
|
||||
ui->socialButton->setFixedSize( QSize( 20, 20 ) );
|
||||
ui->loveButton->setFixedSize( QSize( 20, 20 ) );
|
||||
|
||||
@@ -588,7 +588,7 @@ AudioControls::droppedTracks( QList< query_ptr > tracks )
|
||||
{
|
||||
// queue and play the first no matter what
|
||||
GlobalActionManager::instance()->handlePlayTrack( tracks.first() );
|
||||
ViewManager::instance()->queue()->model()->append( tracks );
|
||||
ViewManager::instance()->queue()->model()->appendQueries( tracks );
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -129,6 +129,8 @@ IF( UNIX )
|
||||
ENDIF( UNIX )
|
||||
|
||||
IF( APPLE )
|
||||
SET( CMAKE_LINKER_FLAGS "-headerpad_max_install_names ${CMAKE_LINKER_FLAGS}" )
|
||||
|
||||
INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/thirdparty/SPMediaKeyTap )
|
||||
|
||||
SET( tomahawkSources ${tomahawkSources} mac/TomahawkApp_Mac.mm mac/MacShortcutHandler.cpp )
|
||||
|
@@ -48,7 +48,7 @@ DiagnosticsDialog::DiagnosticsDialog( QWidget *parent )
|
||||
connect( ui->buttonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
|
||||
|
||||
ui->scrollAreaWidgetContents->setLayout( new QVBoxLayout() );
|
||||
|
||||
|
||||
updateLogView();
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ DiagnosticsDialog::updateLogView()
|
||||
ui->scrollAreaWidgetContents->layout()->addWidget( new QLabel( log, this ) );
|
||||
// Peers / Accounts, TODO
|
||||
ui->scrollAreaWidgetContents->layout()->addWidget( new QLabel( "ACCOUNTS:\n", this ) );
|
||||
|
||||
|
||||
const QList< Tomahawk::source_ptr > sources = SourceList::instance()->sources( true );
|
||||
const QList< Tomahawk::Accounts::Account* > accounts = Tomahawk::Accounts::AccountManager::instance()->accounts( Tomahawk::Accounts::SipType );
|
||||
foreach ( Tomahawk::Accounts::Account* account, accounts )
|
||||
@@ -107,13 +107,15 @@ DiagnosticsDialog::updateLogView()
|
||||
connect( account->sipPlugin(), SIGNAL( peerOffline( QString ) ), SLOT( onPeerOffline( QString ) ) );
|
||||
connect( account->sipPlugin(), SIGNAL( sipInfoReceived( QString, SipInfo ) ), SLOT( onSipInfoReceived( QString, SipInfo ) ) );
|
||||
connect( account->sipPlugin(), SIGNAL( softwareVersionReceived( QString, QString ) ), SLOT( onSoftwareVersionReceived( QString, QString ) ) );
|
||||
|
||||
|
||||
QLabel* accountInfoLabel = new QLabel( this );
|
||||
ui->scrollAreaWidgetContents->layout()->addWidget( accountInfoLabel );
|
||||
m_accountDescriptionStore.insert( account, accountInfoLabel );
|
||||
|
||||
|
||||
updateAccountLabel( account );
|
||||
}
|
||||
|
||||
ui->scrollAreaWidgetContents->layout()->addItem( new QSpacerItem( 1, 1, QSizePolicy::Fixed, QSizePolicy::Expanding ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -135,8 +137,8 @@ DiagnosticsDialog::onAccountConnectionStateChanged( Tomahawk::Accounts::Account:
|
||||
{
|
||||
Tomahawk::Accounts::Account* account = qobject_cast< Tomahawk::Accounts::Account* >( sender() );
|
||||
Q_ASSERT( account );
|
||||
|
||||
updateAccountLabel( account );
|
||||
|
||||
updateAccountLabel( account );
|
||||
}
|
||||
|
||||
|
||||
@@ -153,7 +155,7 @@ DiagnosticsDialog::onPeerOnline( const QString& )
|
||||
{
|
||||
Tomahawk::Accounts::Account* account = qobject_cast< SipPlugin* >( sender() )->account();
|
||||
Q_ASSERT( account );
|
||||
|
||||
|
||||
updateAccountLabel( account );
|
||||
}
|
||||
|
||||
@@ -163,7 +165,7 @@ DiagnosticsDialog::onPeerOffline( const QString& )
|
||||
{
|
||||
Tomahawk::Accounts::Account* account = qobject_cast< SipPlugin* >( sender() )->account();
|
||||
Q_ASSERT( account );
|
||||
|
||||
|
||||
updateAccountLabel( account );
|
||||
}
|
||||
|
||||
@@ -173,7 +175,7 @@ DiagnosticsDialog::onSipInfoReceived( const QString& /* peerId */ , const SipInf
|
||||
{
|
||||
Tomahawk::Accounts::Account* account = qobject_cast< SipPlugin* >( sender() )->account();
|
||||
Q_ASSERT( account );
|
||||
|
||||
|
||||
updateAccountLabel( account );
|
||||
}
|
||||
|
||||
@@ -183,7 +185,7 @@ DiagnosticsDialog::onSoftwareVersionReceived( const QString& /* peerId */ , cons
|
||||
{
|
||||
Tomahawk::Accounts::Account* account = qobject_cast< SipPlugin* >( sender() )->account();
|
||||
Q_ASSERT( account );
|
||||
|
||||
|
||||
updateAccountLabel( account );
|
||||
}
|
||||
|
||||
@@ -192,7 +194,7 @@ void
|
||||
DiagnosticsDialog::updateAccountLabel( Tomahawk::Accounts::Account* account )
|
||||
{
|
||||
QLabel* accountInfoLabel = m_accountDescriptionStore.value( account );
|
||||
|
||||
|
||||
if ( accountInfoLabel )
|
||||
{
|
||||
QString accountInfo;
|
||||
@@ -256,7 +258,7 @@ DiagnosticsDialog::updateAccountLabel( Tomahawk::Accounts::Account* account )
|
||||
}
|
||||
}
|
||||
accountInfo.append( "\n" );
|
||||
|
||||
|
||||
accountInfoLabel->setText( accountInfo );
|
||||
}
|
||||
}
|
@@ -200,7 +200,7 @@ TomahawkApp::init()
|
||||
QFontMetrics fm( f );
|
||||
TomahawkUtils::setHeaderHeight( fm.height() + 8 );
|
||||
#endif
|
||||
|
||||
|
||||
TomahawkUtils::setHeadless( m_headless );
|
||||
|
||||
TomahawkSettings* s = TomahawkSettings::instance();
|
||||
@@ -210,11 +210,18 @@ TomahawkApp::init()
|
||||
Q_UNUSED( TomahawkUtils::nam() );
|
||||
|
||||
m_audioEngine = QWeakPointer<AudioEngine>( new AudioEngine );
|
||||
m_scanManager = QWeakPointer<ScanManager>( new ScanManager( this ) );
|
||||
|
||||
// init pipeline and resolver factories
|
||||
new Pipeline();
|
||||
|
||||
m_servent = QWeakPointer<Servent>( new Servent( this ) );
|
||||
connect( m_servent.data(), SIGNAL( ready() ), SLOT( initSIP() ) );
|
||||
|
||||
tDebug() << "Init Database.";
|
||||
initDatabase();
|
||||
|
||||
m_scanManager = QWeakPointer<ScanManager>( new ScanManager( this ) );
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
Pipeline::instance()->addExternalResolverFactory( boost::bind( &QtScriptResolver::factory, _1 ) );
|
||||
Pipeline::instance()->addExternalResolverFactory( boost::bind( &ScriptResolver::factory, _1 ) );
|
||||
@@ -223,12 +230,6 @@ TomahawkApp::init()
|
||||
connect( ActionCollection::instance()->getAction( "quit" ), SIGNAL( triggered() ), SLOT( quit() ), Qt::UniqueConnection );
|
||||
#endif
|
||||
|
||||
m_servent = QWeakPointer<Servent>( new Servent( this ) );
|
||||
connect( m_servent.data(), SIGNAL( ready() ), SLOT( initSIP() ) );
|
||||
|
||||
tDebug() << "Init Database.";
|
||||
initDatabase();
|
||||
|
||||
QByteArray magic = QByteArray::fromBase64( enApiSecret );
|
||||
QByteArray wand = QByteArray::fromBase64( QCoreApplication::applicationName().toLatin1() );
|
||||
int length = magic.length(), n2 = wand.length();
|
||||
|
@@ -66,17 +66,17 @@ CrashReporter::CrashReporter( const QStringList& args )
|
||||
m_minidump = m_dir + '/' + args.value( 2 ) + ".dmp";
|
||||
m_product_name = args.value( 3 );
|
||||
|
||||
setFixedSize( sizeHint() );
|
||||
|
||||
//hide until "send report" has been clicked
|
||||
ui.progressBar->setVisible( false );
|
||||
ui.button->setVisible( false );
|
||||
ui.progressLabel->setVisible( false );
|
||||
connect( ui.sendButton, SIGNAL( clicked() ), SLOT( onSendButton() ));
|
||||
|
||||
connect( ui.sendButton, SIGNAL( clicked() ), SLOT( onSendButton() ) );
|
||||
|
||||
adjustSize();
|
||||
setFixedSize( size() );
|
||||
}
|
||||
|
||||
|
||||
CrashReporter::~CrashReporter()
|
||||
{
|
||||
delete m_http;
|
||||
@@ -186,6 +186,7 @@ CrashReporter::onFail( int error, const QString& errorString )
|
||||
qDebug() << "Error:" << error << errorString;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CrashReporter::onSendButton()
|
||||
{
|
||||
@@ -194,5 +195,9 @@ CrashReporter::onSendButton()
|
||||
ui.progressLabel->setVisible( true );
|
||||
ui.sendButton->setEnabled( false );
|
||||
ui.dontSendButton->setEnabled( false );
|
||||
|
||||
adjustSize();
|
||||
setFixedSize( size() );
|
||||
|
||||
QTimer::singleShot( 0, this, SLOT( send() ) );
|
||||
}
|
||||
|
@@ -9,8 +9,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>438</width>
|
||||
<height>246</height>
|
||||
<width>376</width>
|
||||
<height>216</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@@ -109,7 +109,7 @@ FdoNotifyPlugin::notifyUser( const QString &messageText )
|
||||
arguments << quint32( 0 ); //notification_id
|
||||
arguments << QString(); //app_icon
|
||||
arguments << QString( "Tomahawk" ); //summary
|
||||
arguments << messageText; //body
|
||||
arguments << QString( messageText ); //body
|
||||
arguments << QStringList(); //actions
|
||||
QVariantMap dict;
|
||||
dict["desktop-entry"] = QString( "tomahawk" );
|
||||
|
@@ -174,17 +174,21 @@ Album::infoSystemInfo( const Tomahawk::InfoSystem::InfoRequestData& requestData,
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !output.isNull() && output.isValid() )
|
||||
if ( output.isNull() )
|
||||
{
|
||||
m_coverLoaded = true;
|
||||
}
|
||||
else if ( output.isValid() )
|
||||
{
|
||||
QVariantMap returnedData = output.value< QVariantMap >();
|
||||
const QByteArray ba = returnedData["imgbytes"].toByteArray();
|
||||
if ( ba.length() )
|
||||
{
|
||||
m_coverBuffer = ba;
|
||||
emit coverChanged();
|
||||
}
|
||||
|
||||
m_coverLoaded = true;
|
||||
emit coverChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,6 +241,6 @@ Album::infoid() const
|
||||
{
|
||||
if ( m_uuid.isEmpty() )
|
||||
m_uuid = uuid();
|
||||
|
||||
|
||||
return m_uuid;
|
||||
}
|
@@ -120,7 +120,7 @@ AlbumPlaylistInterface::tracks()
|
||||
DatabaseCommand_AllTracks* cmd = new DatabaseCommand_AllTracks( m_collection );
|
||||
cmd->setAlbum( m_album );
|
||||
cmd->setSortOrder( DatabaseCommand_AllTracks::AlbumPosition );
|
||||
|
||||
|
||||
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr>, QVariant ) ),
|
||||
SLOT( onTracksLoaded( QList<Tomahawk::query_ptr> ) ) );
|
||||
|
||||
@@ -188,7 +188,7 @@ AlbumPlaylistInterface::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData re
|
||||
cmd->setAlbum( m_album );
|
||||
//this takes discnumber into account as well
|
||||
cmd->setSortOrder( DatabaseCommand_AllTracks::AlbumPosition );
|
||||
|
||||
|
||||
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr>, QVariant ) ),
|
||||
SLOT( onTracksLoaded( QList<Tomahawk::query_ptr> ) ) );
|
||||
|
||||
@@ -196,6 +196,7 @@ AlbumPlaylistInterface::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData re
|
||||
}
|
||||
else
|
||||
{
|
||||
m_finished = true;
|
||||
emit tracksLoaded( m_mode, m_collection );
|
||||
}
|
||||
}
|
||||
@@ -212,5 +213,6 @@ AlbumPlaylistInterface::onTracksLoaded( const QList< query_ptr >& tracks )
|
||||
else
|
||||
m_queries << tracks;
|
||||
|
||||
m_finished = true;
|
||||
emit tracksLoaded( m_mode, m_collection );
|
||||
}
|
||||
|
@@ -315,16 +315,20 @@ Artist::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVari
|
||||
|
||||
case Tomahawk::InfoSystem::InfoArtistImages:
|
||||
{
|
||||
if ( !output.isNull() && output.isValid() )
|
||||
if ( output.isNull() )
|
||||
{
|
||||
m_coverLoaded = true;
|
||||
}
|
||||
else if ( output.isValid() )
|
||||
{
|
||||
const QByteArray ba = returnedData["imgbytes"].toByteArray();
|
||||
if ( ba.length() )
|
||||
{
|
||||
m_coverBuffer = ba;
|
||||
emit coverChanged();
|
||||
}
|
||||
|
||||
m_coverLoaded = true;
|
||||
emit coverChanged();
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -353,7 +357,7 @@ Artist::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVari
|
||||
if ( source == "last.fm" )
|
||||
m_biography = bmap[ source ].toHash()[ "text" ].toString();
|
||||
}
|
||||
|
||||
|
||||
m_biographyLoaded = true;
|
||||
emit biographyLoaded();
|
||||
|
||||
@@ -459,7 +463,7 @@ Artist::playlistInterface( ModelMode mode, const Tomahawk::collection_ptr& colle
|
||||
pli = Tomahawk::playlistinterface_ptr( new Tomahawk::ArtistPlaylistInterface( this, mode, collection ) );
|
||||
connect( pli.data(), SIGNAL( tracksLoaded( Tomahawk::ModelMode, Tomahawk::collection_ptr ) ),
|
||||
SLOT( onTracksLoaded( Tomahawk::ModelMode, Tomahawk::collection_ptr ) ) );
|
||||
|
||||
|
||||
m_playlistInterface[ mode ][ collection ] = pli;
|
||||
}
|
||||
|
||||
@@ -479,6 +483,6 @@ Artist::infoid() const
|
||||
{
|
||||
if ( m_uuid.isEmpty() )
|
||||
m_uuid = uuid();
|
||||
|
||||
|
||||
return m_uuid;
|
||||
}
|
||||
|
@@ -118,7 +118,7 @@ ArtistPlaylistInterface::tracks()
|
||||
DatabaseCommand_AllTracks* cmd = new DatabaseCommand_AllTracks( m_collection );
|
||||
cmd->setArtist( m_artist );
|
||||
cmd->setSortOrder( DatabaseCommand_AllTracks::AlbumPosition );
|
||||
|
||||
|
||||
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr>, QVariant ) ),
|
||||
SLOT( onTracksLoaded( QList<Tomahawk::query_ptr> ) ) );
|
||||
|
||||
@@ -186,7 +186,7 @@ ArtistPlaylistInterface::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData r
|
||||
cmd->setArtist( m_artist );
|
||||
//this takes discnumber into account as well
|
||||
cmd->setSortOrder( DatabaseCommand_AllTracks::AlbumPosition );
|
||||
|
||||
|
||||
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr>, QVariant ) ),
|
||||
SLOT( onTracksLoaded( QList<Tomahawk::query_ptr> ) ) );
|
||||
|
||||
@@ -194,6 +194,7 @@ ArtistPlaylistInterface::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData r
|
||||
}
|
||||
else
|
||||
{
|
||||
m_finished = true;
|
||||
emit tracksLoaded( m_mode, m_collection );
|
||||
}
|
||||
}
|
||||
@@ -210,5 +211,6 @@ ArtistPlaylistInterface::onTracksLoaded( const QList< query_ptr >& tracks )
|
||||
else
|
||||
m_queries << tracks;
|
||||
|
||||
m_finished = true;
|
||||
emit tracksLoaded( m_mode, m_collection );
|
||||
}
|
||||
|
@@ -31,6 +31,9 @@
|
||||
#include <QTemporaryFile>
|
||||
#include <QDir>
|
||||
#include <QTimer>
|
||||
#include <QDomDocument>
|
||||
#include <QDomElement>
|
||||
#include <QDomNode>
|
||||
|
||||
#include "utils/Logger.h"
|
||||
#include "accounts/ResolverAccount.h"
|
||||
@@ -64,7 +67,7 @@ AtticaManager::AtticaManager( QObject* parent )
|
||||
// resolvers
|
||||
// m_manager.addProviderFile( QUrl( "http://bakery.tomahawk-player.org/resolvers/providers.xml" ) );
|
||||
|
||||
const QString url = QString( "http://bakery.tomahawk-player.org/resolvers/providers.xml?version=%1" ).arg( TomahawkUtils::appFriendlyVersion() );
|
||||
const QString url = QString( "%1/resolvers/providers.xml?version=%2" ).arg( hostname() ).arg( TomahawkUtils::appFriendlyVersion() );
|
||||
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( QUrl( url ) ) );
|
||||
NewClosure( reply, SIGNAL( finished() ), this, SLOT( providerFetched( QNetworkReply* ) ), reply );
|
||||
connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( providerError( QNetworkReply::NetworkError ) ) );
|
||||
@@ -90,6 +93,12 @@ AtticaManager::~AtticaManager()
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
AtticaManager::hostname() const
|
||||
{
|
||||
return "http://bakery.tomahawk-player.org";
|
||||
}
|
||||
|
||||
void
|
||||
AtticaManager::loadPixmapsFromCache()
|
||||
{
|
||||
@@ -523,14 +532,15 @@ void AtticaManager::doInstallResolver( const Content& resolver, bool autoCreate,
|
||||
m_resolverStates[ resolver.id() ].version = resolver.version();
|
||||
emit resolverStateChanged( resolver.id() );
|
||||
|
||||
ItemJob< DownloadItem >* job = m_resolverProvider.downloadLink( resolver.id() );
|
||||
connect( job, SIGNAL( finished( Attica::BaseJob* ) ), this, SLOT( resolverDownloadFinished( Attica::BaseJob* ) ) );
|
||||
job->setProperty( "resolverId", resolver.id() );
|
||||
job->setProperty( "createAccount", autoCreate );
|
||||
job->setProperty( "handler", QVariant::fromValue< QObject* >( handler ) );
|
||||
job->setProperty( "binarySignature", resolver.attribute("signature"));
|
||||
|
||||
job->start();
|
||||
// ItemJob< DownloadItem >* job = m_resolverProvider.downloadLink( resolver.id() );
|
||||
QUrl url( QString( "%1/resolvers/v1/content/download/%2/1" ).arg( hostname() ).arg( resolver.id() ) );
|
||||
url.addQueryItem( "tomahawkversion", TomahawkUtils::appFriendlyVersion() );
|
||||
QNetworkReply* r = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
|
||||
NewClosure( r, SIGNAL( finished() ), this, SLOT( resolverDownloadFinished( QNetworkReply* ) ), r );
|
||||
r->setProperty( "resolverId", resolver.id() );
|
||||
r->setProperty( "createAccount", autoCreate );
|
||||
r->setProperty( "handler", QVariant::fromValue< QObject* >( handler ) );
|
||||
r->setProperty( "binarySignature", resolver.attribute("signature"));
|
||||
}
|
||||
|
||||
|
||||
@@ -552,25 +562,49 @@ AtticaManager::upgradeResolver( const Content& resolver )
|
||||
|
||||
|
||||
void
|
||||
AtticaManager::resolverDownloadFinished ( BaseJob* j )
|
||||
AtticaManager::resolverDownloadFinished ( QNetworkReply *j )
|
||||
{
|
||||
ItemJob< DownloadItem >* job = static_cast< ItemJob< DownloadItem >* >( j );
|
||||
Q_ASSERT( j );
|
||||
if ( !j )
|
||||
return;
|
||||
|
||||
if ( job->metadata().error() == Attica::Metadata::NoError )
|
||||
if ( j->error() == QNetworkReply::NoError )
|
||||
{
|
||||
DownloadItem item = job->result();
|
||||
QUrl url = item.url();
|
||||
// download the resolver itself :)
|
||||
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
|
||||
connect( reply, SIGNAL( finished() ), this, SLOT( payloadFetched() ) );
|
||||
reply->setProperty( "resolverId", job->property( "resolverId" ) );
|
||||
reply->setProperty( "createAccount", job->property( "createAccount" ) );
|
||||
reply->setProperty( "handler", job->property( "handler" ) );
|
||||
reply->setProperty( "binarySignature", job->property( "binarySignature" ) );
|
||||
QDomDocument doc;
|
||||
doc.setContent( j );
|
||||
|
||||
const QDomNodeList nodes = doc.documentElement().elementsByTagName( "downloadlink" );
|
||||
if ( nodes.length() < 1 )
|
||||
{
|
||||
tLog() << "Found no download link for resolver:" << doc.toString();
|
||||
return;
|
||||
}
|
||||
|
||||
QUrl url( nodes.item( 0 ).toElement().text() );
|
||||
// download the resolver itself :)
|
||||
tDebug() << "Downloading resolver from url:" << url.toString();
|
||||
|
||||
const QDomNodeList signatures = doc.documentElement().elementsByTagName( "signature" );
|
||||
|
||||
// Use the original signature provided
|
||||
QString signature = j->property( "binarySignature" ).toString();
|
||||
if ( signatures.size() > 0 )
|
||||
{
|
||||
// THis download has an overriding signature. Take that one instead
|
||||
const QString sig = signatures.item( 0 ).toElement().text();
|
||||
tLog() << "Found overridden signature in binary download:" << sig;
|
||||
signature = sig;
|
||||
}
|
||||
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
|
||||
connect( reply, SIGNAL( finished() ), this, SLOT( payloadFetched() ) );
|
||||
reply->setProperty( "resolverId", j->property( "resolverId" ) );
|
||||
reply->setProperty( "createAccount", j->property( "createAccount" ) );
|
||||
reply->setProperty( "handler", j->property( "handler" ) );
|
||||
reply->setProperty( "binarySignature", signature );
|
||||
}
|
||||
else
|
||||
{
|
||||
tLog() << "Failed to do resolver download job!" << job->metadata().error();
|
||||
tLog() << "Failed to do resolver download job!" << j->errorString() << j->error();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -703,19 +737,6 @@ AtticaManager::uninstallResolver( const Content& resolver )
|
||||
|
||||
m_resolverStates[ resolver.id() ].state = Uninstalled;
|
||||
TomahawkSettingsGui::instanceGui()->setAtticaResolverState( resolver.id(), Uninstalled );
|
||||
|
||||
// remove account as well
|
||||
QList< Tomahawk::Accounts::Account* > accounts = Tomahawk::Accounts::AccountManager::instance()->accounts( Tomahawk::Accounts::ResolverType );
|
||||
foreach ( Tomahawk::Accounts::Account* account, accounts )
|
||||
{
|
||||
if ( Tomahawk::Accounts::AtticaResolverAccount* atticaAccount = qobject_cast< Tomahawk::Accounts::AtticaResolverAccount* >( account ) )
|
||||
{
|
||||
if ( atticaAccount->atticaId() == resolver.id() ) // this is the account we want to remove
|
||||
{
|
||||
Tomahawk::Accounts::AccountManager::instance()->removeAccount( atticaAccount );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doResolverRemove( resolver.id() );
|
||||
|
@@ -132,7 +132,7 @@ private slots:
|
||||
void categoriesReturned( Attica::BaseJob* );
|
||||
void resolversList( Attica::BaseJob* );
|
||||
void binaryResolversList( Attica::BaseJob* );
|
||||
void resolverDownloadFinished( Attica::BaseJob* );
|
||||
void resolverDownloadFinished( QNetworkReply* );
|
||||
void payloadFetched();
|
||||
|
||||
void loadPixmapsFromCache();
|
||||
@@ -144,6 +144,7 @@ private slots:
|
||||
private:
|
||||
void doResolverRemove( const QString& id ) const;
|
||||
void doInstallResolver( const Attica::Content& resolver, bool autoCreate, Tomahawk::Accounts::AtticaResolverAccount* handler );
|
||||
QString hostname() const;
|
||||
|
||||
Attica::ProviderManager m_manager;
|
||||
|
||||
|
@@ -17,7 +17,6 @@ add_definitions( -DQT_SHARED )
|
||||
add_definitions( -DDLLEXPORT_PRO )
|
||||
add_definitions( -DQT_SHAREDPOINTER_TRACK_POINTERS )
|
||||
|
||||
|
||||
set( libGuiSources
|
||||
ActionCollection.cpp
|
||||
|
||||
@@ -380,6 +379,8 @@ IF( APPLE )
|
||||
FIND_LIBRARY( SCRIPTINGBRIDGE_LIBRARY ScriptingBridge )
|
||||
MARK_AS_ADVANCED( COREAUDIO_LIBRARY COREFOUNDATION_LIBRARY FOUNDATION_LIBRARY SCRIPTINGBRIDGE_LIBRARY )
|
||||
|
||||
SET( CMAKE_SHARED_LINKER_FLAGS "-headerpad_max_install_names ${CMAKE_SHARED_LINKER_FLAGS}" )
|
||||
|
||||
SET( libSources ${libSources}
|
||||
utils/TomahawkUtils_Mac.mm
|
||||
mac/FileHelpers.mm
|
||||
|
@@ -85,9 +85,9 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
|
||||
if ( m_supportedActions & ActionStopAfter && itemCount() == 1 )
|
||||
{
|
||||
if ( AudioEngine::instance()->stopAfterTrack() == queries.first() )
|
||||
m_sigmap->setMapping( addAction( tr( "&Continue Playback after this Track" ) ), ActionStopAfter );
|
||||
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();
|
||||
@@ -151,8 +151,8 @@ ContextMenu::setAlbums( const QList<Tomahawk::album_ptr>& albums )
|
||||
|
||||
addSeparator();
|
||||
|
||||
/* if ( m_supportedActions & ActionCopyLink && itemCount() == 1 )
|
||||
m_sigmap->setMapping( addAction( tr( "Copy Album &Link" ) ), ActionCopyLink ); */
|
||||
if ( m_supportedActions & ActionCopyLink && itemCount() == 1 )
|
||||
m_sigmap->setMapping( addAction( tr( "Copy Album &Link" ) ), ActionCopyLink );
|
||||
|
||||
foreach ( QAction* action, actions() )
|
||||
{
|
||||
@@ -193,8 +193,8 @@ ContextMenu::setArtists( const QList<Tomahawk::artist_ptr>& artists )
|
||||
|
||||
addSeparator();
|
||||
|
||||
/* if ( m_supportedActions & ActionCopyLink && itemCount() == 1 )
|
||||
m_sigmap->setMapping( addAction( tr( "Copy Artist &Link" ) ), ActionCopyLink ); */
|
||||
if ( m_supportedActions & ActionCopyLink && itemCount() == 1 )
|
||||
m_sigmap->setMapping( addAction( tr( "Copy Artist &Link" ) ), ActionCopyLink );
|
||||
|
||||
foreach ( QAction* action, actions() )
|
||||
{
|
||||
@@ -224,7 +224,7 @@ ContextMenu::onTriggered( int action )
|
||||
case ActionCopyLink:
|
||||
copyLink();
|
||||
break;
|
||||
|
||||
|
||||
case ActionPage:
|
||||
openPage();
|
||||
break;
|
||||
@@ -252,15 +252,15 @@ ContextMenu::addToQueue()
|
||||
{
|
||||
foreach ( const query_ptr& query, m_queries )
|
||||
{
|
||||
ViewManager::instance()->queue()->model()->append( query );
|
||||
ViewManager::instance()->queue()->model()->appendQuery( query );
|
||||
}
|
||||
foreach ( const artist_ptr& artist, m_artists )
|
||||
{
|
||||
ViewManager::instance()->queue()->model()->append( artist );
|
||||
ViewManager::instance()->queue()->model()->appendArtist( artist );
|
||||
}
|
||||
foreach ( const album_ptr& album, m_albums )
|
||||
{
|
||||
ViewManager::instance()->queue()->model()->append( album );
|
||||
ViewManager::instance()->queue()->model()->appendAlbum( album );
|
||||
}
|
||||
|
||||
ViewManager::instance()->showQueue();
|
||||
@@ -274,6 +274,14 @@ ContextMenu::copyLink()
|
||||
{
|
||||
GlobalActionManager::instance()->copyToClipboard( m_queries.first() );
|
||||
}
|
||||
else if ( m_albums.count() )
|
||||
{
|
||||
GlobalActionManager::instance()->copyOpenLink( m_albums.first() );
|
||||
}
|
||||
else if ( m_artists.count() )
|
||||
{
|
||||
GlobalActionManager::instance()->copyOpenLink( m_artists.first() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -553,7 +553,7 @@ GlobalActionManager::handleOpenCommand( const QUrl& url )
|
||||
void
|
||||
GlobalActionManager::handleOpenTrack( const query_ptr& q )
|
||||
{
|
||||
ViewManager::instance()->queue()->model()->append( q );
|
||||
ViewManager::instance()->queue()->model()->appendQuery( q );
|
||||
ViewManager::instance()->showQueue();
|
||||
|
||||
if ( !AudioEngine::instance()->isPlaying() && !AudioEngine::instance()->isPaused() )
|
||||
@@ -570,7 +570,7 @@ GlobalActionManager::handleOpenTracks( const QList< query_ptr >& queries )
|
||||
if ( queries.isEmpty() )
|
||||
return;
|
||||
|
||||
ViewManager::instance()->queue()->model()->append( queries );
|
||||
ViewManager::instance()->queue()->model()->appendQueries( queries );
|
||||
ViewManager::instance()->showQueue();
|
||||
|
||||
if ( !AudioEngine::instance()->isPlaying() && !AudioEngine::instance()->isPaused() )
|
||||
@@ -617,16 +617,15 @@ GlobalActionManager::doQueueAdd( const QStringList& parts, const QList< QPair< Q
|
||||
{
|
||||
if ( parts.size() && parts[ 0 ] == "track" )
|
||||
{
|
||||
|
||||
if ( queueSpotify( parts, queryItems ) )
|
||||
return true;
|
||||
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" )
|
||||
title = pair.second;
|
||||
@@ -642,9 +641,12 @@ GlobalActionManager::doQueueAdd( const QStringList& parts, const QList< QPair< Q
|
||||
{
|
||||
// an individual; query to add to queue
|
||||
query_ptr q = Query::get( artist, title, album, uuid(), false );
|
||||
if ( q.isNull() )
|
||||
return false;
|
||||
|
||||
if ( !urlStr.isEmpty() )
|
||||
q->setResultHint( urlStr );
|
||||
Pipeline::instance()->resolve( q, true );
|
||||
Pipeline::instance()->resolve( q );
|
||||
|
||||
handleOpenTrack( q );
|
||||
return true;
|
||||
@@ -666,11 +668,13 @@ GlobalActionManager::doQueueAdd( const QStringList& parts, const QList< QPair< Q
|
||||
{ // give it a web result hint
|
||||
QFileInfo info( track.path() );
|
||||
query_ptr q = Query::get( QString(), info.baseName(), QString(), uuid(), false );
|
||||
if ( q.isNull() )
|
||||
continue;
|
||||
|
||||
q->setResultHint( track.toString() );
|
||||
Pipeline::instance()->resolve( q );
|
||||
|
||||
Pipeline::instance()->resolve( q, true );
|
||||
|
||||
ViewManager::instance()->queue()->model()->append( q );
|
||||
ViewManager::instance()->queue()->model()->appendQuery( q );
|
||||
ViewManager::instance()->showQueue();
|
||||
}
|
||||
return true;
|
||||
@@ -1067,6 +1071,9 @@ GlobalActionManager::handlePlayCommand( const QUrl& url )
|
||||
}
|
||||
|
||||
query_ptr q = Query::get( artist, title, album );
|
||||
if ( q.isNull() )
|
||||
return false;
|
||||
|
||||
if ( !urlStr.isEmpty() )
|
||||
q->setResultHint( urlStr );
|
||||
|
||||
@@ -1155,18 +1162,25 @@ bool GlobalActionManager::handleBookmarkCommand(const QUrl& url)
|
||||
urlStr = pair.second;
|
||||
}
|
||||
query_ptr q = Query::get( artist, title, album );
|
||||
if ( q.isNull() )
|
||||
return false;
|
||||
|
||||
if ( !urlStr.isEmpty() )
|
||||
q->setResultHint( urlStr );
|
||||
Pipeline::instance()->resolve( q, true );
|
||||
Pipeline::instance()->resolve( q );
|
||||
|
||||
// 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 );
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
doBookmark( bookmarkpl, q );
|
||||
}
|
||||
|
||||
@@ -1343,7 +1357,7 @@ GlobalActionManager::waitingForResolved( bool /* success */ )
|
||||
AudioEngine::instance()->playItem( AudioEngine::instance()->playlist(), m_waitingToPlay->results().first() );
|
||||
else
|
||||
{
|
||||
ViewManager::instance()->queue()->model()->append( m_waitingToPlay );
|
||||
ViewManager::instance()->queue()->model()->appendQuery( m_waitingToPlay );
|
||||
AudioEngine::instance()->play();
|
||||
}
|
||||
}
|
||||
|
@@ -54,6 +54,7 @@ PlaylistEntry::setQueryVariant( const QVariant& v )
|
||||
QString artist = m.value( "artist" ).toString();
|
||||
QString album = m.value( "album" ).toString();
|
||||
QString track = m.value( "track" ).toString();
|
||||
|
||||
m_query = Tomahawk::Query::get( artist, track, album );
|
||||
}
|
||||
|
||||
|
@@ -59,10 +59,11 @@ public:
|
||||
PlaylistEntry();
|
||||
virtual ~PlaylistEntry();
|
||||
|
||||
bool isValid() const { return !m_query.isNull(); }
|
||||
|
||||
void setQuery( const Tomahawk::query_ptr& q );
|
||||
const Tomahawk::query_ptr& query() const;
|
||||
|
||||
// I wish Qt did this for me once i specified the Q_PROPERTIES:
|
||||
void setQueryVariant( const QVariant& v );
|
||||
QVariant queryVariant() const;
|
||||
|
||||
|
@@ -29,6 +29,7 @@ using namespace Tomahawk;
|
||||
PlaylistInterface::PlaylistInterface ()
|
||||
: QObject()
|
||||
, m_latchMode( PlaylistModes::StayOnSong )
|
||||
, m_finished( false )
|
||||
{
|
||||
m_id = uuid();
|
||||
}
|
||||
|
@@ -40,6 +40,7 @@ public:
|
||||
const QString id() { return m_id; }
|
||||
|
||||
virtual QList< Tomahawk::query_ptr > tracks() = 0;
|
||||
virtual bool isFinished() const { return m_finished; }
|
||||
|
||||
virtual int unfilteredTrackCount() const = 0;
|
||||
virtual int trackCount() const = 0;
|
||||
@@ -91,7 +92,8 @@ protected:
|
||||
virtual QList<Tomahawk::query_ptr> filterTracks( const QList<Tomahawk::query_ptr>& queries );
|
||||
|
||||
PlaylistModes::LatchMode m_latchMode;
|
||||
|
||||
bool m_finished;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY( PlaylistInterface )
|
||||
|
||||
|
@@ -82,6 +82,9 @@ PlaybackLog::PlaybackLog( const PlaybackLog& other )
|
||||
query_ptr
|
||||
Query::get( const QString& artist, const QString& track, const QString& album, const QID& qid, bool autoResolve )
|
||||
{
|
||||
if ( artist.trimmed().isEmpty() || track.trimmed().isEmpty() )
|
||||
return query_ptr();
|
||||
|
||||
if ( qid.isEmpty() )
|
||||
autoResolve = false;
|
||||
|
||||
@@ -98,6 +101,8 @@ Query::get( const QString& artist, const QString& track, const QString& album, c
|
||||
query_ptr
|
||||
Query::get( const QString& query, const QID& qid )
|
||||
{
|
||||
Q_ASSERT( !query.trimmed().isEmpty() );
|
||||
|
||||
query_ptr q = query_ptr( new Query( query, qid ), &QObject::deleteLater );
|
||||
q->setWeakRef( q.toWeakRef() );
|
||||
|
||||
@@ -170,14 +175,14 @@ Query::updateSortNames()
|
||||
if ( isFullTextQuery() )
|
||||
{
|
||||
m_artistSortname = DatabaseImpl::sortname( m_fullTextQuery, true );
|
||||
m_composerSortName = DatabaseImpl::sortname( m_composer, true );
|
||||
m_composerSortname = DatabaseImpl::sortname( m_composer, true );
|
||||
m_albumSortname = DatabaseImpl::sortname( m_fullTextQuery );
|
||||
m_trackSortname = m_albumSortname;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_artistSortname = DatabaseImpl::sortname( m_artist, true );
|
||||
m_composerSortName = DatabaseImpl::sortname( m_composer, true );
|
||||
m_composerSortname = DatabaseImpl::sortname( m_composer, true );
|
||||
m_albumSortname = DatabaseImpl::sortname( m_album );
|
||||
m_trackSortname = DatabaseImpl::sortname( m_track );
|
||||
}
|
||||
@@ -189,7 +194,7 @@ Query::displayQuery() const
|
||||
{
|
||||
if ( !results().isEmpty() )
|
||||
return results().first()->toQuery();
|
||||
|
||||
|
||||
return m_ownRef.toStrongRef();
|
||||
}
|
||||
|
||||
@@ -493,13 +498,13 @@ Query::howSimilar( const Tomahawk::result_ptr& r )
|
||||
{
|
||||
// result values
|
||||
const QString rArtistname = r->artist()->sortname();
|
||||
const QString rAlbumname = DatabaseImpl::sortname( r->album()->name() );
|
||||
const QString rAlbumname = r->album()->sortname();
|
||||
const QString rTrackname = DatabaseImpl::sortname( r->track() );
|
||||
|
||||
// normal edit distance
|
||||
int artdist = levenshtein( m_artistSortname, rArtistname );
|
||||
int albdist = levenshtein( m_albumSortname, rAlbumname );
|
||||
int trkdist = levenshtein( m_trackSortname, rTrackname );
|
||||
int artdist = TomahawkUtils::levenshtein( m_artistSortname, rArtistname );
|
||||
int albdist = TomahawkUtils::levenshtein( m_albumSortname, rAlbumname );
|
||||
int trkdist = TomahawkUtils::levenshtein( m_trackSortname, rTrackname );
|
||||
|
||||
// max length of name
|
||||
int mlart = qMax( m_artistSortname.length(), rArtistname.length() );
|
||||
@@ -516,7 +521,7 @@ Query::howSimilar( const Tomahawk::result_ptr& r )
|
||||
const QString artistTrackname = DatabaseImpl::sortname( fullTextQuery() );
|
||||
const QString rArtistTrackname = DatabaseImpl::sortname( r->artist()->name() + " " + r->track() );
|
||||
|
||||
int atrdist = levenshtein( artistTrackname, rArtistTrackname );
|
||||
int atrdist = TomahawkUtils::levenshtein( artistTrackname, rArtistTrackname );
|
||||
int mlatr = qMax( artistTrackname.length(), rArtistTrackname.length() );
|
||||
float dcatr = (float)( mlatr - atrdist ) / mlatr;
|
||||
|
||||
@@ -566,7 +571,7 @@ Query::playbackHistory( const Tomahawk::source_ptr& source ) const
|
||||
history << log;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return history;
|
||||
}
|
||||
|
||||
@@ -588,7 +593,7 @@ Query::playbackCount( const source_ptr& source )
|
||||
if ( source.isNull() || log.source == source )
|
||||
count++;
|
||||
}
|
||||
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -596,6 +601,9 @@ Query::playbackCount( const source_ptr& source )
|
||||
void
|
||||
Query::loadSocialActions()
|
||||
{
|
||||
if ( m_socialActionsLoaded )
|
||||
return;
|
||||
|
||||
m_socialActionsLoaded = true;
|
||||
query_ptr q = m_ownRef.toStrongRef();
|
||||
|
||||
@@ -670,12 +678,12 @@ Query::setLoved( bool loved )
|
||||
trackInfo["album"] = album();
|
||||
|
||||
loveInfo[ "trackinfo" ] = QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( trackInfo );
|
||||
|
||||
|
||||
Tomahawk::InfoSystem::InfoPushData pushData ( id(),
|
||||
( loved ? Tomahawk::InfoSystem::InfoLove : Tomahawk::InfoSystem::InfoUnLove ),
|
||||
loveInfo,
|
||||
Tomahawk::InfoSystem::PushShortUrlFlag );
|
||||
|
||||
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( pushData );
|
||||
|
||||
DatabaseCommand_SocialAction* cmd = new DatabaseCommand_SocialAction( q, QString( "Love" ), loved ? QString( "true" ) : QString( "false" ) );
|
||||
@@ -783,10 +791,10 @@ Query::coverLoaded() const
|
||||
{
|
||||
if ( m_albumPtr.isNull() )
|
||||
return false;
|
||||
|
||||
|
||||
if ( m_albumPtr->coverLoaded() && !m_albumPtr->cover( QSize( 0, 0 ) ).isNull() )
|
||||
return true;
|
||||
|
||||
|
||||
return m_artistPtr->coverLoaded();
|
||||
}
|
||||
|
||||
@@ -809,7 +817,7 @@ Query::similarTracks() const
|
||||
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( trackInfo );
|
||||
requestData.type = Tomahawk::InfoSystem::InfoTrackSimilars;
|
||||
requestData.requestId = TomahawkUtils::infosystemRequestId();
|
||||
|
||||
|
||||
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
|
||||
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
|
||||
@@ -821,7 +829,7 @@ Query::similarTracks() const
|
||||
m_infoJobs++;
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
|
||||
}
|
||||
|
||||
|
||||
return m_similarTracks;
|
||||
}
|
||||
|
||||
@@ -842,7 +850,7 @@ Query::lyrics() const
|
||||
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( trackInfo );
|
||||
requestData.type = Tomahawk::InfoSystem::InfoTrackLyrics;
|
||||
requestData.requestId = TomahawkUtils::infosystemRequestId();
|
||||
|
||||
|
||||
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
|
||||
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
|
||||
@@ -854,7 +862,7 @@ Query::lyrics() const
|
||||
m_infoJobs++;
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
|
||||
}
|
||||
|
||||
|
||||
return m_lyrics;
|
||||
}
|
||||
|
||||
@@ -871,7 +879,7 @@ Query::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVaria
|
||||
case InfoSystem::InfoTrackLyrics:
|
||||
{
|
||||
m_lyrics = output.value< QVariant >().toString().split( "\n" );
|
||||
|
||||
|
||||
m_lyricsLoaded = true;
|
||||
emit lyricsLoaded();
|
||||
break;
|
||||
@@ -887,7 +895,7 @@ Query::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVaria
|
||||
m_similarTracks << Query::get( artists.at( i ), tracks.at( i ), QString(), uuid(), false );
|
||||
}
|
||||
Pipeline::instance()->resolve( m_similarTracks );
|
||||
|
||||
|
||||
m_simTracksLoaded = true;
|
||||
emit similarTracksLoaded();
|
||||
|
||||
@@ -917,83 +925,3 @@ Query::infoSystemFinished( QString target )
|
||||
|
||||
emit updated();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Query::levenshtein( const QString& source, const QString& target )
|
||||
{
|
||||
// Step 1
|
||||
const int n = source.length();
|
||||
const int m = target.length();
|
||||
|
||||
if ( n == 0 )
|
||||
return m;
|
||||
if ( m == 0 )
|
||||
return n;
|
||||
|
||||
// Good form to declare a TYPEDEF
|
||||
typedef QVector< QVector<int> > Tmatrix;
|
||||
Tmatrix matrix;
|
||||
matrix.resize( n + 1 );
|
||||
|
||||
// Size the vectors in the 2.nd dimension. Unfortunately C++ doesn't
|
||||
// allow for allocation on declaration of 2.nd dimension of vec of vec
|
||||
for ( int i = 0; i <= n; i++ )
|
||||
{
|
||||
QVector<int> tmp;
|
||||
tmp.resize( m + 1 );
|
||||
matrix.insert( i, tmp );
|
||||
}
|
||||
|
||||
// Step 2
|
||||
for ( int i = 0; i <= n; i++ )
|
||||
matrix[i][0] = i;
|
||||
for ( int j = 0; j <= m; j++ )
|
||||
matrix[0][j] = j;
|
||||
|
||||
// Step 3
|
||||
for ( int i = 1; i <= n; i++ )
|
||||
{
|
||||
const QChar s_i = source[i - 1];
|
||||
|
||||
// Step 4
|
||||
for ( int j = 1; j <= m; j++ )
|
||||
{
|
||||
const QChar t_j = target[j - 1];
|
||||
|
||||
// Step 5
|
||||
int cost;
|
||||
if ( s_i == t_j )
|
||||
cost = 0;
|
||||
else
|
||||
cost = 1;
|
||||
|
||||
// Step 6
|
||||
const int above = matrix[i - 1][j];
|
||||
const int left = matrix[i][j - 1];
|
||||
const int diag = matrix[i - 1][j - 1];
|
||||
|
||||
int cell = ( ( ( left + 1 ) > ( diag + cost ) ) ? diag + cost : left + 1 );
|
||||
if ( above + 1 < cell )
|
||||
cell = above + 1;
|
||||
|
||||
// Step 6A: Cover transposition, in addition to deletion,
|
||||
// insertion and substitution. This step is taken from:
|
||||
// Berghel, Hal ; Roach, David : "An Extension of Ukkonen's
|
||||
// Enhanced Dynamic Programming ASM Algorithm"
|
||||
// (http://www.acm.org/~hlb/publications/asm/asm.html)
|
||||
if ( i > 2 && j > 2 )
|
||||
{
|
||||
int trans = matrix[i - 2][j - 2] + 1;
|
||||
|
||||
if ( source[ i - 2 ] != t_j ) trans++;
|
||||
if ( s_i != target[ j - 2 ] ) trans++;
|
||||
if ( cell > trans ) cell = trans;
|
||||
}
|
||||
matrix[i][j] = cell;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 7
|
||||
return matrix[n][m];
|
||||
}
|
||||
|
@@ -97,7 +97,7 @@ public:
|
||||
QID id() const;
|
||||
|
||||
/// sorter for list of results
|
||||
static bool resultSorter( const result_ptr &left, const result_ptr& right );
|
||||
static bool resultSorter( const result_ptr& left, const result_ptr& right );
|
||||
|
||||
/// true when a perfect result has been found (score of 1.0)
|
||||
bool solved() const { return m_solved; }
|
||||
@@ -129,6 +129,7 @@ public:
|
||||
|
||||
QString resultHint() const { return m_resultHint; }
|
||||
QString artistSortname() const { return m_artistSortname; }
|
||||
QString composerSortname() const { return m_composerSortname; }
|
||||
QString albumSortname() const { return m_albumSortname; }
|
||||
QString trackSortname() const { return m_trackSortname; }
|
||||
|
||||
@@ -139,7 +140,7 @@ public:
|
||||
int duration() const { return m_duration; }
|
||||
unsigned int albumpos() const { return m_albumpos; }
|
||||
unsigned int discnumber() const { return m_discnumber; }
|
||||
|
||||
|
||||
query_ptr displayQuery() const;
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
@@ -220,7 +221,6 @@ private:
|
||||
void checkResults();
|
||||
|
||||
void updateSortNames();
|
||||
static int levenshtein( const QString& source, const QString& target );
|
||||
|
||||
void parseSocialActions();
|
||||
|
||||
@@ -233,7 +233,7 @@ private:
|
||||
mutable QID m_qid;
|
||||
|
||||
QString m_artistSortname;
|
||||
QString m_composerSortName;
|
||||
QString m_composerSortname;
|
||||
QString m_albumSortname;
|
||||
QString m_trackSortname;
|
||||
|
||||
@@ -266,10 +266,10 @@ private:
|
||||
|
||||
bool m_simTracksLoaded;
|
||||
QList<Tomahawk::query_ptr> m_similarTracks;
|
||||
|
||||
|
||||
bool m_lyricsLoaded;
|
||||
QStringList m_lyrics;
|
||||
|
||||
|
||||
mutable int m_infoJobs;
|
||||
};
|
||||
|
||||
|
@@ -305,7 +305,7 @@ ViewManager::show( const Tomahawk::collection_ptr& collection )
|
||||
view = new TreeView();
|
||||
TreeModel* model = new TreeModel();
|
||||
view->setTreeModel( model );
|
||||
|
||||
|
||||
if ( collection && collection->source()->isLocal() )
|
||||
view->setEmptyTip( tr( "After you have scanned your music collection you will find your tracks right here." ) );
|
||||
else
|
||||
@@ -483,7 +483,7 @@ ViewManager::showRecentPlaysPage()
|
||||
{
|
||||
PlaylistView* pv = new PlaylistView( m_widget );
|
||||
|
||||
RecentlyPlayedModel* raModel = new RecentlyPlayedModel( source_ptr(), pv );
|
||||
RecentlyPlayedModel* raModel = new RecentlyPlayedModel( pv );
|
||||
raModel->setTitle( tr( "Recently Played Tracks" ) );
|
||||
raModel->setDescription( tr( "Recently played tracks from all your friends" ) );
|
||||
raModel->setStyle( PlayableModel::Large );
|
||||
@@ -493,6 +493,7 @@ ViewManager::showRecentPlaysPage()
|
||||
pv->setItemDelegate( del );
|
||||
|
||||
pv->setPlaylistModel( raModel );
|
||||
raModel->setSource( source_ptr() );
|
||||
|
||||
m_recentPlaysWidget = pv;
|
||||
}
|
||||
@@ -570,7 +571,7 @@ ViewManager::historyBack()
|
||||
return;
|
||||
|
||||
ViewPage* page = m_pageHistoryBack.takeLast();
|
||||
|
||||
|
||||
if ( m_currentPage )
|
||||
{
|
||||
m_pageHistoryFwd << m_currentPage;
|
||||
@@ -589,7 +590,7 @@ ViewManager::historyForward()
|
||||
return;
|
||||
|
||||
ViewPage* page = m_pageHistoryFwd.takeLast();
|
||||
|
||||
|
||||
if ( m_currentPage )
|
||||
{
|
||||
m_pageHistoryBack << m_currentPage;
|
||||
@@ -615,14 +616,7 @@ ViewManager::destroyPage( ViewPage* page )
|
||||
return;
|
||||
|
||||
tDebug() << Q_FUNC_INFO << "Deleting page:" << page->title();
|
||||
if ( m_currentPage == page )
|
||||
{
|
||||
delete page;
|
||||
m_currentPage = 0;
|
||||
|
||||
historyBack();
|
||||
}
|
||||
else if ( historyPages().contains( page ) )
|
||||
if ( historyPages().contains( page ) )
|
||||
{
|
||||
m_pageHistoryBack.removeAll( page );
|
||||
m_pageHistoryFwd.removeAll( page );
|
||||
@@ -632,6 +626,13 @@ ViewManager::destroyPage( ViewPage* page )
|
||||
|
||||
delete page;
|
||||
}
|
||||
|
||||
if ( m_currentPage == page )
|
||||
{
|
||||
m_currentPage = 0;
|
||||
|
||||
historyBack();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -640,6 +641,8 @@ ViewManager::setPage( ViewPage* page, bool trackHistory )
|
||||
{
|
||||
if ( !page )
|
||||
return;
|
||||
if ( page == m_currentPage )
|
||||
return;
|
||||
|
||||
// save the old playlist shuffle state in config before we change playlists
|
||||
saveCurrentPlaylistSettings();
|
||||
@@ -865,7 +868,7 @@ ViewManager::onWidgetDestroyed( QWidget* widget )
|
||||
{
|
||||
m_dynamicWidgets.remove( dynamicPlaylistForInterface( page->playlistInterface() ) );
|
||||
}
|
||||
|
||||
|
||||
m_pageHistoryBack.removeAll( page );
|
||||
m_pageHistoryFwd.removeAll( page );
|
||||
}
|
||||
|
@@ -132,7 +132,7 @@ LastFmConfig::onHistoryLoaded()
|
||||
uint total = 0;
|
||||
bool finished = false;
|
||||
QNetworkReply* reply = qobject_cast< QNetworkReply* >( sender() );
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
lastfm::XmlQuery lfm;
|
||||
@@ -140,24 +140,27 @@ LastFmConfig::onHistoryLoaded()
|
||||
|
||||
foreach ( lastfm::XmlQuery e, lfm.children( "track" ) )
|
||||
{
|
||||
// tDebug() << "Found:" << e["artist"].text() << e["name"].text() << e["date"].attribute( "uts" ).toUInt();
|
||||
Tomahawk::query_ptr query = Query::get( e["artist"].text(), e["name"].text(), QString(), QString(), false );
|
||||
// tDebug() << "Found:" << e.children( "artist" ).first()["name"].text() << e["name"].text() << e["date"].attribute( "uts" ).toUInt();
|
||||
Tomahawk::query_ptr query = Query::get( e.children( "artist" ).first()["name"].text(), e["name"].text(), QString(), QString(), false );
|
||||
if ( query.isNull() )
|
||||
continue;
|
||||
|
||||
m_lastTimeStamp = e["date"].attribute( "uts" ).toUInt();
|
||||
|
||||
|
||||
DatabaseCommand_LogPlayback* cmd = new DatabaseCommand_LogPlayback( query, DatabaseCommand_LogPlayback::Finished, m_lastTimeStamp );
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>(cmd) );
|
||||
}
|
||||
|
||||
|
||||
if ( !lfm.children( "recenttracks" ).isEmpty() )
|
||||
{
|
||||
lastfm::XmlQuery stats = lfm.children( "recenttracks" ).first();
|
||||
|
||||
|
||||
uint page = stats.attribute( "page" ).toUInt();
|
||||
total = stats.attribute( "totalPages" ).toUInt();
|
||||
|
||||
|
||||
m_ui->progressBar->setMaximum( total );
|
||||
m_ui->progressBar->setValue( page );
|
||||
|
||||
|
||||
if ( page < total )
|
||||
{
|
||||
m_page = page + 1;
|
||||
@@ -174,7 +177,7 @@ LastFmConfig::onHistoryLoaded()
|
||||
tDebug() << "XmlQuery error:" << e.message();
|
||||
finished = true;
|
||||
}
|
||||
|
||||
|
||||
if ( finished )
|
||||
{
|
||||
if ( m_page != total )
|
||||
|
@@ -212,7 +212,7 @@ LastFmInfoPlugin::scrobble()
|
||||
return;
|
||||
|
||||
tLog() << Q_FUNC_INFO << "Scrobbling now:" << m_track.toString();
|
||||
|
||||
|
||||
// FIXME: workaround for the duration-less dilandau (and others) tracks
|
||||
if ( m_track.duration() == 0 )
|
||||
m_track.setDuration( 31 );
|
||||
@@ -525,7 +525,7 @@ LastFmInfoPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::In
|
||||
imgurl.addEncodedQueryItem( "artist", QUrl::toPercentEncoding( artistName, "", "+" ) );
|
||||
imgurl.addEncodedQueryItem( "album", QUrl::toPercentEncoding( albumName, "", "+" ) );
|
||||
imgurl.addQueryItem( "autocorrect", QString::number( 1 ) );
|
||||
imgurl.addQueryItem( "size", "largesquare" );
|
||||
imgurl.addQueryItem( "size", "large" );
|
||||
imgurl.addQueryItem( "api_key", "7a90f6672a04b809ee309af169f34b8b" );
|
||||
|
||||
QNetworkRequest req( imgurl );
|
||||
|
@@ -121,7 +121,6 @@ SpotifyAccount::init()
|
||||
void
|
||||
SpotifyAccount::delayedInit()
|
||||
{
|
||||
|
||||
connect( AtticaManager::instance(), SIGNAL( resolverInstalled( QString ) ), this, SLOT( resolverInstalled( QString ) ) );
|
||||
|
||||
const Attica::Content res = AtticaManager::instance()->resolverForId( s_resolverId );
|
||||
@@ -131,6 +130,11 @@ SpotifyAccount::delayedInit()
|
||||
if ( !checkForResolver() && state != AtticaManager::Uninstalled )
|
||||
{
|
||||
// If the user manually deleted the resolver, mark it as uninstalled, so we re-fetch for the user
|
||||
QVariantHash conf = configuration();
|
||||
conf.remove( "path" );
|
||||
setConfiguration( conf );
|
||||
sync();
|
||||
|
||||
AtticaManager::instance()->uninstallResolver( res );
|
||||
}
|
||||
else if ( state == AtticaManager::Installed || !path.isEmpty() )
|
||||
@@ -138,9 +142,15 @@ SpotifyAccount::delayedInit()
|
||||
if ( !path.isEmpty() )
|
||||
{
|
||||
QFileInfo info( path );
|
||||
// Resolver was deleted, so abort.
|
||||
// Resolver was deleted, so abort and remove our manual override, as it's no longer valid
|
||||
if ( !info.exists() )
|
||||
{
|
||||
QVariantHash conf = configuration();
|
||||
conf.remove( "path" );
|
||||
setConfiguration( conf );
|
||||
sync();
|
||||
return;
|
||||
}
|
||||
}
|
||||
hookupResolver();
|
||||
}
|
||||
@@ -165,6 +175,21 @@ SpotifyAccount::hookupResolver()
|
||||
}
|
||||
|
||||
qDebug() << "Starting spotify resolver with path:" << path;
|
||||
if ( !m_spotifyResolver.isNull() )
|
||||
{
|
||||
delete m_spotifyResolver.data();
|
||||
}
|
||||
|
||||
if ( !QFile::exists( path ) )
|
||||
{
|
||||
qWarning() << "Asked to hook up spotify resolver but it doesn't exist, ignoring";
|
||||
return;
|
||||
}
|
||||
|
||||
// HACK
|
||||
// Since the resolver in 0.4.x used an incompatible version of kdsingleappguard, we can't auto-kill old resolvers on the
|
||||
// 0.4.x->0.5.x upgrade. So we do it manually for a while
|
||||
killExistingResolvers();
|
||||
m_spotifyResolver = QWeakPointer< ScriptResolver >( qobject_cast< ScriptResolver* >( Pipeline::instance()->addScriptResolver( path ) ) );
|
||||
|
||||
connect( m_spotifyResolver.data(), SIGNAL( changed() ), this, SLOT( resolverChanged() ) );
|
||||
@@ -182,6 +207,20 @@ SpotifyAccount::hookupResolver()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccount::killExistingResolvers()
|
||||
{
|
||||
QProcess p;
|
||||
#if defined(Q_OS_UNIX)
|
||||
const int ret = p.execute( "killall -9 spotify_tomahawkresolver" );
|
||||
qDebug() << "Tried to killall -9 spotify_tomahawkresolver with return code:" << ret;
|
||||
#elif defined(Q_OS_WIN)
|
||||
const int ret = p.execute( "taskkill.exe /F /im spotify_tomahawkresolver.exe" );
|
||||
qDebug() << "Tried to taskkill.exe /F /im spotify_tomahawkresolver.exe with return code:" << ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SpotifyAccount::checkForResolver()
|
||||
{
|
||||
@@ -228,13 +267,18 @@ SpotifyAccount::authenticate()
|
||||
const AtticaManager::ResolverState state = AtticaManager::instance()->resolverState( res );
|
||||
|
||||
qDebug() << "Spotify account authenticating...";
|
||||
|
||||
const QString path = configuration().value( "path" ).toString();
|
||||
const QFileInfo info( path );
|
||||
const bool manualResolverRemoved = !path.isEmpty() && !info.exists();
|
||||
|
||||
if ( m_spotifyResolver.isNull() && state == AtticaManager::Installed )
|
||||
{
|
||||
// We don;t have the resolver but it has been installed via attica already, so lets just turn it on
|
||||
qDebug() << "No valid spotify resolver running, but attica reports it is installed, so start it up";
|
||||
hookupResolver();
|
||||
}
|
||||
else if ( m_spotifyResolver.isNull() )
|
||||
else if ( m_spotifyResolver.isNull() || manualResolverRemoved )
|
||||
{
|
||||
qDebug() << "Got null resolver but asked to authenticate, so installing if we have one from attica:" << res.isValid() << res.id();
|
||||
if ( res.isValid() && !res.id().isEmpty() )
|
||||
@@ -318,6 +362,11 @@ SpotifyAccount::setManualResolverPath( const QString &resolverPath )
|
||||
setConfiguration( conf );
|
||||
sync();
|
||||
|
||||
// uninstall
|
||||
const Attica::Content res = AtticaManager::instance()->resolverForId( s_resolverId );
|
||||
if ( AtticaManager::instance()->resolverState( res ) != AtticaManager::Uninstalled )
|
||||
AtticaManager::instance()->uninstallResolver( res );
|
||||
|
||||
m_preventEnabling = false;
|
||||
|
||||
if ( !m_spotifyResolver.isNull() )
|
||||
|
@@ -126,6 +126,7 @@ private:
|
||||
void init();
|
||||
bool checkForResolver();
|
||||
void hookupResolver();
|
||||
void killExistingResolvers();
|
||||
|
||||
void loadPlaylists();
|
||||
void clearUser( bool permanentlyDelete = false );
|
||||
|
@@ -674,6 +674,9 @@ SpotifyPlaylistUpdater::variantToQueries( const QVariantList& list )
|
||||
{
|
||||
QVariantMap trackMap = blob.toMap();
|
||||
const query_ptr q = Query::get( trackMap.value( "artist" ).toString(), trackMap.value( "track" ).toString(), trackMap.value( "album" ).toString(), uuid(), false );
|
||||
if ( q.isNull() )
|
||||
continue;
|
||||
|
||||
if ( trackMap.contains( "id" ) )
|
||||
q->setProperty( "annotation", trackMap.value( "id" ) );
|
||||
|
||||
|
@@ -37,6 +37,9 @@
|
||||
#include "infosystem/InfoSystem.h"
|
||||
#include "Album.h"
|
||||
#include "Pipeline.h"
|
||||
#include "jobview/JobStatusView.h"
|
||||
#include "jobview/JobStatusModel.h"
|
||||
#include "jobview/ErrorStatusMessage.h"
|
||||
|
||||
#include "utils/Logger.h"
|
||||
|
||||
@@ -94,12 +97,9 @@ AudioEngine::AudioEngine()
|
||||
AudioEngine::~AudioEngine()
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
|
||||
|
||||
m_mediaObject->stop();
|
||||
TomahawkSettings::instance()->setVolume( volume() );
|
||||
|
||||
delete m_audioOutput;
|
||||
delete m_mediaObject;
|
||||
}
|
||||
|
||||
|
||||
@@ -604,8 +604,17 @@ AudioEngine::playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk:
|
||||
{
|
||||
if ( query->resolvingFinished() )
|
||||
{
|
||||
if ( query->numResults() )
|
||||
if ( query->numResults() && query->results().first()->isOnline() )
|
||||
{
|
||||
playItem( playlist, query->results().first() );
|
||||
return;
|
||||
}
|
||||
|
||||
JobStatusView::instance()->model()->addJob(
|
||||
new ErrorStatusMessage( tr( "Sorry, Tomahawk couldn't find the track '%1' by %2" ).arg( query->track() ).arg( query->artist() ), 15 ) );
|
||||
|
||||
if ( isStopped() )
|
||||
emit stopped(); // we do this so the original caller knows we couldn't find this track
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -621,9 +630,18 @@ void
|
||||
AudioEngine::playItem( const Tomahawk::artist_ptr& artist )
|
||||
{
|
||||
playlistinterface_ptr pli = artist->playlistInterface( Mixed );
|
||||
if ( pli->trackCount() )
|
||||
if ( pli->isFinished() )
|
||||
{
|
||||
playItem( pli, pli->tracks().first() );
|
||||
if ( !pli->tracks().count() )
|
||||
{
|
||||
JobStatusView::instance()->model()->addJob(
|
||||
new ErrorStatusMessage( tr( "Sorry, Tomahawk couldn't find the artist '%1'" ).arg( artist->name() ), 15 ) );
|
||||
|
||||
if ( isStopped() )
|
||||
emit stopped(); // we do this so the original caller knows we couldn't find this track
|
||||
}
|
||||
else
|
||||
playItem( pli, pli->tracks().first() );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -638,9 +656,18 @@ void
|
||||
AudioEngine::playItem( const Tomahawk::album_ptr& album )
|
||||
{
|
||||
playlistinterface_ptr pli = album->playlistInterface( Mixed );
|
||||
if ( pli->trackCount() )
|
||||
if ( pli->isFinished() )
|
||||
{
|
||||
playItem( pli, pli->tracks().first() );
|
||||
if ( !pli->tracks().count() )
|
||||
{
|
||||
JobStatusView::instance()->model()->addJob(
|
||||
new ErrorStatusMessage( tr( "Sorry, Tomahawk couldn't find the album '%1' by %2" ).arg( album->name() ).arg( album->artist()->name() ), 15 ) );
|
||||
|
||||
if ( isStopped() )
|
||||
emit stopped(); // we do this so the original caller knows we couldn't find this track
|
||||
}
|
||||
else
|
||||
playItem( pli, pli->tracks().first() );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -734,7 +761,7 @@ AudioEngine::onStateChanged( Phonon::State newState, Phonon::State oldState )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( newState == Phonon::PausedState || newState == Phonon::PlayingState || newState == Phonon::ErrorState )
|
||||
{
|
||||
tDebug() << "Phonon state now:" << newState;
|
||||
@@ -860,10 +887,10 @@ AudioEngine::checkStateQueue()
|
||||
m_mediaObject->play();
|
||||
if ( paused )
|
||||
setVolume( m_volume );
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case Paused:
|
||||
{
|
||||
m_volume = volume();
|
||||
|
@@ -138,7 +138,7 @@ private slots:
|
||||
|
||||
void sendNowPlayingNotification( const Tomahawk::InfoSystem::InfoType type );
|
||||
void sendWaitingNotification() const;
|
||||
|
||||
|
||||
void queueStateSafety();
|
||||
|
||||
private:
|
||||
|
@@ -100,7 +100,7 @@ TopTracksContext::onTracksFound( const QList<Tomahawk::query_ptr>& queries, Mode
|
||||
{
|
||||
Q_UNUSED( mode );
|
||||
|
||||
m_topHitsModel->append( queries );
|
||||
m_topHitsModel->appendQueries( queries );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -62,10 +62,13 @@ DatabaseCommand_DeleteDynamicPlaylist::postCommitHook()
|
||||
if( playlist.isNull() )
|
||||
playlist = source()->collection()->station( m_playlistguid );
|
||||
|
||||
qDebug() << "Just tried to load playlist for deletion:" << m_playlistguid << "Did we get a null one?" << playlist.isNull() << "is it a station?" << (playlist->mode() == OnDemand);
|
||||
tLog( LOGVERBOSE ) << "Just tried to load playlist for deletion:" << m_playlistguid << "Did we get a null one?" << playlist.isNull();
|
||||
Q_ASSERT( !playlist.isNull() );
|
||||
|
||||
playlist->reportDeleted( playlist );
|
||||
if ( !playlist.isNull() )
|
||||
{
|
||||
tLog( LOGVERBOSE ) << "is it a station?" << ( playlist->mode() == OnDemand );
|
||||
playlist->reportDeleted( playlist );
|
||||
}
|
||||
|
||||
if( source()->isLocal() )
|
||||
Servent::instance()->triggerDBSync();
|
||||
|
@@ -91,6 +91,8 @@ DatabaseCommand_GenericSelect::exec( DatabaseImpl* dbi )
|
||||
artist = query.value( 1 ).toString();
|
||||
|
||||
qry = Tomahawk::Query::get( artist, track, QString() );
|
||||
if ( qry.isNull() )
|
||||
continue;
|
||||
}
|
||||
else if ( m_queryType == Artist )
|
||||
{
|
||||
|
@@ -77,6 +77,9 @@ DatabaseCommand_LoadPlaylistEntries::generateEntries( DatabaseImpl* dbi )
|
||||
e->setResultHint( query.value( 8 ).toString() );
|
||||
|
||||
Tomahawk::query_ptr q = Tomahawk::Query::get( query.value( 2 ).toString(), query.value( 1 ).toString(), query.value( 3 ).toString() );
|
||||
if ( q.isNull() )
|
||||
continue;
|
||||
|
||||
q->setResultHint( query.value( 8 ).toString() );
|
||||
q->setProperty( "annotation", e->annotation() );
|
||||
e->setQuery( q );
|
||||
|
@@ -111,11 +111,18 @@ DatabaseCommand_SetDynamicPlaylistRevision::postCommitHook()
|
||||
if( playlist.isNull() ) // if it's neither an auto or station, it must not be auto-loaded, so we MUST have been told about it directly
|
||||
rawPl = m_playlist;
|
||||
|
||||
if ( rawPl == 0 )
|
||||
{
|
||||
tLog() <<"Got null playlist with guid:" << playlistguid() << "from source and collection:" << source()->friendlyName() << source()->collection()->name() << "and mode is static?:" << (m_mode == Static);
|
||||
Q_ASSERT( false );
|
||||
return;
|
||||
}
|
||||
|
||||
// workaround a bug in pre-0.1.0 tomahawks. they created dynamic playlists in OnDemand mode *always*, and then set the mode to the real one.
|
||||
// now that we separate them, if we get them as one and then get a changed mode, the playlist ends up in the wrong bucket in Collection.
|
||||
// so here we fix it if we have to.
|
||||
// HACK
|
||||
tDebug() << "Does this need the 0.3->0.1 playlist category hack fix?" << ( rawPl->mode() == Static && source()->collection()->autoPlaylist( playlistguid() ).isNull() )
|
||||
tDebug() << "Does this need the 0.3->0.1 playlist category hack fix?" << ( rawPl->mode() == Static && source()->collection()->autoPlaylist( playlistguid() ).isNull() )
|
||||
<< ( rawPl->mode() == OnDemand && source()->collection()->station( playlistguid() ).isNull() )
|
||||
<< rawPl->mode() << source()->collection()->autoPlaylist( playlistguid() ).isNull() << source()->collection()->station( playlistguid() ).isNull();
|
||||
if( rawPl->mode() == Static && source()->collection()->autoPlaylist( playlistguid() ).isNull() ) // should be here
|
||||
@@ -123,13 +130,7 @@ DatabaseCommand_SetDynamicPlaylistRevision::postCommitHook()
|
||||
else if ( rawPl->mode() == OnDemand && source()->collection()->station( playlistguid() ).isNull() ) // should be here
|
||||
source()->collection()->moveAutoToStation( playlistguid() );
|
||||
|
||||
if ( rawPl == 0 )
|
||||
{
|
||||
tLog() <<"Got null playlist with guid:" << playlistguid() << "from source and collection:" << source()->friendlyName() << source()->collection()->name() << "and mode is static?:" << (m_mode == Static);
|
||||
Q_ASSERT( false );
|
||||
return;
|
||||
}
|
||||
if ( !m_controlsV.isEmpty() && m_controls.isEmpty() )
|
||||
if ( !m_controlsV.isEmpty() && m_controls.isEmpty() )
|
||||
{
|
||||
QList<QVariantMap> controlMap;
|
||||
foreach( const QVariant& v, m_controlsV )
|
||||
|
@@ -80,7 +80,6 @@ DatabaseCommand_SetPlaylistRevision::DatabaseCommand_SetPlaylistRevision(
|
||||
tmp << s;
|
||||
|
||||
setOrderedguids( tmp );
|
||||
|
||||
setPlaylistguid( playlistguid );
|
||||
}
|
||||
|
||||
@@ -100,7 +99,6 @@ DatabaseCommand_SetPlaylistRevision::postCommitHook()
|
||||
playlist_ptr playlist = source()->collection()->playlist( m_playlistguid );
|
||||
if ( playlist.isNull() )
|
||||
{
|
||||
qDebug() << m_playlistguid;
|
||||
Q_ASSERT( !playlist.isNull() );
|
||||
return;
|
||||
}
|
||||
@@ -150,7 +148,9 @@ DatabaseCommand_SetPlaylistRevision::exec( DatabaseImpl* lib )
|
||||
|
||||
foreach( const plentry_ptr& e, m_entries )
|
||||
{
|
||||
if ( e->query()->results().isEmpty() )
|
||||
if ( !e->isValid() )
|
||||
continue;
|
||||
if ( !e->query()->numResults() )
|
||||
continue;
|
||||
|
||||
adde.bindValue( 0, e->query()->results().first()->url() );
|
||||
@@ -167,6 +167,9 @@ DatabaseCommand_SetPlaylistRevision::exec( DatabaseImpl* lib )
|
||||
|
||||
foreach( const plentry_ptr& e, m_entries )
|
||||
{
|
||||
if ( !e->isValid() )
|
||||
continue;
|
||||
|
||||
adde.bindValue( 0, e->query()->track() );
|
||||
adde.bindValue( 1, e->query()->artist() );
|
||||
adde.bindValue( 2, e->query()->album() );
|
||||
@@ -189,6 +192,9 @@ DatabaseCommand_SetPlaylistRevision::exec( DatabaseImpl* lib )
|
||||
qDebug() << "Num new playlist_items to add:" << m_addedentries.length();
|
||||
foreach( const plentry_ptr& e, m_addedentries )
|
||||
{
|
||||
if ( !e->isValid() )
|
||||
continue;
|
||||
|
||||
// qDebug() << "Adding:" << e->guid() << e->query()->track() << e->query()->artist();
|
||||
|
||||
m_addedmap.insert( e->guid(), e ); // needed in postcommithook
|
||||
|
@@ -77,9 +77,11 @@ public:
|
||||
m_addedentries.clear();
|
||||
foreach( const QVariant& v, vlist )
|
||||
{
|
||||
PlaylistEntry * pep = new PlaylistEntry;
|
||||
PlaylistEntry* pep = new PlaylistEntry;
|
||||
QJson::QObjectHelper::qvariant2qobject( v.toMap(), pep );
|
||||
m_addedentries << plentry_ptr(pep);
|
||||
|
||||
if ( pep->isValid() )
|
||||
m_addedentries << plentry_ptr( pep );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +90,9 @@ public:
|
||||
QVariantList vlist;
|
||||
foreach( const plentry_ptr& pe, m_addedentries )
|
||||
{
|
||||
if ( !pe->isValid() )
|
||||
continue;
|
||||
|
||||
QVariant v = QJson::QObjectHelper::qobject2qvariant( pe.data() );
|
||||
vlist << v;
|
||||
}
|
||||
|
@@ -328,9 +328,10 @@ DatabaseImpl::artistId( const QString& name_orig, bool autoCreate )
|
||||
int id = 0;
|
||||
QString sortname = DatabaseImpl::sortname( name_orig );
|
||||
|
||||
QString queryString = QString( "SELECT id FROM artist WHERE sortname = '%1'" ).arg( TomahawkSqlQuery::escape( sortname ) );
|
||||
TomahawkSqlQuery query = newquery();
|
||||
query.exec( queryString );
|
||||
query.prepare( "SELECT id FROM artist WHERE sortname = ?" );
|
||||
query.addBindValue( sortname );
|
||||
query.exec();
|
||||
if ( query.next() )
|
||||
{
|
||||
id = query.value( 0 ).toInt();
|
||||
|
@@ -83,7 +83,7 @@ FuzzyIndex::wipeIndex()
|
||||
endIndexing();
|
||||
|
||||
QTimer::singleShot( 0, this, SLOT( updateIndex() ) );
|
||||
|
||||
|
||||
return true; // FIXME
|
||||
}
|
||||
|
||||
@@ -189,8 +189,8 @@ FuzzyIndex::appendFields( const QMap< unsigned int, QMap< QString, QString > >&
|
||||
catch( CLuceneError& error )
|
||||
{
|
||||
tDebug() << "Caught CLucene error:" << error.what();
|
||||
|
||||
wipeIndex();
|
||||
|
||||
QTimer::singleShot( 0, this, SLOT( wipeIndex() ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,9 +282,9 @@ FuzzyIndex::search( const Tomahawk::query_ptr& query )
|
||||
}
|
||||
catch( CLuceneError& error )
|
||||
{
|
||||
tDebug() << "Caught CLucene error:" << error.what();
|
||||
|
||||
wipeIndex();
|
||||
tDebug() << "Caught CLucene error:" << error.what() << query->toString();
|
||||
|
||||
QTimer::singleShot( 0, this, SLOT( wipeIndex() ) );
|
||||
}
|
||||
|
||||
return resultsmap;
|
||||
@@ -338,8 +338,8 @@ FuzzyIndex::searchAlbum( const Tomahawk::query_ptr& query )
|
||||
catch( CLuceneError& error )
|
||||
{
|
||||
tDebug() << "Caught CLucene error:" << error.what();
|
||||
|
||||
wipeIndex();
|
||||
|
||||
QTimer::singleShot( 0, this, SLOT( wipeIndex() ) );
|
||||
}
|
||||
|
||||
return resultsmap;
|
||||
|
@@ -61,7 +61,7 @@ public:
|
||||
void beginIndexing();
|
||||
void endIndexing();
|
||||
void appendFields( const QMap< unsigned int, QMap< QString, QString > >& trackData );
|
||||
|
||||
|
||||
signals:
|
||||
void indexReady();
|
||||
|
||||
@@ -73,10 +73,9 @@ public slots:
|
||||
|
||||
private slots:
|
||||
void updateIndex();
|
||||
|
||||
private:
|
||||
bool wipeIndex();
|
||||
|
||||
private:
|
||||
QMutex m_mutex;
|
||||
QString m_lucenePath;
|
||||
|
||||
|
@@ -51,6 +51,14 @@ TomahawkSqlQuery::escape( QString identifier )
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TomahawkSqlQuery::prepare( const QString& query )
|
||||
{
|
||||
m_query = query;
|
||||
return QSqlQuery::prepare( query );
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TomahawkSqlQuery::exec( const QString& query )
|
||||
{
|
||||
@@ -76,6 +84,21 @@ TomahawkSqlQuery::exec()
|
||||
unsigned int retries = 0;
|
||||
while ( !QSqlQuery::exec() && ++retries < 10 )
|
||||
{
|
||||
if ( lastError().text().toLower().contains( "no query" ) ||
|
||||
lastError().text().toLower().contains( "parameter count mismatch" ) )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO << "Re-preparing query!";
|
||||
|
||||
QMap< QString, QVariant > bv = boundValues();
|
||||
prepare( m_query );
|
||||
|
||||
foreach ( const QString& key, bv.keys() )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO << "Rebinding key" << key << "with value" << bv.value( key );
|
||||
bindValue( key, bv.value( key ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( isBusyError( lastError() ) )
|
||||
retries = 0;
|
||||
|
||||
@@ -104,7 +127,7 @@ TomahawkSqlQuery::commitTransaction()
|
||||
#endif
|
||||
if ( log )
|
||||
tLog( LOGSQL ) << "TomahawkSqlQuery::commitTransaction running in thread " << QThread::currentThread();
|
||||
|
||||
|
||||
unsigned int retries = 0;
|
||||
while ( !m_db.commit() && ++retries < 10 )
|
||||
{
|
||||
@@ -114,7 +137,7 @@ TomahawkSqlQuery::commitTransaction()
|
||||
tDebug() << "INFO: Retrying failed commit:" << retries << lastError().text();
|
||||
TomahawkUtils::msleep( 10 );
|
||||
}
|
||||
|
||||
|
||||
return ( retries < 10 );
|
||||
}
|
||||
|
||||
@@ -136,5 +159,5 @@ TomahawkSqlQuery::isBusyError( const QSqlError& error ) const
|
||||
{
|
||||
const QString text = error.text().trimmed().toLower();
|
||||
|
||||
return ( text.contains( "no query" ) || text.contains( "locked" ) || text.contains( "busy" ) || text.isEmpty() );
|
||||
return ( text.contains( "locked" ) || text.contains( "busy" ) || text.isEmpty() );
|
||||
}
|
||||
|
@@ -35,17 +35,19 @@ public:
|
||||
|
||||
static QString escape( QString identifier );
|
||||
|
||||
bool prepare( const QString& query );
|
||||
bool exec( const QString& query );
|
||||
bool exec();
|
||||
|
||||
|
||||
bool commitTransaction();
|
||||
|
||||
private:
|
||||
bool isBusyError( const QSqlError& error ) const;
|
||||
|
||||
void showError();
|
||||
|
||||
|
||||
QSqlDatabase m_db;
|
||||
QString m_query;
|
||||
};
|
||||
|
||||
#endif // TOMAHAWKSQLQUERY_H
|
||||
|
@@ -132,10 +132,11 @@ InfoBar::setDescription( const QString& s )
|
||||
ui->descriptionLabel->setText( s );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoBar::setDescription( const artist_ptr& artist )
|
||||
{
|
||||
m_queryLabel->setQuery( Query::get( artist->name(), QString(), QString() ) );
|
||||
m_queryLabel->setArtist( artist );
|
||||
m_queryLabel->setExtraContentsMargins( 4, 0, 0, 0 );
|
||||
|
||||
if ( !m_queryLabel->isVisible() )
|
||||
@@ -151,16 +152,17 @@ InfoBar::setDescription( const artist_ptr& artist )
|
||||
}
|
||||
|
||||
void
|
||||
InfoBar::setDescription( const album_ptr& )
|
||||
InfoBar::setDescription( const album_ptr& )
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoBar::artistClicked()
|
||||
{
|
||||
if ( m_queryLabel && !m_queryLabel->query().isNull() )
|
||||
ViewManager::instance()->show( Artist::get( m_queryLabel->artist() ) );
|
||||
if ( m_queryLabel && !m_queryLabel->artist().isNull() )
|
||||
ViewManager::instance()->show( m_queryLabel->artist() );
|
||||
}
|
||||
|
||||
|
||||
@@ -212,7 +214,6 @@ InfoBar::setUpdaters( const QList<PlaylistUpdaterInterface*>& updaters )
|
||||
newUpdaterWidgets << updater->configurationWidget();
|
||||
}
|
||||
|
||||
|
||||
foreach ( QWidget* updaterWidget, m_updaterConfigurations )
|
||||
{
|
||||
updaterWidget->hide();
|
||||
|
@@ -26,8 +26,10 @@
|
||||
#include <QListView>
|
||||
|
||||
#define ROW_HEIGHT 20
|
||||
#define ICON_PADDING 1
|
||||
#define ICON_PADDING 2
|
||||
#define PADDING 2
|
||||
|
||||
|
||||
JobStatusDelegate::JobStatusDelegate( QObject* parent )
|
||||
: QStyledItemDelegate ( parent )
|
||||
, m_parentView( qobject_cast< QListView* >( parent ) )
|
||||
@@ -35,6 +37,7 @@ JobStatusDelegate::JobStatusDelegate( QObject* parent )
|
||||
Q_ASSERT( m_parentView );
|
||||
}
|
||||
|
||||
|
||||
JobStatusDelegate::~JobStatusDelegate()
|
||||
{
|
||||
|
||||
@@ -55,7 +58,7 @@ JobStatusDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
|
||||
// painter->drawLine( opt.rect.topLeft(), opt.rect.topRight() );
|
||||
|
||||
painter->setRenderHint( QPainter::Antialiasing );
|
||||
QRect iconRect( ICON_PADDING, ICON_PADDING + opt.rect.y(), ROW_HEIGHT - 2*ICON_PADDING, ROW_HEIGHT - 2*ICON_PADDING );
|
||||
QRect iconRect( ICON_PADDING, ICON_PADDING + opt.rect.y(), ROW_HEIGHT - 2 * ICON_PADDING, ROW_HEIGHT - 2 * ICON_PADDING );
|
||||
if ( allowMultiLine )
|
||||
iconRect.moveTop( opt.rect.top() + opt.rect.height() / 2 - iconRect.height() / 2);
|
||||
QPixmap p = index.data( Qt::DecorationRole ).value< QPixmap >();
|
||||
@@ -71,22 +74,24 @@ JobStatusDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
|
||||
if ( !rCol.isEmpty() )
|
||||
{
|
||||
const int w = fm.width( rCol );
|
||||
const QRect rRect( opt.rect.right() - PADDING - w, PADDING + opt.rect.y(), w, opt.rect.height() - 2*PADDING );
|
||||
const QRect rRect( opt.rect.right() - PADDING - w, PADDING + opt.rect.y(), w, opt.rect.height() - 2 * PADDING );
|
||||
painter->drawText( rRect, Qt::AlignCenter, rCol );
|
||||
|
||||
rightEdge = rRect.left();
|
||||
}
|
||||
|
||||
const int mainW = rightEdge - 3*PADDING - iconRect.right();
|
||||
const int mainW = rightEdge - 4 * PADDING - iconRect.right();
|
||||
QString mainText = index.data( Qt::DisplayRole ).toString();
|
||||
QTextOption to( Qt::AlignLeft | Qt::AlignVCenter );
|
||||
if ( !allowMultiLine )
|
||||
mainText = fm.elidedText( mainText, Qt::ElideRight, mainW );
|
||||
mainText = fm.elidedText( mainText, Qt::ElideRight, mainW );
|
||||
else
|
||||
to.setWrapMode( QTextOption::WrapAtWordBoundaryOrAnywhere );
|
||||
painter->drawText( QRect( iconRect.right() + 2*PADDING, PADDING + opt.rect.y(), mainW, opt.rect.height() - 2*PADDING ), mainText, to );
|
||||
|
||||
painter->drawText( QRect( iconRect.right() + 4 * PADDING, PADDING + opt.rect.y(), mainW, opt.rect.height() - 2 * PADDING ), mainText, to );
|
||||
}
|
||||
|
||||
|
||||
QSize
|
||||
JobStatusDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||
{
|
||||
@@ -102,11 +107,11 @@ JobStatusDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelInd
|
||||
initStyleOption( &opt, index );
|
||||
|
||||
const QString text = index.data( Qt::DisplayRole ).toString();
|
||||
const int leftEdge = ICON_PADDING + ROW_HEIGHT + 2*PADDING;
|
||||
const int leftEdge = ICON_PADDING + ROW_HEIGHT + 2 * PADDING;
|
||||
const QRect rect = opt.fontMetrics.boundingRect( leftEdge, opt.rect.top(), m_parentView->width() - leftEdge, 200, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, text );
|
||||
|
||||
m_cachedMultiLineHeights.insert( index, rect.height() + 4*PADDING );
|
||||
m_cachedMultiLineHeights.insert( index, rect.height() + 4 * PADDING );
|
||||
|
||||
return QSize( QStyledItemDelegate::sizeHint ( option, index ).width(), rect.height() + 4*PADDING );
|
||||
return QSize( QStyledItemDelegate::sizeHint ( option, index ).width(), rect.height() + 4 * PADDING );
|
||||
}
|
||||
|
||||
|
@@ -101,13 +101,12 @@ JobStatusView::setModel( JobStatusModel* m )
|
||||
void
|
||||
JobStatusView::customDelegateJobInserted( int row, JobStatusItem* item )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "item is " << item << ", row is " << row;
|
||||
tLog() << Q_FUNC_INFO << "item is" << item << ", row is" << row;
|
||||
if ( !item )
|
||||
return;
|
||||
|
||||
tLog() << Q_FUNC_INFO << "telling item to create delegate";
|
||||
item->createDelegate( m_view );
|
||||
tLog() << Q_FUNC_INFO << "item delegate is " << item->customDelegate();
|
||||
tLog() << Q_FUNC_INFO << "item delegate is" << item->customDelegate();
|
||||
m_view->setItemDelegateForRow( row, item->customDelegate() );
|
||||
AclJobDelegate* delegate = qobject_cast< AclJobDelegate* >( item->customDelegate() );
|
||||
if ( delegate )
|
||||
@@ -127,7 +126,7 @@ JobStatusView::customDelegateJobInserted( int row, JobStatusItem* item )
|
||||
void
|
||||
JobStatusView::customDelegateJobRemoved( int row )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "row is " << row;
|
||||
tLog() << Q_FUNC_INFO << "row is" << row;
|
||||
}
|
||||
|
||||
|
||||
@@ -138,12 +137,12 @@ JobStatusView::refreshDelegates()
|
||||
int count = m_model->rowCount();
|
||||
for ( int i = 0; i < count; i++ )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "checking row " << i;
|
||||
tLog() << Q_FUNC_INFO << "checking row" << i;
|
||||
QModelIndex index = m_model->index( i );
|
||||
QVariant itemVar = index.data( JobStatusModel::JobDataRole );
|
||||
if ( !itemVar.canConvert< JobStatusItem* >() || !itemVar.value< JobStatusItem* >() )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "unable to fetch JobStatusItem* at row " << i;
|
||||
tLog() << Q_FUNC_INFO << "unable to fetch JobStatusItem* at row" << i;
|
||||
continue;
|
||||
}
|
||||
JobStatusItem* item = itemVar.value< JobStatusItem* >();
|
||||
|
@@ -30,7 +30,7 @@ LatchedStatusItem::LatchedStatusItem( const Tomahawk::source_ptr& from, const To
|
||||
, m_to( to )
|
||||
, m_parent( parent )
|
||||
{
|
||||
m_text = tr( "%1 is listening along to you!" ).arg( from->friendlyName() );
|
||||
m_text = tr( "%1 is listening along with you!" ).arg( from->friendlyName() );
|
||||
}
|
||||
|
||||
LatchedStatusItem::~LatchedStatusItem()
|
||||
|
@@ -29,11 +29,14 @@
|
||||
|
||||
QPixmap* PipelineStatusItem::s_pixmap = 0;
|
||||
|
||||
PipelineStatusItem::PipelineStatusItem()
|
||||
PipelineStatusItem::PipelineStatusItem( const Tomahawk::query_ptr& q )
|
||||
: JobStatusItem()
|
||||
{
|
||||
connect( Tomahawk::Pipeline::instance(), SIGNAL( resolving( Tomahawk::query_ptr ) ), this, SLOT( resolving( Tomahawk::query_ptr ) ) );
|
||||
connect( Tomahawk::Pipeline::instance(), SIGNAL( idle() ), this, SLOT( idle() ) );
|
||||
|
||||
if ( !q.isNull() )
|
||||
resolving( q );
|
||||
}
|
||||
|
||||
|
||||
@@ -102,11 +105,10 @@ PipelineStatusManager::PipelineStatusManager( QObject* parent )
|
||||
void
|
||||
PipelineStatusManager::resolving( const Tomahawk::query_ptr& p )
|
||||
{
|
||||
Q_UNUSED( p );
|
||||
if ( m_curItem.isNull() )
|
||||
{
|
||||
// No current query item and we're resolving something, so show it
|
||||
m_curItem = QWeakPointer< PipelineStatusItem >( new PipelineStatusItem );
|
||||
m_curItem = QWeakPointer< PipelineStatusItem >( new PipelineStatusItem( p ) );
|
||||
JobStatusView::instance()->model()->addJob( m_curItem.data() );
|
||||
}
|
||||
}
|
||||
|
@@ -28,7 +28,7 @@ class PipelineStatusItem : public JobStatusItem
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PipelineStatusItem();
|
||||
explicit PipelineStatusItem( const Tomahawk::query_ptr& q );
|
||||
virtual ~PipelineStatusItem();
|
||||
|
||||
virtual QString rightColumnText() const;
|
||||
|
@@ -107,16 +107,17 @@ void
|
||||
DBSyncConnection::check()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << this << m_source->id();
|
||||
if ( m_state != UNKNOWN && m_state != SYNCED )
|
||||
{
|
||||
qDebug() << "Syncing in progress already.";
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_state == SHUTDOWN )
|
||||
{
|
||||
qDebug() << "Aborting sync due to shutdown.";
|
||||
return;
|
||||
}
|
||||
if ( m_state != UNKNOWN && m_state != SYNCED )
|
||||
{
|
||||
qDebug() << "Syncing in progress already.";
|
||||
return;
|
||||
}
|
||||
|
||||
m_uscache.clear();
|
||||
changeState( CHECKING );
|
||||
|
@@ -112,7 +112,7 @@ CustomPlaylistView::tracksGenerated( QList< query_ptr > tracks )
|
||||
return;
|
||||
|
||||
m_model->clear();
|
||||
m_model->append( newTracks );
|
||||
m_model->appendQueries( newTracks );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -56,7 +56,8 @@ GridItemDelegate::GridItemDelegate( QAbstractItemView* parent, PlayableProxyMode
|
||||
if ( m_view && m_view->metaObject()->indexOfSignal( "modelChanged()" ) > -1 )
|
||||
connect( m_view, SIGNAL( modelChanged() ), this, SLOT( modelChanged() ) );
|
||||
|
||||
connect( m_view, SIGNAL( scrolledContents( int, int ) ), SLOT( onScrolled( int, int ) ) );
|
||||
connect( m_view, SIGNAL( scrolledContents( int, int ) ), SLOT( onViewChanged() ) );
|
||||
connect( m_view, SIGNAL( resized() ), SLOT( onViewChanged() ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -116,8 +117,8 @@ GridItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
|
||||
m_covers.insert( index, QSharedPointer< Tomahawk::PixmapDelegateFader >( new Tomahawk::PixmapDelegateFader( item->query(), r.size(), TomahawkUtils::Grid ) ) );
|
||||
}
|
||||
|
||||
_detail::Closure* closure = NewClosure( m_covers[ index ], SIGNAL( repaintRequest() ), const_cast<GridItemDelegate*>(this), SLOT( doUpdateIndex( QPersistentModelIndex ) ), QPersistentModelIndex( index ) );
|
||||
closure->setAutoDelete( false );
|
||||
NewClosure( m_covers[ index ], SIGNAL( repaintRequest() ),
|
||||
const_cast<GridItemDelegate*>(this), SLOT( doUpdateIndex( QPersistentModelIndex ) ), QPersistentModelIndex( index ) )->setAutoDelete( false );
|
||||
}
|
||||
|
||||
QSharedPointer< Tomahawk::PixmapDelegateFader > fader = m_covers[ index ];
|
||||
@@ -237,14 +238,18 @@ GridItemDelegate::onPlayClicked( const QPersistentModelIndex& index )
|
||||
PlayableItem* item = m_model->sourceModel()->itemFromIndex( m_model->mapToSource( index ) );
|
||||
if ( item )
|
||||
{
|
||||
_detail::Closure* closure;
|
||||
NewClosure( AudioEngine::instance(), SIGNAL( loading( Tomahawk::result_ptr ) ),
|
||||
const_cast<GridItemDelegate*>(this), SLOT( onPlaybackStarted( QPersistentModelIndex ) ), QPersistentModelIndex( index ) );
|
||||
|
||||
closure = NewClosure( AudioEngine::instance(), SIGNAL( loading( Tomahawk::result_ptr ) ),
|
||||
const_cast<GridItemDelegate*>(this), SLOT( onPlaybackStarted( QPersistentModelIndex ) ), QPersistentModelIndex( index ) );
|
||||
m_closures.remove( index );
|
||||
|
||||
closure = NewClosure( AudioEngine::instance(), SIGNAL( started( Tomahawk::result_ptr ) ),
|
||||
const_cast<GridItemDelegate*>(this), SLOT( onPlaylistChanged( QPersistentModelIndex ) ), QPersistentModelIndex( index ) );
|
||||
closure->setAutoDelete( false );
|
||||
m_closures.insertMulti( index, NewClosure( AudioEngine::instance(), SIGNAL( started( Tomahawk::result_ptr ) ),
|
||||
const_cast<GridItemDelegate*>(this), SLOT( onPlaylistChanged( QPersistentModelIndex ) ), QPersistentModelIndex( index ) ) );
|
||||
m_closures.insertMulti( index, NewClosure( AudioEngine::instance(), SIGNAL( stopped() ),
|
||||
const_cast<GridItemDelegate*>(this), SLOT( onPlaylistChanged( QPersistentModelIndex ) ), QPersistentModelIndex( index ) ) );
|
||||
|
||||
foreach ( _detail::Closure* closure, m_closures.values( index ) )
|
||||
closure->setAutoDelete( false );
|
||||
|
||||
connect( AudioEngine::instance(), SIGNAL( stopped() ), SLOT( onPlaybackFinished() ) );
|
||||
|
||||
@@ -421,19 +426,22 @@ GridItemDelegate::doUpdateIndex( const QPersistentModelIndex& idx )
|
||||
|
||||
|
||||
void
|
||||
GridItemDelegate::onScrolled( int dx, int dy )
|
||||
GridItemDelegate::onViewChanged()
|
||||
{
|
||||
foreach ( QWidget* widget, m_spinner.values() )
|
||||
foreach ( const QPersistentModelIndex& index, m_spinner.keys() )
|
||||
{
|
||||
widget->move( widget->pos() + QPoint( dx, dy ) );
|
||||
QRect rect = m_view->visualRect( index );
|
||||
m_spinner.value( index )->move( rect.center() - QPoint( 23, 23 ) );
|
||||
}
|
||||
foreach ( ImageButton* button, m_playButton.values() )
|
||||
foreach ( const QPersistentModelIndex& index, m_playButton.keys() )
|
||||
{
|
||||
button->move( button->pos() + QPoint( dx, dy ) );
|
||||
QRect rect = m_view->visualRect( index );
|
||||
m_playButton.value( index )->move( rect.center() - QPoint( 23, 23 ) );
|
||||
}
|
||||
foreach ( ImageButton* button, m_pauseButton.values() )
|
||||
foreach ( const QPersistentModelIndex& index, m_pauseButton.keys() )
|
||||
{
|
||||
button->move( button->pos() + QPoint( dx, dy ) );
|
||||
QRect rect = m_view->visualRect( index );
|
||||
m_pauseButton.value( index )->move( rect.center() - QPoint( 23, 23 ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,11 +481,19 @@ GridItemDelegate::onPlaylistChanged( const QPersistentModelIndex& index )
|
||||
|
||||
if ( finished )
|
||||
{
|
||||
foreach ( _detail::Closure* closure, m_closures.values( index ) )
|
||||
closure->deleteLater();
|
||||
|
||||
if ( m_pauseButton.contains( index ) )
|
||||
{
|
||||
m_pauseButton[ index ]->deleteLater();
|
||||
m_pauseButton.remove( index );
|
||||
}
|
||||
if ( m_spinner.contains( index ) )
|
||||
{
|
||||
m_spinner[ index ]->deleteLater();
|
||||
m_spinner.remove( index );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -29,6 +29,10 @@ namespace Tomahawk {
|
||||
class PixmapDelegateFader;
|
||||
}
|
||||
|
||||
namespace _detail {
|
||||
class Closure;
|
||||
}
|
||||
|
||||
class QEvent;
|
||||
class QTimeLine;
|
||||
class PlayableProxyModel;
|
||||
@@ -55,7 +59,7 @@ private slots:
|
||||
void modelChanged();
|
||||
void doUpdateIndex( const QPersistentModelIndex& idx );
|
||||
|
||||
void onScrolled( int dx, int dy );
|
||||
void onViewChanged();
|
||||
void onPlaybackStarted( const QPersistentModelIndex& index );
|
||||
void onPlaybackFinished();
|
||||
|
||||
@@ -64,6 +68,7 @@ private slots:
|
||||
|
||||
void fadingFrameChanged( const QPersistentModelIndex& );
|
||||
void fadingFrameFinished( const QPersistentModelIndex& );
|
||||
|
||||
private:
|
||||
QTimeLine* createTimeline( QTimeLine::Direction direction );
|
||||
|
||||
@@ -81,8 +86,8 @@ private:
|
||||
mutable QHash< QPersistentModelIndex, QWidget* > m_spinner;
|
||||
mutable QHash< QPersistentModelIndex, ImageButton* > m_playButton;
|
||||
mutable QHash< QPersistentModelIndex, ImageButton* > m_pauseButton;
|
||||
|
||||
mutable QHash< QPersistentModelIndex, QTimeLine* > m_hoverFaders;
|
||||
mutable QHash< QPersistentModelIndex, _detail::Closure* > m_closures;
|
||||
};
|
||||
|
||||
#endif // GRIDITEMDELEGATE_H
|
||||
|
@@ -77,9 +77,6 @@ GridView::GridView( QWidget* parent )
|
||||
setAutoResize( false );
|
||||
setProxyModel( new PlayableProxyModel( this ) );
|
||||
|
||||
/* m_overlay->setText( tr( "After you have scanned your music collection you will find your latest album additions right here." ) );
|
||||
m_overlay->setText( tr( "This collection doesn't have any recent albums." ) );*/
|
||||
|
||||
connect( this, SIGNAL( doubleClicked( QModelIndex ) ), SLOT( onItemActivated( QModelIndex ) ) );
|
||||
connect( this, SIGNAL( customContextMenuRequested( QPoint ) ), SLOT( onCustomContextMenu( QPoint ) ) );
|
||||
|
||||
@@ -208,6 +205,8 @@ GridView::resizeEvent( QResizeEvent* event )
|
||||
{
|
||||
QListView::resizeEvent( event );
|
||||
layoutItems();
|
||||
|
||||
emit resized();
|
||||
}
|
||||
|
||||
|
||||
|
@@ -78,6 +78,7 @@ public slots:
|
||||
signals:
|
||||
void modelChanged();
|
||||
void scrolledContents( int dx, int dy );
|
||||
void resized();
|
||||
|
||||
protected:
|
||||
virtual void startDrag( Qt::DropActions supportedActions );
|
||||
|
@@ -46,7 +46,7 @@ PlayableModel::PlayableModel( QObject* parent, bool loading )
|
||||
{
|
||||
connect( AudioEngine::instance(), SIGNAL( started( Tomahawk::result_ptr ) ), SLOT( onPlaybackStarted( Tomahawk::result_ptr ) ), Qt::DirectConnection );
|
||||
connect( AudioEngine::instance(), SIGNAL( stopped() ), SLOT( onPlaybackStopped() ), Qt::DirectConnection );
|
||||
|
||||
|
||||
m_header << tr( "Artist" ) << tr( "Title" ) << tr( "Composer" ) << tr( "Album" ) << tr( "Track" ) << tr( "Duration" )
|
||||
<< tr( "Bitrate" ) << tr( "Age" ) << tr( "Year" ) << tr( "Size" ) << tr( "Origin" ) << tr( "Score" ) << tr( "Name" );
|
||||
|
||||
@@ -200,11 +200,11 @@ PlayableModel::queryData( const query_ptr& query, int column, int role ) const
|
||||
case Album:
|
||||
return query->album();
|
||||
break;
|
||||
|
||||
|
||||
case Composer:
|
||||
return query->composer();
|
||||
break;
|
||||
|
||||
|
||||
case Duration:
|
||||
return TomahawkUtils::timeToString( query->duration() );
|
||||
break;
|
||||
@@ -223,7 +223,7 @@ PlayableModel::queryData( const query_ptr& query, int column, int role ) const
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -256,7 +256,7 @@ PlayableModel::queryData( const query_ptr& query, int column, int role ) const
|
||||
case Score:
|
||||
return query->results().first()->score();
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -305,7 +305,7 @@ PlayableModel::data( const QModelIndex& index, int role ) const
|
||||
{
|
||||
return albumData( entry->album(), role );
|
||||
}
|
||||
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
@@ -576,20 +576,6 @@ PlayableModel::queries() const
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
PlayableModel::insertInternal( const T& item, int row )
|
||||
{
|
||||
if ( item.isNull() )
|
||||
return;
|
||||
|
||||
QList< T > list;
|
||||
list << item;
|
||||
|
||||
insert( list, row );
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
PlayableModel::insertInternal( const QList< T >& items, int row )
|
||||
@@ -598,7 +584,7 @@ PlayableModel::insertInternal( const QList< T >& items, int row )
|
||||
{
|
||||
emit trackCountChanged( rowCount( QModelIndex() ) );
|
||||
emit itemCountChanged( rowCount( QModelIndex() ) );
|
||||
|
||||
|
||||
finishLoading();
|
||||
return;
|
||||
}
|
||||
@@ -633,12 +619,12 @@ PlayableModel::insertInternal( const QList< T >& items, int row )
|
||||
void
|
||||
PlayableModel::remove( int row, bool moreToCome )
|
||||
{
|
||||
remove( index( row, 0, QModelIndex() ), moreToCome );
|
||||
removeIndex( index( row, 0, QModelIndex() ), moreToCome );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::remove( const QModelIndex& index, bool moreToCome )
|
||||
PlayableModel::removeIndex( const QModelIndex& index, bool moreToCome )
|
||||
{
|
||||
if ( QThread::currentThread() != thread() )
|
||||
{
|
||||
@@ -666,7 +652,7 @@ PlayableModel::remove( const QModelIndex& index, bool moreToCome )
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::remove( const QList<QModelIndex>& indexes )
|
||||
PlayableModel::removeIndexes( const QList<QModelIndex>& indexes )
|
||||
{
|
||||
QList<QPersistentModelIndex> pil;
|
||||
foreach ( const QModelIndex& idx, indexes )
|
||||
@@ -674,12 +660,12 @@ PlayableModel::remove( const QList<QModelIndex>& indexes )
|
||||
pil << idx;
|
||||
}
|
||||
|
||||
remove( pil );
|
||||
removeIndexes( pil );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::remove( const QList<QPersistentModelIndex>& indexes )
|
||||
PlayableModel::removeIndexes( const QList<QPersistentModelIndex>& indexes )
|
||||
{
|
||||
QList<QPersistentModelIndex> finalIndexes;
|
||||
foreach ( const QPersistentModelIndex index, indexes )
|
||||
@@ -691,7 +677,7 @@ PlayableModel::remove( const QList<QPersistentModelIndex>& indexes )
|
||||
|
||||
for ( int i = 0; i < finalIndexes.count(); i++ )
|
||||
{
|
||||
remove( finalIndexes.at( i ), i + 1 != finalIndexes.count() );
|
||||
removeIndex( finalIndexes.at( i ), i + 1 != finalIndexes.count() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -828,84 +814,102 @@ PlayableModel::itemFromIndex( const QModelIndex& index ) const
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::append( const Tomahawk::artist_ptr& artist )
|
||||
PlayableModel::appendArtist( const Tomahawk::artist_ptr& artist )
|
||||
{
|
||||
insert( artist, rowCount( QModelIndex() ) );
|
||||
QList< artist_ptr > artists;
|
||||
artists << artist;
|
||||
|
||||
appendArtists( artists );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::append( const Tomahawk::album_ptr& album )
|
||||
PlayableModel::appendAlbum( const Tomahawk::album_ptr& album )
|
||||
{
|
||||
insert( album, rowCount( QModelIndex() ) );
|
||||
QList< album_ptr > albums;
|
||||
albums << album;
|
||||
|
||||
appendAlbums( albums );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::append( const Tomahawk::query_ptr& query )
|
||||
PlayableModel::appendQuery( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
insert( query, rowCount( QModelIndex() ) );
|
||||
QList< query_ptr > queries;
|
||||
queries << query;
|
||||
|
||||
appendQueries( queries );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::append( const QList< Tomahawk::artist_ptr >& artists )
|
||||
PlayableModel::appendArtists( const QList< Tomahawk::artist_ptr >& artists )
|
||||
{
|
||||
insert( artists, rowCount( QModelIndex() ) );
|
||||
insertArtists( artists, rowCount( QModelIndex() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::append( const QList< Tomahawk::album_ptr >& albums )
|
||||
PlayableModel::appendAlbums( const QList< Tomahawk::album_ptr >& albums )
|
||||
{
|
||||
insert( albums, rowCount( QModelIndex() ) );
|
||||
insertAlbums( albums, rowCount( QModelIndex() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::append( const QList< Tomahawk::query_ptr >& queries )
|
||||
PlayableModel::appendQueries( const QList< Tomahawk::query_ptr >& queries )
|
||||
{
|
||||
insert( queries, rowCount( QModelIndex() ) );
|
||||
insertQueries( queries, rowCount( QModelIndex() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::insert( const Tomahawk::artist_ptr& artist, int row )
|
||||
PlayableModel::insertArtist( const Tomahawk::artist_ptr& artist, int row )
|
||||
{
|
||||
insertInternal( artist, row );
|
||||
QList< artist_ptr > artists;
|
||||
artists << artist;
|
||||
|
||||
insertArtists( artists, row );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::insert( const Tomahawk::album_ptr& album, int row )
|
||||
PlayableModel::insertAlbum( const Tomahawk::album_ptr& album, int row )
|
||||
{
|
||||
insertInternal( album, row );
|
||||
QList< album_ptr > albums;
|
||||
albums << album;
|
||||
|
||||
insertAlbums( albums, row );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::insert( const Tomahawk::query_ptr& query, int row )
|
||||
PlayableModel::insertQuery( const Tomahawk::query_ptr& query, int row )
|
||||
{
|
||||
insertInternal( query, row );
|
||||
QList< query_ptr > queries;
|
||||
queries << query;
|
||||
|
||||
insertQueries( queries, row );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::insert( const QList< Tomahawk::artist_ptr >& artists, int row )
|
||||
PlayableModel::insertArtists( const QList< Tomahawk::artist_ptr >& artists, int row )
|
||||
{
|
||||
insertInternal( artists, row );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::insert( const QList< Tomahawk::album_ptr >& albums, int row )
|
||||
PlayableModel::insertAlbums( const QList< Tomahawk::album_ptr >& albums, int row )
|
||||
{
|
||||
insertInternal( albums, row );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::insert( const QList< Tomahawk::query_ptr >& queries, int row )
|
||||
PlayableModel::insertQueries( const QList< Tomahawk::query_ptr >& queries, int row )
|
||||
{
|
||||
insertInternal( queries, row );
|
||||
}
|
||||
|
@@ -91,7 +91,7 @@ public:
|
||||
|
||||
virtual QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const;
|
||||
virtual QVariant headerData( int section, Qt::Orientation orientation, int role ) const;
|
||||
|
||||
|
||||
virtual QVariant artistData( const Tomahawk::artist_ptr& artist, int role = Qt::DisplayRole ) const;
|
||||
virtual QVariant albumData( const Tomahawk::album_ptr& album, int role = Qt::DisplayRole ) const;
|
||||
virtual QVariant queryData( const Tomahawk::query_ptr&, int column, int role = Qt::DisplayRole ) const;
|
||||
@@ -114,7 +114,7 @@ public:
|
||||
QList< Tomahawk::query_ptr > queries() const;
|
||||
|
||||
void updateDetailedInfo( const QModelIndex& index );
|
||||
|
||||
|
||||
QSize itemSize() const { return m_itemSize; }
|
||||
void setItemSize( const QSize& size ) { m_itemSize = size; }
|
||||
|
||||
@@ -136,24 +136,24 @@ public slots:
|
||||
|
||||
virtual void clear();
|
||||
|
||||
virtual void append( const QList< Tomahawk::query_ptr >& queries );
|
||||
virtual void append( const QList< Tomahawk::artist_ptr >& artists );
|
||||
virtual void append( const QList< Tomahawk::album_ptr >& albums );
|
||||
virtual void append( const Tomahawk::query_ptr& query );
|
||||
virtual void append( const Tomahawk::artist_ptr& artist );
|
||||
virtual void append( const Tomahawk::album_ptr& album );
|
||||
virtual void appendQueries( const QList< Tomahawk::query_ptr >& queries );
|
||||
virtual void appendArtists( const QList< Tomahawk::artist_ptr >& artists );
|
||||
virtual void appendAlbums( const QList< Tomahawk::album_ptr >& albums );
|
||||
virtual void appendQuery( const Tomahawk::query_ptr& query );
|
||||
virtual void appendArtist( const Tomahawk::artist_ptr& artist );
|
||||
virtual void appendAlbum( const Tomahawk::album_ptr& album );
|
||||
|
||||
virtual void insert( const QList< Tomahawk::query_ptr >& queries, int row = 0 );
|
||||
virtual void insert( const QList< Tomahawk::artist_ptr >& artists, int row = 0 );
|
||||
virtual void insert( const QList< Tomahawk::album_ptr >& albums, int row = 0 );
|
||||
virtual void insert( const Tomahawk::query_ptr& query, int row = 0 );
|
||||
virtual void insert( const Tomahawk::artist_ptr& artist, int row = 0 );
|
||||
virtual void insert( const Tomahawk::album_ptr& album, int row = 0 );
|
||||
virtual void insertQueries( const QList< Tomahawk::query_ptr >& queries, int row = 0 );
|
||||
virtual void insertArtists( const QList< Tomahawk::artist_ptr >& artists, int row = 0 );
|
||||
virtual void insertAlbums( const QList< Tomahawk::album_ptr >& albums, int row = 0 );
|
||||
virtual void insertQuery( const Tomahawk::query_ptr& query, int row = 0 );
|
||||
virtual void insertArtist( const Tomahawk::artist_ptr& artist, int row = 0 );
|
||||
virtual void insertAlbum( const Tomahawk::album_ptr& album, int row = 0 );
|
||||
|
||||
virtual void remove( int row, bool moreToCome = false );
|
||||
virtual void remove( const QModelIndex& index, bool moreToCome = false );
|
||||
virtual void remove( const QList<QModelIndex>& indexes );
|
||||
virtual void remove( const QList<QPersistentModelIndex>& indexes );
|
||||
virtual void removeIndex( const QModelIndex& index, bool moreToCome = false );
|
||||
virtual void removeIndexes( const QList<QModelIndex>& indexes );
|
||||
virtual void removeIndexes( const QList<QPersistentModelIndex>& indexes );
|
||||
|
||||
virtual void setRepeatMode( Tomahawk::PlaylistModes::RepeatMode /*mode*/ ) {}
|
||||
virtual void setShuffled( bool /*shuffled*/ ) {}
|
||||
@@ -170,8 +170,6 @@ private slots:
|
||||
private:
|
||||
template <typename T>
|
||||
void insertInternal( const QList< T >& items, int row );
|
||||
template <typename T>
|
||||
void insertInternal( const T& item, int row );
|
||||
|
||||
Qt::Alignment columnAlignment( int column ) const;
|
||||
|
||||
|
@@ -84,7 +84,7 @@ PlayableProxyModel::setSourcePlayableModel( PlayableModel* sourceModel )
|
||||
{
|
||||
if ( m_model->metaObject()->indexOfSignal( "trackCountChanged(uint)" ) > -1 )
|
||||
connect( m_model, SIGNAL( trackCountChanged( unsigned int ) ), playlistInterface().data(), SIGNAL( sourceTrackCountChanged( unsigned int ) ) );
|
||||
|
||||
|
||||
connect( m_model, SIGNAL( loadingStarted() ), SIGNAL( loadingStarted() ) );
|
||||
connect( m_model, SIGNAL( loadingFinished() ), SIGNAL( loadingFinished() ) );
|
||||
}
|
||||
@@ -99,10 +99,10 @@ PlayableProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourcePa
|
||||
PlayableItem* pi = itemFromIndex( sourceModel()->index( sourceRow, 0, sourceParent ) );
|
||||
if ( !pi )
|
||||
return false;
|
||||
|
||||
|
||||
if ( m_maxVisibleItems >= 0 && sourceRow > m_maxVisibleItems - 1 )
|
||||
return false;
|
||||
|
||||
|
||||
if ( m_hideDupeItems )
|
||||
{
|
||||
for ( int i = 0; i < sourceRow; i++ )
|
||||
@@ -132,10 +132,10 @@ PlayableProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourcePa
|
||||
|
||||
if ( !m_showOfflineResults && !r.isNull() && !r->isOnline() )
|
||||
return false;
|
||||
|
||||
|
||||
if ( filterRegExp().isEmpty() )
|
||||
return true;
|
||||
|
||||
|
||||
QStringList sl = filterRegExp().pattern().split( " ", QString::SkipEmptyParts );
|
||||
foreach( QString s, sl )
|
||||
{
|
||||
@@ -188,19 +188,19 @@ PlayableProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourcePa
|
||||
|
||||
|
||||
void
|
||||
PlayableProxyModel::remove( const QModelIndex& index )
|
||||
PlayableProxyModel::removeIndex( const QModelIndex& index )
|
||||
{
|
||||
if ( !sourceModel() )
|
||||
return;
|
||||
if ( !index.isValid() )
|
||||
return;
|
||||
|
||||
sourceModel()->remove( mapToSource( index ) );
|
||||
sourceModel()->removeIndex( mapToSource( index ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableProxyModel::remove( const QModelIndexList& indexes )
|
||||
PlayableProxyModel::removeIndexes( const QModelIndexList& indexes )
|
||||
{
|
||||
if ( !sourceModel() )
|
||||
return;
|
||||
@@ -212,12 +212,12 @@ PlayableProxyModel::remove( const QModelIndexList& indexes )
|
||||
pil << mapToSource( idx );
|
||||
}
|
||||
|
||||
sourceModel()->remove( pil );
|
||||
sourceModel()->removeIndexes( pil );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableProxyModel::remove( const QList< QPersistentModelIndex >& indexes )
|
||||
PlayableProxyModel::removeIndexes( const QList< QPersistentModelIndex >& indexes )
|
||||
{
|
||||
if ( !sourceModel() )
|
||||
return;
|
||||
@@ -229,7 +229,7 @@ PlayableProxyModel::remove( const QList< QPersistentModelIndex >& indexes )
|
||||
pil << mapToSource( idx );
|
||||
}
|
||||
|
||||
sourceModel()->remove( pil );
|
||||
sourceModel()->removeIndexes( pil );
|
||||
}
|
||||
|
||||
|
||||
@@ -269,6 +269,8 @@ PlayableProxyModel::lessThan( int column, const Tomahawk::query_ptr& q1, const T
|
||||
const QString album2 = q2->albumSortname();
|
||||
const QString track1 = q1->trackSortname();
|
||||
const QString track2 = q2->trackSortname();
|
||||
const QString composer1 = q1->composerSortname();
|
||||
const QString composer2 = q2->composerSortname();
|
||||
const unsigned int albumpos1 = q1->albumpos();
|
||||
const unsigned int albumpos2 = q2->albumpos();
|
||||
const unsigned int discnumber1 = q1->discnumber();
|
||||
@@ -277,6 +279,8 @@ PlayableProxyModel::lessThan( int column, const Tomahawk::query_ptr& q1, const T
|
||||
unsigned int mtime1 = 0, mtime2 = 0;
|
||||
unsigned int size1 = 0, size2 = 0;
|
||||
float score1 = 0, score2 = 0;
|
||||
QString origin1;
|
||||
QString origin2;
|
||||
qint64 id1 = 0, id2 = 0;
|
||||
|
||||
if ( q1->numResults() )
|
||||
@@ -286,6 +290,7 @@ PlayableProxyModel::lessThan( int column, const Tomahawk::query_ptr& q1, const T
|
||||
mtime1 = r->modificationTime();
|
||||
size1 = r->size();
|
||||
score1 = r->score();
|
||||
origin1 = r->friendlySource().toLower();
|
||||
id1 = (qint64)&r;
|
||||
}
|
||||
if ( q2->numResults() )
|
||||
@@ -295,6 +300,7 @@ PlayableProxyModel::lessThan( int column, const Tomahawk::query_ptr& q1, const T
|
||||
mtime2 = r->modificationTime();
|
||||
size2 = r->size();
|
||||
score2 = r->score();
|
||||
origin2 = r->friendlySource().toLower();
|
||||
id2 = (qint64)&r;
|
||||
}
|
||||
|
||||
@@ -327,6 +333,28 @@ PlayableProxyModel::lessThan( int column, const Tomahawk::query_ptr& q1, const T
|
||||
|
||||
return QString::localeAwareCompare( artist1, artist2 ) < 0;
|
||||
}
|
||||
else if ( column == PlayableModel::Composer ) // sort by composer
|
||||
{
|
||||
if ( composer1 == composer2 )
|
||||
{
|
||||
if ( album1 == album2 )
|
||||
{
|
||||
if ( discnumber1 == discnumber2 )
|
||||
{
|
||||
if ( albumpos1 == albumpos2 )
|
||||
return id1 < id2;
|
||||
|
||||
return albumpos1 < albumpos2;
|
||||
}
|
||||
|
||||
return discnumber1 < discnumber2;
|
||||
}
|
||||
|
||||
return QString::localeAwareCompare( album1, album2 ) < 0;
|
||||
}
|
||||
|
||||
return QString::localeAwareCompare( composer1, composer2 ) < 0;
|
||||
}
|
||||
else if ( column == PlayableModel::Album ) // sort by album
|
||||
{
|
||||
if ( album1 == album2 )
|
||||
@@ -372,6 +400,13 @@ PlayableProxyModel::lessThan( int column, const Tomahawk::query_ptr& q1, const T
|
||||
|
||||
return score1 < score2;
|
||||
}
|
||||
else if ( column == PlayableModel::Origin ) // sort by file origin
|
||||
{
|
||||
if ( origin1 == origin2 )
|
||||
return id1 < id2;
|
||||
|
||||
return origin1 < origin2;
|
||||
}
|
||||
else if ( column == PlayableModel::AlbumPos ) // sort by album pos
|
||||
{
|
||||
if ( discnumber1 != discnumber2 )
|
||||
@@ -384,7 +419,7 @@ PlayableProxyModel::lessThan( int column, const Tomahawk::query_ptr& q1, const T
|
||||
return albumpos1 < albumpos2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const QString& lefts = q1->track();
|
||||
const QString& rights = q2->track();
|
||||
if ( lefts == rights )
|
||||
|
@@ -44,9 +44,9 @@ public:
|
||||
virtual QPersistentModelIndex currentIndex() const { return mapFromSource( m_model->currentItem() ); }
|
||||
virtual void setCurrentIndex( const QModelIndex& index ) { m_model->setCurrentItem( mapToSource( index ) ); }
|
||||
|
||||
virtual void remove( const QModelIndex& index );
|
||||
virtual void remove( const QModelIndexList& indexes );
|
||||
virtual void remove( const QList< QPersistentModelIndex >& indexes );
|
||||
virtual void removeIndex( const QModelIndex& index );
|
||||
virtual void removeIndexes( const QModelIndexList& indexes );
|
||||
virtual void removeIndexes( const QList< QPersistentModelIndex >& indexes );
|
||||
|
||||
virtual bool showOfflineResults() const { return m_showOfflineResults; }
|
||||
virtual void setShowOfflineResults( bool b );
|
||||
|
@@ -227,7 +227,7 @@ PlaylistItemDelegate::paintDetailed( QPainter* painter, const QStyleOptionViewIt
|
||||
opt.text.clear();
|
||||
qApp->style()->drawControl( QStyle::CE_ItemViewItem, &opt, painter );
|
||||
|
||||
if ( m_view->hoveredIndex().row() == index.row() && m_view->hoveredIndex().column() == index.column() &&
|
||||
if ( m_view->hoveredIndex().row() == index.row() && m_view->hoveredIndex().column() == index.column() && !index.data().toString().isEmpty() &&
|
||||
( index.column() == PlayableModel::Artist || index.column() == PlayableModel::Album || index.column() == PlayableModel::Track ) )
|
||||
{
|
||||
opt.rect.setWidth( opt.rect.width() - 16 );
|
||||
|
@@ -93,10 +93,10 @@ PlaylistModel::loadPlaylist( const Tomahawk::playlist_ptr& playlist, bool loadEn
|
||||
}
|
||||
|
||||
QList<plentry_ptr> entries = playlist->entries();
|
||||
foreach( const plentry_ptr& p, entries )
|
||||
qDebug() << p->guid() << p->query()->track() << p->query()->artist();
|
||||
/* foreach ( const plentry_ptr& p, entries )
|
||||
qDebug() << p->guid() << p->query()->track() << p->query()->artist();*/
|
||||
|
||||
append( entries );
|
||||
appendEntries( entries );
|
||||
|
||||
m_isLoading = false;
|
||||
}
|
||||
@@ -112,78 +112,67 @@ PlaylistModel::clear()
|
||||
|
||||
|
||||
void
|
||||
PlaylistModel::append( const QList< plentry_ptr >& entries )
|
||||
PlaylistModel::appendEntries( const QList< plentry_ptr >& entries )
|
||||
{
|
||||
insert( entries, rowCount( QModelIndex() ) );
|
||||
insertEntries( entries, rowCount( QModelIndex() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistModel::append( const QList< query_ptr >& queries )
|
||||
PlaylistModel::insertAlbums( const QList< Tomahawk::album_ptr >& albums, int row )
|
||||
{
|
||||
insert( queries, rowCount( QModelIndex() ) );
|
||||
}
|
||||
// FIXME: This currently appends, not inserts!
|
||||
|
||||
|
||||
void
|
||||
PlaylistModel::append( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
insert( query, rowCount( QModelIndex() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistModel::append( const Tomahawk::album_ptr& album )
|
||||
{
|
||||
if ( album.isNull() )
|
||||
return;
|
||||
|
||||
connect( album.data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr>, Tomahawk::ModelMode, Tomahawk::collection_ptr ) ),
|
||||
SLOT( append( QList<Tomahawk::query_ptr> ) ) );
|
||||
|
||||
if ( rowCount( QModelIndex() ) == 0 )
|
||||
foreach ( const album_ptr& album, albums )
|
||||
{
|
||||
setTitle( album->name() );
|
||||
setDescription( tr( "All tracks by %1 on album %2" ).arg( album->artist()->name() ).arg( album->name() ) );
|
||||
m_isTemporary = true;
|
||||
if ( album.isNull() )
|
||||
return;
|
||||
|
||||
connect( album.data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr>, Tomahawk::ModelMode, Tomahawk::collection_ptr ) ),
|
||||
SLOT( appendQueries( QList<Tomahawk::query_ptr> ) ) );
|
||||
|
||||
appendQueries( album->playlistInterface( Mixed )->tracks() );
|
||||
}
|
||||
|
||||
append( album->playlistInterface( Mixed )->tracks() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistModel::append( const Tomahawk::artist_ptr& artist )
|
||||
{
|
||||
if ( artist.isNull() )
|
||||
return;
|
||||
|
||||
connect( artist.data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr>, Tomahawk::ModelMode, Tomahawk::collection_ptr ) ),
|
||||
SLOT( append( QList<Tomahawk::query_ptr> ) ) );
|
||||
|
||||
if ( rowCount( QModelIndex() ) == 0 )
|
||||
if ( rowCount( QModelIndex() ) == 0 && albums.count() == 1 )
|
||||
{
|
||||
setTitle( artist->name() );
|
||||
setDescription( tr( "All tracks by %1" ).arg( artist->name() ) );
|
||||
setTitle( albums.first()->name() );
|
||||
setDescription( tr( "All tracks by %1 on album %2" ).arg( albums.first()->artist()->name() ).arg( albums.first()->name() ) );
|
||||
m_isTemporary = true;
|
||||
}
|
||||
|
||||
append( artist->playlistInterface( Mixed )->tracks() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistModel::insert( const Tomahawk::query_ptr& query, int row )
|
||||
PlaylistModel::insertArtists( const QList< Tomahawk::artist_ptr >& artists, int row )
|
||||
{
|
||||
PlayableModel::insert( query, row );
|
||||
// FIXME: This currently appends, not inserts!
|
||||
|
||||
foreach ( const artist_ptr& artist, artists )
|
||||
{
|
||||
if ( artist.isNull() )
|
||||
return;
|
||||
|
||||
connect( artist.data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr>, Tomahawk::ModelMode, Tomahawk::collection_ptr ) ),
|
||||
SLOT( appendQueries( QList<Tomahawk::query_ptr> ) ) );
|
||||
|
||||
appendQueries( artist->playlistInterface( Mixed )->tracks() );
|
||||
}
|
||||
|
||||
if ( rowCount( QModelIndex() ) == 0 && artists.count() == 1 )
|
||||
{
|
||||
setTitle( artists.first()->name() );
|
||||
setDescription( tr( "All tracks by %1" ).arg( artists.first()->name() ) );
|
||||
m_isTemporary = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistModel::insert( const QList< Tomahawk::query_ptr >& queries, int row )
|
||||
PlaylistModel::insertQueries( const QList< Tomahawk::query_ptr >& queries, int row )
|
||||
{
|
||||
QList< Tomahawk::plentry_ptr > entries;
|
||||
foreach( const query_ptr& query, queries )
|
||||
foreach ( const query_ptr& query, queries )
|
||||
{
|
||||
plentry_ptr entry = plentry_ptr( new PlaylistEntry() );
|
||||
|
||||
@@ -200,12 +189,12 @@ PlaylistModel::insert( const QList< Tomahawk::query_ptr >& queries, int row )
|
||||
entries << entry;
|
||||
}
|
||||
|
||||
insert( entries, row );
|
||||
insertEntries( entries, row );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistModel::insert( const QList< Tomahawk::plentry_ptr >& entries, int row )
|
||||
PlaylistModel::insertEntries( const QList< Tomahawk::plentry_ptr >& entries, int row )
|
||||
{
|
||||
if ( !entries.count() )
|
||||
{
|
||||
@@ -368,7 +357,7 @@ PlaylistModel::parsedDroppedTracks( QList< query_ptr > tracks )
|
||||
if ( update )
|
||||
beginPlaylistChanges();
|
||||
|
||||
insert( tracks, beginRow );
|
||||
insertQueries( tracks, beginRow );
|
||||
|
||||
if ( update && m_dropStorage.action & Qt::CopyAction )
|
||||
endPlaylistChanges();
|
||||
@@ -488,14 +477,7 @@ PlaylistModel::playlistEntries() const
|
||||
|
||||
|
||||
void
|
||||
PlaylistModel::remove( int row, bool moreToCome )
|
||||
{
|
||||
PlayableModel::remove( row, moreToCome );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistModel::remove( const QModelIndex& index, bool moreToCome )
|
||||
PlaylistModel::removeIndex( const QModelIndex& index, bool moreToCome )
|
||||
{
|
||||
PlayableItem* item = itemFromIndex( index );
|
||||
|
||||
@@ -513,27 +495,13 @@ PlaylistModel::remove( const QModelIndex& index, bool moreToCome )
|
||||
if ( item && !m_isLoading )
|
||||
m_savedRemoveTracks << item->query();
|
||||
|
||||
PlayableModel::remove( index, moreToCome );
|
||||
PlayableModel::removeIndex( index, moreToCome );
|
||||
|
||||
if ( !moreToCome )
|
||||
endPlaylistChanges();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistModel::remove( const QList<QModelIndex>& indexes )
|
||||
{
|
||||
PlayableModel::remove( indexes );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistModel::remove( const QList<QPersistentModelIndex>& indexes )
|
||||
{
|
||||
PlayableModel::remove( indexes );
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PlaylistModel::isTemporary() const
|
||||
{
|
||||
|
@@ -58,20 +58,14 @@ public:
|
||||
public slots:
|
||||
virtual void clear();
|
||||
|
||||
virtual void append( const Tomahawk::query_ptr& query );
|
||||
virtual void append( const Tomahawk::album_ptr& album );
|
||||
virtual void append( const Tomahawk::artist_ptr& artist );
|
||||
virtual void append( const QList< Tomahawk::query_ptr >& queries );
|
||||
virtual void append( const QList< Tomahawk::plentry_ptr >& entries );
|
||||
virtual void appendEntries( const QList< Tomahawk::plentry_ptr >& entries );
|
||||
|
||||
virtual void insert( const Tomahawk::query_ptr& query, int row = 0 );
|
||||
virtual void insert( const QList< Tomahawk::query_ptr >& queries, int row = 0 );
|
||||
virtual void insert( const QList< Tomahawk::plentry_ptr >& entries, int row = 0 );
|
||||
virtual void insertAlbums( const QList< Tomahawk::album_ptr >& album, int row = 0 );
|
||||
virtual void insertArtists( const QList< Tomahawk::artist_ptr >& artist, int row = 0 );
|
||||
virtual void insertQueries( const QList< Tomahawk::query_ptr >& queries, int row = 0 );
|
||||
virtual void insertEntries( const QList< Tomahawk::plentry_ptr >& entries, int row = 0 );
|
||||
|
||||
virtual void remove( int row, bool moreToCome = false );
|
||||
virtual void remove( const QModelIndex& index, bool moreToCome = false );
|
||||
virtual void remove( const QList<QModelIndex>& indexes );
|
||||
virtual void remove( const QList<QPersistentModelIndex>& indexes );
|
||||
virtual void removeIndex( const QModelIndex& index, bool moreToCome = false );
|
||||
|
||||
signals:
|
||||
void repeatModeChanged( Tomahawk::PlaylistModes::RepeatMode mode );
|
||||
|
@@ -92,7 +92,7 @@ PlaylistView::keyPressEvent( QKeyEvent* event )
|
||||
if ( ( event->key() == Qt::Key_Delete || event->key() == Qt::Key_Backspace ) && !model()->isReadOnly() )
|
||||
{
|
||||
qDebug() << "Removing selected items";
|
||||
proxyModel()->remove( selectedIndexes() );
|
||||
deleteItems();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ PlaylistView::eventFilter( QObject* obj, QEvent* event )
|
||||
void
|
||||
PlaylistView::deleteItems()
|
||||
{
|
||||
proxyModel()->remove( selectedIndexes() );
|
||||
proxyModel()->removeIndexes( selectedIndexes() );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -52,7 +52,7 @@ QueueProxyModel::onPlaybackStarted( const Tomahawk::result_ptr& result )
|
||||
PlayableItem* item = itemFromIndex( mapToSource( idx ) );
|
||||
if ( item && item->query() && ( item->query()->results().contains( result ) ||
|
||||
item->query()->equals( result->toQuery() ) ) )
|
||||
remove( idx );
|
||||
removeIndex( idx );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ void
|
||||
QueueProxyModel::onIndexActivated( const QModelIndex& index )
|
||||
{
|
||||
setCurrentIndex( QModelIndex() );
|
||||
remove( index );
|
||||
removeIndex( index );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -33,21 +33,10 @@
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
RecentlyAddedModel::RecentlyAddedModel( const source_ptr& source, QObject* parent )
|
||||
RecentlyAddedModel::RecentlyAddedModel( QObject* parent )
|
||||
: PlayableModel( parent )
|
||||
, m_source( source )
|
||||
, m_limit( LATEST_TRACK_ITEMS )
|
||||
{
|
||||
if ( source.isNull() )
|
||||
{
|
||||
connect( SourceList::instance(), SIGNAL( ready() ), SLOT( onSourcesReady() ) );
|
||||
connect( SourceList::instance(), SIGNAL( sourceAdded( Tomahawk::source_ptr ) ), SLOT( onSourceAdded( Tomahawk::source_ptr ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
onSourceAdded( source );
|
||||
loadHistory();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +52,7 @@ RecentlyAddedModel::loadHistory()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
startLoading();
|
||||
|
||||
DatabaseCommand_AllTracks* cmd = new DatabaseCommand_AllTracks( m_source->collection() );
|
||||
cmd->setLimit( m_limit );
|
||||
@@ -70,7 +60,7 @@ RecentlyAddedModel::loadHistory()
|
||||
cmd->setSortDescending( true );
|
||||
|
||||
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr>, QVariant ) ),
|
||||
SLOT( append( QList<Tomahawk::query_ptr> ) ), Qt::QueuedConnection );
|
||||
SLOT( appendQueries( QList<Tomahawk::query_ptr> ) ), Qt::QueuedConnection );
|
||||
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||
}
|
||||
@@ -88,6 +78,28 @@ RecentlyAddedModel::onSourcesReady()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RecentlyAddedModel::setSource( const Tomahawk::source_ptr& source )
|
||||
{
|
||||
m_source = source;
|
||||
|
||||
if ( source.isNull() )
|
||||
{
|
||||
if ( SourceList::instance()->isReady() )
|
||||
onSourcesReady();
|
||||
else
|
||||
connect( SourceList::instance(), SIGNAL( ready() ), SLOT( onSourcesReady() ) );
|
||||
|
||||
connect( SourceList::instance(), SIGNAL( sourceAdded( Tomahawk::source_ptr ) ), SLOT( onSourceAdded( Tomahawk::source_ptr ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
onSourceAdded( source );
|
||||
loadHistory();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RecentlyAddedModel::onSourceAdded( const Tomahawk::source_ptr& source )
|
||||
{
|
||||
|
@@ -32,7 +32,7 @@ class DLLEXPORT RecentlyAddedModel : public PlayableModel
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RecentlyAddedModel( const Tomahawk::source_ptr& source, QObject* parent = 0 );
|
||||
explicit RecentlyAddedModel( QObject* parent = 0 );
|
||||
~RecentlyAddedModel();
|
||||
|
||||
unsigned int limit() const { return m_limit; }
|
||||
@@ -40,6 +40,9 @@ public:
|
||||
|
||||
bool isTemporary() const;
|
||||
|
||||
public slots:
|
||||
void setSource( const Tomahawk::source_ptr& source );
|
||||
|
||||
private slots:
|
||||
void onSourcesReady();
|
||||
void onSourceAdded( const Tomahawk::source_ptr& source );
|
||||
|
@@ -34,25 +34,10 @@
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
RecentlyPlayedModel::RecentlyPlayedModel( const source_ptr& source, QObject* parent )
|
||||
RecentlyPlayedModel::RecentlyPlayedModel( QObject* parent )
|
||||
: PlaylistModel( parent )
|
||||
, m_source( source )
|
||||
, m_limit( HISTORY_TRACK_ITEMS )
|
||||
{
|
||||
if ( source.isNull() )
|
||||
{
|
||||
if ( SourceList::instance()->isReady() )
|
||||
onSourcesReady();
|
||||
else
|
||||
connect( SourceList::instance(), SIGNAL( ready() ), SLOT( onSourcesReady() ) );
|
||||
|
||||
connect( SourceList::instance(), SIGNAL( sourceAdded( Tomahawk::source_ptr ) ), SLOT( onSourceAdded( Tomahawk::source_ptr ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
onSourceAdded( source );
|
||||
loadHistory();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,13 +53,13 @@ RecentlyPlayedModel::loadHistory()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
loadingStarted();
|
||||
startLoading();
|
||||
|
||||
DatabaseCommand_PlaybackHistory* cmd = new DatabaseCommand_PlaybackHistory( m_source );
|
||||
cmd->setLimit( m_limit );
|
||||
|
||||
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ),
|
||||
SLOT( append( QList<Tomahawk::query_ptr> ) ), Qt::QueuedConnection );
|
||||
SLOT( appendQueries( QList<Tomahawk::query_ptr> ) ), Qt::QueuedConnection );
|
||||
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||
}
|
||||
@@ -92,6 +77,27 @@ RecentlyPlayedModel::onSourcesReady()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RecentlyPlayedModel::setSource( const Tomahawk::source_ptr& source )
|
||||
{
|
||||
m_source = source;
|
||||
if ( source.isNull() )
|
||||
{
|
||||
if ( SourceList::instance()->isReady() )
|
||||
onSourcesReady();
|
||||
else
|
||||
connect( SourceList::instance(), SIGNAL( ready() ), SLOT( onSourcesReady() ) );
|
||||
|
||||
connect( SourceList::instance(), SIGNAL( sourceAdded( Tomahawk::source_ptr ) ), SLOT( onSourceAdded( Tomahawk::source_ptr ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
onSourceAdded( source );
|
||||
loadHistory();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RecentlyPlayedModel::onSourceAdded( const Tomahawk::source_ptr& source )
|
||||
{
|
||||
@@ -113,7 +119,7 @@ RecentlyPlayedModel::onPlaybackFinished( const Tomahawk::query_ptr& query )
|
||||
|
||||
PlayableItem* youngestItem = itemFromIndex( index( 0, 0, QModelIndex() ) );
|
||||
if ( youngestItem->query()->playedBy().second <= playtime )
|
||||
insert( query, 0 );
|
||||
insertQuery( query, 0 );
|
||||
else
|
||||
{
|
||||
for ( int i = 0; i < count - 1; i++ )
|
||||
@@ -123,14 +129,14 @@ RecentlyPlayedModel::onPlaybackFinished( const Tomahawk::query_ptr& query )
|
||||
|
||||
if ( item1->query()->playedBy().second >= playtime && item2->query()->playedBy().second <= playtime )
|
||||
{
|
||||
insert( query, i + 1 );
|
||||
insertQuery( query, i + 1 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
insert( query, 0 );
|
||||
insertQuery( query, 0 );
|
||||
|
||||
if ( trackCount() > (int)m_limit )
|
||||
remove( m_limit );
|
||||
|
@@ -32,7 +32,7 @@ class DLLEXPORT RecentlyPlayedModel : public PlaylistModel
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RecentlyPlayedModel( const Tomahawk::source_ptr& source, QObject* parent = 0 );
|
||||
explicit RecentlyPlayedModel( QObject* parent = 0 );
|
||||
~RecentlyPlayedModel();
|
||||
|
||||
unsigned int limit() const { return m_limit; }
|
||||
@@ -40,6 +40,9 @@ public:
|
||||
|
||||
bool isTemporary() const;
|
||||
|
||||
public slots:
|
||||
void setSource( const Tomahawk::source_ptr& source );
|
||||
|
||||
private slots:
|
||||
void onSourcesReady();
|
||||
void onSourceAdded( const Tomahawk::source_ptr& source );
|
||||
|
@@ -99,7 +99,7 @@ TrackView::TrackView( QWidget* parent )
|
||||
connect( this, SIGNAL( doubleClicked( QModelIndex ) ), SLOT( onItemActivated( QModelIndex ) ) );
|
||||
connect( this, SIGNAL( customContextMenuRequested( const QPoint& ) ), SLOT( onCustomContextMenu( const QPoint& ) ) );
|
||||
connect( m_contextMenu, SIGNAL( triggered( int ) ), SLOT( onMenuTriggered( int ) ) );
|
||||
|
||||
|
||||
setProxyModel( new PlayableProxyModel( this ) );
|
||||
}
|
||||
|
||||
@@ -554,7 +554,7 @@ TrackView::startDrag( Qt::DropActions supportedActions )
|
||||
Qt::DropAction action = drag->exec( supportedActions, Qt::CopyAction );
|
||||
if ( action == Qt::MoveAction )
|
||||
{
|
||||
m_proxyModel->remove( pindexes );
|
||||
m_proxyModel->removeIndexes( pindexes );
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -110,7 +110,7 @@ TreeItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
|
||||
o.rect.setX( oldX );
|
||||
|
||||
if ( m_view->hoveredIndex().row() == index.row() && m_view->hoveredIndex().column() == index.column() &&
|
||||
( index.column() == 0 ) )
|
||||
!index.data().toString().isEmpty() && index.column() == 0 )
|
||||
{
|
||||
o.rect.setWidth( o.rect.width() - 16 );
|
||||
QRect arrowRect( o.rect.x() + o.rect.width(), o.rect.y() + 1, o.rect.height() - 2, o.rect.height() - 2 );
|
||||
|
@@ -249,6 +249,8 @@ TreeModel::addCollection( const collection_ptr& collection )
|
||||
<< collection->source()->id()
|
||||
<< collection->source()->userName();
|
||||
|
||||
startLoading();
|
||||
|
||||
m_collection = collection;
|
||||
DatabaseCommand_AllArtists* cmd = new DatabaseCommand_AllArtists( collection );
|
||||
|
||||
|
@@ -190,18 +190,18 @@ TreeProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent
|
||||
PlayableItem* item = sourceModel()->itemFromIndex( sourceModel()->index( sourceRow, 0, sourceParent ) );
|
||||
Q_ASSERT( item );
|
||||
|
||||
if ( m_model->mode() == Tomahawk::DatabaseMode && !item->result().isNull() )
|
||||
if ( m_model->mode() == Tomahawk::DatabaseMode && !item->query().isNull() )
|
||||
{
|
||||
QList< Tomahawk::result_ptr > rl = m_cache.values( sourceParent );
|
||||
foreach ( const Tomahawk::result_ptr& cachedResult, rl )
|
||||
QList< Tomahawk::query_ptr > rl = m_cache.values( sourceParent );
|
||||
foreach ( const Tomahawk::query_ptr& cachedQuery, rl )
|
||||
{
|
||||
if ( cachedResult.isNull() )
|
||||
if ( cachedQuery.isNull() )
|
||||
continue;
|
||||
|
||||
if ( cachedResult->track() == item->result()->track() &&
|
||||
( cachedResult->albumpos() == item->result()->albumpos() || cachedResult->albumpos() == 0 ) )
|
||||
if ( cachedQuery->track() == item->query()->track() &&
|
||||
( cachedQuery->albumpos() == item->query()->albumpos() || cachedQuery->albumpos() == 0 ) )
|
||||
{
|
||||
return ( cachedResult.data() == item->result().data() );
|
||||
return ( cachedQuery.data() == item->query().data() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,14 +212,25 @@ TreeProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent
|
||||
|
||||
PlayableItem* ti = sourceModel()->itemFromIndex( sourceModel()->index( i, 0, sourceParent ) );
|
||||
|
||||
if ( ti->name() == item->name() &&
|
||||
( ti->result()->albumpos() == item->result()->albumpos() || ti->result()->albumpos() == 0 || item->result()->albumpos() == 0 ) )
|
||||
if ( ti && ti->name() == item->name() )
|
||||
{
|
||||
if ( !item->result()->isOnline() && ti->result()->isOnline() )
|
||||
return false;
|
||||
if ( ti->query()->albumpos() == item->query()->albumpos() || ti->query()->albumpos() == 0 || item->query()->albumpos() == 0 )
|
||||
{
|
||||
if ( item->result().isNull() )
|
||||
return false;
|
||||
|
||||
if ( !item->result()->collection()->source()->isLocal() && ti->result()->collection()->source()->isLocal() )
|
||||
return false;
|
||||
if ( !ti->result().isNull() )
|
||||
{
|
||||
if ( !item->result()->isOnline() && ti->result()->isOnline() )
|
||||
return false;
|
||||
|
||||
if ( ( item->result()->collection().isNull() || !item->result()->collection()->source()->isLocal() ) &&
|
||||
!ti->result()->collection().isNull() && ti->result()->collection()->source()->isLocal() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -246,7 +257,7 @@ TreeProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent
|
||||
}
|
||||
}
|
||||
|
||||
m_cache.insertMulti( sourceParent, item->result() );
|
||||
m_cache.insertMulti( sourceParent, item->query() );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -65,7 +65,7 @@ private:
|
||||
void filterFinished();
|
||||
QString textForItem( PlayableItem* item ) const;
|
||||
|
||||
mutable QMap< QPersistentModelIndex, Tomahawk::result_ptr > m_cache;
|
||||
mutable QMap< QPersistentModelIndex, Tomahawk::query_ptr > m_cache;
|
||||
|
||||
QList<Tomahawk::artist_ptr> m_artistsFilter;
|
||||
QList<int> m_albumsFilter;
|
||||
|
@@ -84,6 +84,8 @@ ViewHeader::checkState()
|
||||
{
|
||||
if ( isSectionHidden( i ) )
|
||||
continue;
|
||||
if ( i >= m_columnWeights.count() )
|
||||
break;
|
||||
|
||||
double nw = (double)m_parent->width() * m_columnWeights.at( i );
|
||||
resizeSection( i, qMax( minimumSectionSize(), int( nw - 0.5 ) ) );
|
||||
|
@@ -121,7 +121,7 @@ DynamicModel::newTrackGenerated( const Tomahawk::query_ptr& query )
|
||||
connect( query.data(), SIGNAL( resolvingFinished( bool ) ), this, SLOT( trackResolveFinished( bool ) ) );
|
||||
|
||||
m_waitingFor << query.data();
|
||||
append( query );
|
||||
appendQuery( query );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,11 +316,9 @@ DynamicModel::addToPlaylist( const QList< query_ptr >& entries, bool clearFirst
|
||||
m_playlist->addEntries( entries, m_playlist->currentrevision() );
|
||||
}
|
||||
else
|
||||
{ // read-only, so add tracks only in the GUI, not to the playlist itself
|
||||
foreach ( const query_ptr& query, entries )
|
||||
{
|
||||
append( query );
|
||||
}
|
||||
{
|
||||
// read-only, so add tracks only in the GUI, not to the playlist itself
|
||||
appendQueries( entries );
|
||||
}
|
||||
|
||||
emit tracksAdded();
|
||||
@@ -328,7 +326,7 @@ DynamicModel::addToPlaylist( const QList< query_ptr >& entries, bool clearFirst
|
||||
|
||||
|
||||
void
|
||||
DynamicModel::remove(const QModelIndex& idx, bool moreToCome)
|
||||
DynamicModel::removeIndex( const QModelIndex& idx, bool moreToCome )
|
||||
{
|
||||
if ( m_playlist->mode() == Static && isReadOnly() )
|
||||
return;
|
||||
@@ -340,10 +338,10 @@ DynamicModel::remove(const QModelIndex& idx, bool moreToCome)
|
||||
{ // if the user is manually removing the last one, re-add as we're a station
|
||||
newTrackLoading();
|
||||
}
|
||||
PlayableModel::remove( idx );
|
||||
PlayableModel::removeIndex( idx );
|
||||
}
|
||||
else
|
||||
PlaylistModel::remove( idx, moreToCome );
|
||||
PlaylistModel::removeIndex( idx, moreToCome );
|
||||
// don't call onPlaylistChanged.
|
||||
|
||||
if( !moreToCome )
|
||||
|
@@ -46,7 +46,7 @@ public:
|
||||
|
||||
void loadPlaylist( const dynplaylist_ptr& playlist, bool loadEntries = true );
|
||||
|
||||
virtual void remove( const QModelIndex& index, bool moreToCome = false );
|
||||
virtual void removeIndex( const QModelIndex& index, bool moreToCome = false );
|
||||
|
||||
bool searchingForNext() const { return m_searchingForNext; }
|
||||
|
||||
|
@@ -260,7 +260,7 @@ DynamicView::collapseEntries( int startRow, int num, int numToKeep )
|
||||
todel << proxyModel()->index( startRow + i, k );
|
||||
}
|
||||
}
|
||||
proxyModel()->remove( todel );
|
||||
proxyModel()->removeIndexes( todel );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -442,7 +442,7 @@ DynamicWidget::steeringChanged()
|
||||
toRemove << m_view->proxyModel()->index( i, 0, QModelIndex() );
|
||||
}
|
||||
|
||||
m_view->proxyModel()->remove( toRemove );
|
||||
m_view->proxyModel()->removeIndexes( toRemove );
|
||||
|
||||
m_playlist->generator()->fetchNext();
|
||||
}
|
||||
|
@@ -213,7 +213,7 @@ void
|
||||
ScriptEngine::javaScriptConsoleMessage( const QString& message, int lineNumber, const QString& sourceID )
|
||||
{
|
||||
tLog() << "JAVASCRIPT:" << m_scriptPath << message << lineNumber << sourceID;
|
||||
#ifdef DEBUG_BUILD
|
||||
#ifndef QT_NO_DEBUG
|
||||
QMessageBox::critical( 0, "Script Resolver Error", QString( "%1 %2 %3 %4" ).arg( m_scriptPath ).arg( message ).arg( lineNumber ).arg( sourceID ) );
|
||||
#endif
|
||||
}
|
||||
@@ -408,6 +408,8 @@ QtScriptResolver::parseResultVariantList( const QVariantList& reslist )
|
||||
foreach( const QVariant& rv, reslist )
|
||||
{
|
||||
QVariantMap m = rv.toMap();
|
||||
if ( m.value( "artist" ).toString().trimmed().isEmpty() || m.value( "track" ).toString().trimmed().isEmpty() )
|
||||
continue;
|
||||
|
||||
Tomahawk::result_ptr rp = Tomahawk::Result::get( m.value( "url" ).toString() );
|
||||
Tomahawk::artist_ptr ap = Tomahawk::Artist::get( m.value( "artist" ).toString(), false );
|
||||
|
@@ -76,7 +76,6 @@ ScriptResolver::~ScriptResolver()
|
||||
if ( !finished || m_proc.state() == QProcess::Running )
|
||||
{
|
||||
qDebug() << "External resolver didn't exit after waiting 2s for it to die, killing forcefully";
|
||||
Q_ASSERT(false);
|
||||
#ifdef Q_OS_WIN
|
||||
m_proc.kill();
|
||||
#else
|
||||
@@ -160,6 +159,7 @@ ScriptResolver::running() const
|
||||
return !m_stopped;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptResolver::sendMessage( const QVariantMap& map )
|
||||
{
|
||||
@@ -255,7 +255,11 @@ ScriptResolver::handleMsg( const QByteArray& msg )
|
||||
setupConfWidget( m );
|
||||
return;
|
||||
}
|
||||
|
||||
else if ( msgtype == "status" )
|
||||
{
|
||||
sendStatus();
|
||||
return;
|
||||
}
|
||||
else if ( msgtype == "results" )
|
||||
{
|
||||
const QString qid = m.value( "qid" ).toString();
|
||||
@@ -265,7 +269,9 @@ ScriptResolver::handleMsg( const QByteArray& msg )
|
||||
foreach( const QVariant& rv, reslist )
|
||||
{
|
||||
QVariantMap m = rv.toMap();
|
||||
qDebug() << "Found result:" << m;
|
||||
tDebug( LOGVERBOSE ) << "Found result:" << m;
|
||||
if ( m.value( "artist" ).toString().trimmed().isEmpty() || m.value( "track" ).toString().trimmed().isEmpty() )
|
||||
continue;
|
||||
|
||||
Tomahawk::result_ptr rp = Tomahawk::Result::get( m.value( "url" ).toString() );
|
||||
Tomahawk::artist_ptr ap = Tomahawk::Artist::get( m.value( "artist" ).toString(), false );
|
||||
@@ -333,6 +339,7 @@ ScriptResolver::cmdExited( int code, QProcess::ExitStatus status )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptResolver::resolve( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
@@ -358,6 +365,16 @@ ScriptResolver::resolve( const Tomahawk::query_ptr& query )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptResolver::sendStatus()
|
||||
{
|
||||
QVariantMap msg;
|
||||
msg[ "_msgtype" ] = "status";
|
||||
msg[ "_status" ] = 1;
|
||||
sendMessage( msg );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptResolver::doSetup( const QVariantMap& m )
|
||||
{
|
||||
@@ -398,7 +415,8 @@ ScriptResolver::setupConfWidget( const QVariantMap& m )
|
||||
}
|
||||
|
||||
|
||||
void ScriptResolver::startProcess()
|
||||
void
|
||||
ScriptResolver::startProcess()
|
||||
{
|
||||
if ( !QFile::exists( filePath() ) )
|
||||
m_error = Tomahawk::ExternalResolver::FileNotFound;
|
||||
@@ -407,10 +425,14 @@ void ScriptResolver::startProcess()
|
||||
m_error = Tomahawk::ExternalResolver::NoError;
|
||||
}
|
||||
|
||||
QFileInfo fi( filePath() );
|
||||
const QFileInfo fi( filePath() );
|
||||
|
||||
QString interpreter;
|
||||
QString runPath = filePath();
|
||||
// have to enclose in quotes if path contains spaces...
|
||||
const QString runPath = QString( "\"%1\"" ).arg( filePath() );
|
||||
|
||||
QFile file( filePath() );
|
||||
file.setPermissions( file.permissions() | QFile::ExeOwner | QFile::ExeGroup | QFile::ExeOther );
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
if ( fi.suffix().toLower() != "exe" )
|
||||
@@ -434,18 +456,14 @@ void ScriptResolver::startProcess()
|
||||
interpreter = QString( "\"%1\"" ).arg(QString::fromUtf16((const ushort *) path));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// have to enclose in quotes if path contains spaces on windows...
|
||||
runPath = QString( "\"%1\"" ).arg( filePath() );
|
||||
}
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
if( interpreter.isEmpty() )
|
||||
if ( interpreter.isEmpty() )
|
||||
{
|
||||
#ifndef Q_OS_WIN
|
||||
const QFileInfo info( runPath );
|
||||
const QFileInfo info( filePath() );
|
||||
m_proc.setWorkingDirectory( info.absolutePath() );
|
||||
tLog() << "Setting working dir:" << info.absolutePath();
|
||||
#endif
|
||||
m_proc.start( runPath );
|
||||
}
|
||||
|
@@ -77,6 +77,7 @@ private:
|
||||
void sendMsg( const QByteArray& msg );
|
||||
void doSetup( const QVariantMap& m );
|
||||
void setupConfWidget( const QVariantMap& m );
|
||||
void sendStatus();
|
||||
|
||||
void startProcess();
|
||||
|
||||
|
@@ -35,71 +35,37 @@ namespace TomahawkUtils
|
||||
void
|
||||
BinaryExtractWorker::run()
|
||||
{
|
||||
ScopedDeleter deleter( this );
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
// Platform-specific handling of resolver payload now. We know it's good
|
||||
// Unzip the file.
|
||||
QFileInfo info( m_zipFileName );
|
||||
QDir tmpDir = QDir::tempPath();
|
||||
if ( !tmpDir.mkdir( info.baseName() ) )
|
||||
{
|
||||
qWarning() << "Failed to create temporary directory to unzip in:" << tmpDir.absolutePath();
|
||||
return;
|
||||
}
|
||||
tmpDir.cd( info.baseName() );
|
||||
TomahawkUtils::unzipFileInFolder( info.absoluteFilePath(), tmpDir );
|
||||
|
||||
// On OSX it just contains 1 file, the resolver executable itself. For now. We just copy it to
|
||||
// the Tomahawk.app/Contents/MacOS/ folder alongside the Tomahawk executable.
|
||||
const QString dest = QCoreApplication::applicationDirPath();
|
||||
// Find the filename
|
||||
const QDir toList( tmpDir.absolutePath() );
|
||||
const QStringList files = toList.entryList( QStringList(), QDir::Files );
|
||||
Q_ASSERT( files.size() == 1 );
|
||||
|
||||
const QString src = toList.absoluteFilePath( files.first() );
|
||||
qDebug() << "OS X: Copying binary resolver from to:" << src << dest;
|
||||
|
||||
copyWithAuthentication( src, dest, m_receiver );
|
||||
|
||||
ScopedDeleter deleter( this );
|
||||
// We unzip directly to the target location, just like normal attica resolvers
|
||||
Q_ASSERT( m_receiver );
|
||||
if ( !m_receiver )
|
||||
return;
|
||||
#elif defined(Q_OS_WIN) || defined(Q_OS_LINUX)
|
||||
// We unzip directly to the target location, just like normal attica resolvers
|
||||
Q_ASSERT( m_receiver );
|
||||
if ( !m_receiver )
|
||||
return;
|
||||
|
||||
const QString resolverId = m_receiver->property( "resolverid" ).toString();
|
||||
const QString resolverId = m_receiver->property( "resolverid" ).toString();
|
||||
|
||||
Q_ASSERT( !resolverId.isEmpty() );
|
||||
if ( resolverId.isEmpty() )
|
||||
return;
|
||||
Q_ASSERT( !resolverId.isEmpty() );
|
||||
if ( resolverId.isEmpty() )
|
||||
return;
|
||||
|
||||
const QDir resolverPath( extractScriptPayload( m_zipFileName, resolverId ) );
|
||||
const QDir resolverPath( extractScriptPayload( m_zipFileName, resolverId ) );
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
const QStringList files = resolverPath.entryList( QStringList() << "*.exe", QDir::Files );
|
||||
#elif defined(Q_OS_LINUX)
|
||||
const QStringList files = resolverPath.entryList( QStringList() << "*_tomahawkresolver", QDir::Files );
|
||||
const QStringList files = resolverPath.entryList( QStringList() << "*.exe", QDir::Files );
|
||||
#else
|
||||
const QStringList files = resolverPath.entryList( QStringList() << "*_tomahawkresolver", QDir::Files );
|
||||
#endif
|
||||
|
||||
qDebug() << "Found executables in unzipped binary resolver dir:" << files;
|
||||
Q_ASSERT( files.size() == 1 );
|
||||
if ( files.size() < 1 )
|
||||
return;
|
||||
qDebug() << "Found executables in unzipped binary resolver dir:" << files;
|
||||
Q_ASSERT( files.size() == 1 );
|
||||
if ( files.size() < 1 )
|
||||
return;
|
||||
|
||||
const QString resolverToUse = resolverPath.absoluteFilePath( files.first() );
|
||||
const QString resolverToUse = resolverPath.absoluteFilePath( files.first() );
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
QProcess p;
|
||||
p.start( "chmod", QStringList() << "744" << resolverToUse, QIODevice::ReadOnly );
|
||||
p.waitForFinished();
|
||||
#endif
|
||||
QFile file( resolverToUse );
|
||||
file.setPermissions( file.permissions() | QFile::ExeOwner | QFile::ExeGroup | QFile::ExeOther );
|
||||
|
||||
QMetaObject::invokeMethod( m_receiver, "installSucceeded", Qt::QueuedConnection, Q_ARG( QString, resolverToUse ) );
|
||||
|
||||
#endif
|
||||
QMetaObject::invokeMethod( m_receiver, "installSucceeded", Qt::QueuedConnection, Q_ARG( QString, resolverToUse ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -199,7 +199,8 @@ GroovesharkParser::trackPageFetchFinished()
|
||||
tDebug() << "Got track info from grooveshark, enough to create a query:" << title.toPlainText() << artist.toPlainText() << album.toPlainText();
|
||||
|
||||
Tomahawk::query_ptr q = Tomahawk::Query::get( artist.toPlainText(), title.toPlainText(), album.toPlainText(), uuid(), true );
|
||||
m_tracks << q;
|
||||
if ( !q.isNull() )
|
||||
m_tracks << q;
|
||||
}
|
||||
|
||||
checkTrackFinished();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user