diff --git a/admin/mac/macdeploy.py b/admin/mac/macdeploy.py index 94eed534b..8e1f83370 100755 --- a/admin/mac/macdeploy.py +++ b/admin/mac/macdeploy.py @@ -1,4 +1,5 @@ #!/usr/bin/python +<<<<<<< HEAD # This file is part of Tomahawk. # It was inspired in large part by the macdeploy script in Clementine. # @@ -249,7 +250,7 @@ frameworks_dir = os.path.join(bundle_dir, 'Contents', 'Frameworks') commands.append(['mkdir', '-p', frameworks_dir]) resources_dir = os.path.join(bundle_dir, 'Contents', 'Resources') commands.append(['mkdir', '-p', resources_dir]) -plugins_dir = os.path.join(bundle_dir, 'Contents', 'plugins') +plugins_dir = os.path.join(bundle_dir, 'Contents', 'PlugIns') binary = os.path.join(bundle_dir, 'Contents', 'MacOS', bundle_name) fixed_libraries = [] diff --git a/data/images/recently-played.png b/data/images/recently-played.png index 956f761f2..0c1161af0 100644 Binary files a/data/images/recently-played.png and b/data/images/recently-played.png differ diff --git a/src/accounts/spotify/SpotifyAccount.cpp b/src/accounts/spotify/SpotifyAccount.cpp index ddcad7da8..e28b9c669 100644 --- a/src/accounts/spotify/SpotifyAccount.cpp +++ b/src/accounts/spotify/SpotifyAccount.cpp @@ -160,7 +160,7 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg { const QString plid = msg.value( "playlistid" ).toString(); // We should already be syncing this playlist if we get updates for it - Q_ASSERT( m_updaters.contains( plid ) ); +// Q_ASSERT( m_updaters.contains( plid ) ); if ( !m_updaters.contains( plid ) ) return; @@ -179,7 +179,7 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg { const QString plid = msg.value( "playlistid" ).toString(); // We should already be syncing this playlist if we get updates for it - Q_ASSERT( m_updaters.contains( plid ) ); +// Q_ASSERT( m_updaters.contains( plid ) ); if ( !m_updaters.contains( plid ) ) return; @@ -187,7 +187,7 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg SpotifyPlaylistUpdater* updater = m_updaters[ plid ]; Q_ASSERT( updater->sync() ); - const QVariantList tracksList = msg.value( "tracks" ).toList(); + const QVariantList tracksList = msg.value( "trackPositions" ).toList(); const QString newRev = msg.value( "revid" ).toString(); const QString oldRev = msg.value( "oldRev" ).toString(); @@ -206,7 +206,7 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg SpotifyPlaylistUpdater* updater = m_updaters[ plid ]; Q_ASSERT( updater->sync() ); - const QVariantList tracksList = msg.value( "tracks" ).toList(); + const QVariantList tracksList = msg.value( "trackPositions" ).toList(); const QString newRev = msg.value( "revid" ).toString(); const QString oldRev = msg.value( "oldRev" ).toString(); diff --git a/src/accounts/spotify/SpotifyPlaylistUpdater.cpp b/src/accounts/spotify/SpotifyPlaylistUpdater.cpp index da8a16aef..ad3a07d97 100644 --- a/src/accounts/spotify/SpotifyPlaylistUpdater.cpp +++ b/src/accounts/spotify/SpotifyPlaylistUpdater.cpp @@ -40,6 +40,12 @@ SpotifyUpdaterFactory::create( const Tomahawk::playlist_ptr& pl ) } } + if ( !m_account ) + { + qWarning() << "Found a spotify updater with no spotify account... ignoreing for now!!"; + return 0; + } + // Register the updater with the account const QString spotifyId = QString( "playlistupdaters/%1" ).arg( pl->guid() ); Q_ASSERT( !spotifyId.isEmpty() ); @@ -143,49 +149,53 @@ SpotifyPlaylistUpdater::spotifyTracksAdded( const QVariantList& tracks, int star // Q_ASSERT( m_latestRev == oldRev ); // m_latestRev = newRev; - //NOTE: remove 1 from the position, as spotify gives the *newly inserted* position, not the index to insert at - startPos--; + if ( startPos > playlist()->entries().size() ) + startPos = playlist()->entries().size(); + + m_plRevisionBeforeUpdate = playlist()->currentrevision(); playlist()->insertEntries( queries, startPos, playlist()->currentrevision() ); } void -SpotifyPlaylistUpdater::spotifyTracksRemoved( const QVariantList& tracks, const QString& newRev, const QString& oldRev ) +SpotifyPlaylistUpdater::spotifyTracksRemoved( const QVariantList& trackPositions, const QString& newRev, const QString& oldRev ) { - qDebug() << Q_FUNC_INFO << "remove tracks in middle of tomahawk playlist, from spotify command!" << tracks << newRev << oldRev; + qDebug() << Q_FUNC_INFO << "remove tracks in middle of tomahawk playlist, from spotify command!" << trackPositions << newRev << oldRev; // Uh oh, dont' want to get out of sync!! // Q_ASSERT( m_latestRev == oldRev ); // m_latestRev = newRev; QList< plentry_ptr > entries = playlist()->entries(); - // FIXME UGH have to do a manual lookup for each track we want to remove... any ideas? - foreach( const QVariant& blob, tracks ) + // Collect list of tracks to remove (can't remove in-place as that might modify the indices) + QList toRemove; + foreach( const QVariant posV, trackPositions ) { - const QVariantMap trackMap = blob.toMap(); - for ( QList::iterator iter = entries.begin(); iter != entries.end(); ++iter ) + bool ok; + const int pos = posV.toInt( &ok ); + if ( !ok || pos < 0 || pos >= entries.size() ) { - const QString trackId = iter->data()->query()->property( "spotifytrackid" ).toString(); - // easy case, we have a track id on both sides, so we're sure - if ( trackId.isEmpty() && trackId == trackMap.value( "id" ).toString() ) - { - iter = entries.erase( iter ); - continue; - } - - // fuzzy case, check metadata - if ( iter->data()->query()->track() == trackMap[ "track" ].toString() && - iter->data()->query()->artist() == trackMap[ "artist" ].toString() && - iter->data()->query()->album() == trackMap[ "album" ].toString() ) - { - iter = entries.erase( iter ); - continue; - } + qWarning() << Q_FUNC_INFO << "Tried to get track position to remove, but either couldn't convert to int, or out of bounds:" << ok << pos << entries.size() << entries << trackPositions; + continue; } + + toRemove << entries.at(pos); } - qDebug() << "We were asked to delete:" << tracks.size() << "tracks from the playlist, and we deleted:" << ( playlist()->entries().size() - entries.size() ); + + // Now remove them all + foreach( const plentry_ptr& torm, toRemove ) + entries.removeAll( torm ); + + + m_plRevisionBeforeUpdate = playlist()->currentrevision(); + + qDebug() << "We were asked to delete:" << trackPositions.size() << "tracks from the playlist, and we deleted:" << ( playlist()->entries().size() - entries.size() ); + if ( trackPositions.size() != ( playlist()->entries().size() - entries.size() ) ) + qWarning() << "========================= Failed to delete all the tracks we were asked for!! Didn't find some indicesss... ==================="; + + playlist()->createNewRevision( uuid(), playlist()->currentrevision(), entries ); } @@ -200,6 +210,12 @@ SpotifyPlaylistUpdater::spotifyTracksMoved( const QVariantList& tracks, const QS void SpotifyPlaylistUpdater::tomahawkTracksInserted( const QList< plentry_ptr >& tracks, int pos ) { + if ( playlist()->currentrevision() == m_plRevisionBeforeUpdate ) + { + // We did the insert. Don't get in an infinite loop! + return; + } + // Notify the resolver that we've updated qDebug() << Q_FUNC_INFO << "updating spotify resolver with inserted tracks at:" << pos << tracks; QVariantMap msg; diff --git a/src/accounts/spotify/SpotifyPlaylistUpdater.h b/src/accounts/spotify/SpotifyPlaylistUpdater.h index c6350f15c..ea2cf6543 100644 --- a/src/accounts/spotify/SpotifyPlaylistUpdater.h +++ b/src/accounts/spotify/SpotifyPlaylistUpdater.h @@ -74,6 +74,7 @@ private: Tomahawk::Accounts::SpotifyAccount* m_spotify; QString m_latestRev, m_spotifyId; + QString m_plRevisionBeforeUpdate; bool m_sync; }; diff --git a/src/libtomahawk/aclregistry.cpp b/src/libtomahawk/aclregistry.cpp index f561490de..d3261f15c 100644 --- a/src/libtomahawk/aclregistry.cpp +++ b/src/libtomahawk/aclregistry.cpp @@ -43,9 +43,10 @@ ACLRegistry::ACLRegistry( QObject* parent ) : QObject( parent ) { s_instance = this; - qRegisterMetaType< ACLRegistry::ACL >("ACLRegistry::ACL"); + qRegisterMetaType< ACLRegistry::ACL >( "ACLRegistry::ACL" ); + qRegisterMetaType< ACLRegistry::User >( "ACLRegistry::User" ); - m_cache = TomahawkSettings::instance()->aclEntries(); + load(); } @@ -55,174 +56,77 @@ ACLRegistry::~ACLRegistry() void -ACLRegistry::isAuthorizedPeer( const QString& dbid, ACLRegistry::ACL globalType, const QString &username ) +ACLRegistry::isAuthorizedUser( const QString& dbid, const QString &username, ACLRegistry::ACL globalType ) { if ( QThread::currentThread() != TOMAHAWK_APPLICATION::instance()->thread() ) { - emit aclResult( dbid, globalType ); + emit aclResult( dbid, username, globalType ); return; } - - qDebug() << "Current cache keys =" << m_cache.keys(); - if( m_cache.contains( dbid ) ) + + bool found = false; + QMutableListIterator< ACLRegistry::User > i( m_cache ); + while ( i.hasNext() ) { - QVariantHash peerHash = m_cache[ dbid ].toHash(); - if( peerHash.contains( "global" ) ) + ACLRegistry::User user = i.next(); + foreach ( QString knowndbid, user.knownDbids ) { - registerAlias( dbid, username ); - emit aclResult( dbid, ACLRegistry::ACL( peerHash[ "global" ].toInt() ) ); + if ( dbid == knowndbid ) + { + if ( !user.knownAccountIds.contains( username ) ) + user.knownAccountIds.append( username ); + found = true; + } + } + + foreach ( QString knownaccountid, user.knownAccountIds ) + { + if ( username == knownaccountid ) + { + if ( !user.knownDbids.contains( dbid ) ) + user.knownDbids.append( dbid ); + found = true; + } + } + + if ( found ) + { + emit aclResult( dbid, username, user.acl ); + i.setValue( user ); + return; + } + } + + // User was not found, create a new user entry + ACLRegistry::User user; + user.knownDbids.append( dbid ); + user.knownAccountIds.append( username ); + if ( globalType != ACLRegistry::NotFound ) + user.acl = globalType; + else + { + ACLRegistry::ACL acl = globalType; + tDebug( LOGVERBOSE ) << "ACL is intially" << acl; + #ifndef ENABLE_HEADLESS + acl = getUserDecision( username ); + tDebug( LOGVERBOSE ) << "after getUserDecision acl is" << acl; + #endif + + if ( acl == ACLRegistry::NotFound ) + { + emit aclResult( dbid, username, acl ); return; } - if ( globalType == ACLRegistry::NotFound ) - { - emit aclResult( dbid, globalType ); - return; - } - - peerHash[ "global" ] = int( globalType ); - m_cache[ dbid ] = peerHash; - save(); - registerAlias( dbid, username ); - emit aclResult( dbid, globalType ); - return; + user.acl = acl; } - ACLRegistry::ACL acl = globalType; - tDebug( LOGVERBOSE ) << "ACL is intially" << acl; -#ifndef ENABLE_HEADLESS - acl = getUserDecision( username ); - tDebug( LOGVERBOSE ) << "after getUserDecision acl is" << acl; -#endif - - if ( acl == ACLRegistry::NotFound || acl == ACLRegistry::AllowOnce || acl == ACLRegistry::DenyOnce ) - { - emit aclResult( dbid, acl ); - return; - } - - QVariantHash peerHash; - peerHash[ "global" ] = int( acl ); - m_cache[ dbid ] = peerHash; - save(); - registerAlias( dbid, username ); - emit aclResult( dbid, acl ); + m_cache.append( user ); + emit aclResult( dbid, username, user.acl ); return; } -void -ACLRegistry::registerPeer( const QString& dbid, ACLRegistry::ACL globalType, const QString &username ) -{ - if ( QThread::currentThread() != TOMAHAWK_APPLICATION::instance()->thread() ) - return; - - if ( globalType == ACLRegistry::NotFound || globalType == ACLRegistry::DenyOnce || globalType == ACLRegistry::AllowOnce ) - return; - - QVariantHash peerHash; - if ( m_cache.contains( dbid ) ) - peerHash = m_cache[ dbid ].toHash(); - peerHash[ "global" ] = int( globalType ); - m_cache[ dbid ] = peerHash; - save(); - registerAlias( dbid, username ); -} - - -QPair< QString, ACLRegistry::ACL > -ACLRegistry::isAuthorizedUser( const QString &username, ACLRegistry::ACL globalType ) -{ - if ( QThread::currentThread() != TOMAHAWK_APPLICATION::instance()->thread() ) - return QPair< QString, ACLRegistry::ACL >( QString(), ACLRegistry::NotFound ); - - qDebug() << "Current cache keys =" << m_cache.keys(); - foreach ( QString dbid, m_cache.keys() ) - { - // qDebug() << "Looking up dbid"; - QVariantHash peerHash = m_cache[ dbid ].toHash(); - if ( !peerHash.contains( "usernames" ) ) - continue; - - if ( !peerHash[ "usernames" ].toStringList().contains( username ) ) - continue; - - if ( globalType != ACLRegistry::NotFound ) - { - peerHash[ "global" ] = int( globalType ); - m_cache[ dbid ] = peerHash; - save(); - return QPair< QString, ACLRegistry::ACL >( dbid, globalType ); - } - - return QPair< QString, ACLRegistry::ACL >( dbid, ACLRegistry::ACL( peerHash[ "global" ].toInt() ) ); - } - - return QPair< QString, ACLRegistry::ACL >( QString(), ACLRegistry::NotFound ); -} - - -void -ACLRegistry::registerAlias( const QString& dbid, const QString &username ) -{ - if ( QThread::currentThread() != TOMAHAWK_APPLICATION::instance()->thread() ) - return; - - if ( dbid.isEmpty() || username.isEmpty() ) - return; - - if ( !m_cache.contains( dbid ) ) - return; - - QVariantHash peerHash = m_cache[ dbid ].toHash(); - if ( !peerHash.contains( "usernames" ) ) - peerHash[ "usernames" ] = QStringList( username ); - else if ( !peerHash[ "usernames" ].toStringList().contains( username ) ) - peerHash[ "usernames" ] = peerHash[ "usernames" ].toStringList() + QStringList( username ); - else - return; - - m_cache[ dbid ] = peerHash; - save(); -} - - -// ACLRegistry::ACL -// ACLRegistry::isAuthorizedPath( const QString& dbid, const QString& path ) -// { -// QMutexLocker locker( &m_cacheMutex ); -// -// if( !m_cache.contains( dbid ) ) -// return ACLRegistry::NotFound; -// -// QHash< QString, ACL > peerHash = m_cache[dbid]; -// if( !peerHash.contains( path ) ) -// { -// if( peerHash.contains( "global" ) ) -// return peerHash["global"]; -// else -// return ACLRegistry::Deny; -// } -// return peerHash[path]; -// } -// -// void -// ACLRegistry::authorizePath( const QString& dbid, const QString& path, ACLRegistry::ACL type ) -// { -// TomahawkSettings *s = TomahawkSettings::instance(); -// if( !s->scannerPaths().contains( path ) ) -// { -// qDebug() << "path selected is not in our scanner path!"; -// return; -// } -// QMutexLocker locker( &m_cacheMutex ); -// QHash< QString, ACLRegistry::ACL > peerHash; -// if ( m_cache.contains( dbid ) ) -// peerHash = m_cache[dbid]; -// peerHash[path] = type; -// m_cache[dbid] = peerHash; -// } - #ifndef ENABLE_HEADLESS #include @@ -230,14 +134,13 @@ ACLRegistry::registerAlias( const QString& dbid, const QString &username ) ACLRegistry::ACL ACLRegistry::getUserDecision( const QString &username ) { + return ACLRegistry::Stream; QMessageBox msgBox; msgBox.setIcon( QMessageBox::Question ); msgBox.setText( tr( "Connect to Peer?" ) ); msgBox.setInformativeText( tr( "Another Tomahawk instance that claims to be owned by %1 is attempting to connect to you. Select whether to allow or deny this connection.\n\nRemember: Only allow peers to connect if you trust who they are and if you have the legal right for them to stream music from you.").arg( username ) ); - QPushButton *denyButton = msgBox.addButton( tr( "Deny" ), QMessageBox::HelpRole ); - QPushButton *alwaysDenyButton = msgBox.addButton( tr( "Always Deny" ), QMessageBox::YesRole ); - QPushButton *allowButton = msgBox.addButton( tr( "Allow" ), QMessageBox::NoRole ); - QPushButton *alwaysAllowButton = msgBox.addButton( tr( "Always Allow" ), QMessageBox::ActionRole ); + QPushButton *denyButton = msgBox.addButton( tr( "Deny" ), QMessageBox::YesRole ); + QPushButton *allowButton = msgBox.addButton( tr( "Allow" ), QMessageBox::ActionRole ); msgBox.setDefaultButton( allowButton ); msgBox.setEscapeButton( denyButton ); @@ -245,13 +148,9 @@ ACLRegistry::getUserDecision( const QString &username ) msgBox.exec(); if( msgBox.clickedButton() == denyButton ) - return ACLRegistry::DenyOnce; - else if( msgBox.clickedButton() == alwaysDenyButton ) return ACLRegistry::Deny; else if( msgBox.clickedButton() == allowButton ) - return ACLRegistry::AllowOnce; - else if( msgBox.clickedButton() == alwaysAllowButton ) - return ACLRegistry::Allow; + return ACLRegistry::Stream; //How could we get here? tDebug( LOGVERBOSE ) << "ERROR: returning NotFound"; @@ -261,8 +160,26 @@ ACLRegistry::getUserDecision( const QString &username ) #endif + +void +ACLRegistry::load() +{ + QVariantList entryList = TomahawkSettings::instance()->aclEntries(); + foreach ( QVariant entry, entryList ) + { + if ( !entry.isValid() || !entry.canConvert< ACLRegistry::User >() ) + continue; + ACLRegistry::User entryUser = entry.value< ACLRegistry::User >(); + m_cache.append( entryUser ); + } +} + + void ACLRegistry::save() { - TomahawkSettings::instance()->setAclEntries( m_cache ); + QVariantList entryList; + foreach ( ACLRegistry::User user, m_cache ) + entryList.append( QVariant::fromValue< ACLRegistry::User >( user ) ); + TomahawkSettings::instance()->setAclEntries( entryList ); } \ No newline at end of file diff --git a/src/libtomahawk/aclregistry.h b/src/libtomahawk/aclregistry.h index 8d6e2fcda..c9231ad90 100644 --- a/src/libtomahawk/aclregistry.h +++ b/src/libtomahawk/aclregistry.h @@ -39,46 +39,35 @@ public: static ACLRegistry* instance(); enum ACL { - Allow = 0, + NotFound = 0, Deny = 1, - NotFound = 2, - AllowOnce = 3, - DenyOnce = 4 + Read = 2, + Stream = 3 + }; + + struct User { + QString uuid; + QStringList knownDbids; + QStringList knownAccountIds; + ACL acl; + + User() + : uuid( QUuid::createUuid().toString() ) + {} + + User( QString p_uuid, QStringList p_knownDbids, QStringList p_knownAccountIds, ACL p_acl ) + : uuid( p_uuid ) + , knownDbids( p_knownDbids ) + , knownAccountIds( p_knownAccountIds ) + , acl( p_acl ) + {} }; ACLRegistry( QObject *parent = 0 ); ~ACLRegistry(); - - /** - * @brief Registers the global ACL value for this peer - * - * @param dbid DBID of peer - * @param globalType Global ACL to use for this peer. ACLRegistry::NotFound is invalid and will return immediately. - * @param username If not empty, will store the given username along with the new ACL value. Defaults to QString(). - * @return void - **/ - void registerPeer( const QString &dbid, ACLRegistry::ACL globalType, const QString &username = QString() ); - - /** - * @brief Checks if peer is authorized, using the username. Optionally, can change authorization of the peer, but only if the peer is found. - * - * @param username Username for the peer - * @param globalType Global ACL to store if peer is found; if ACLRegistry::NotFound, does not change the ACL. Defaults to ACLRegistry::NotFound. - * @return QPair< QString, ACLRegistry::ACL > - **/ - QPair< QString, ACLRegistry::ACL > isAuthorizedUser( const QString &username, ACLRegistry::ACL globalType = ACLRegistry::NotFound ); - - /** - * @brief Registers an alias for a known peer. If you do not know the DBID, you can retrieve it via isAuthorizedUser first. - * - * @param dbid DBID of peer - * @param username Username of the peer to be added to the entry - * @return void - **/ - void registerAlias( const QString &dbid, const QString &username ); signals: - void aclResult( QString nodeid, ACLRegistry::ACL peerStatus ); + void aclResult( QString nodeid, QString username, ACLRegistry::ACL peerStatus ); public slots: /** @@ -89,16 +78,13 @@ public slots: * @param username If not empty, will store the given username along with the new ACL value. Defaults to QString(). * @return ACLRegistry::ACL **/ - void isAuthorizedPeer( const QString &dbid, ACLRegistry::ACL globalType = ACLRegistry::NotFound, const QString &username = QString() ); + void isAuthorizedUser( const QString &dbid, const QString &username, ACLRegistry::ACL globalType = ACLRegistry::NotFound ); #ifndef ENABLE_HEADLESS ACLRegistry::ACL getUserDecision( const QString &username ); #endif -// ACLRegistry::ACL isAuthorizedPath( const QString &dbid, const QString &path ); -// void authorizePath( const QString &dbid, const QString &path, ACLRegistry::ACL type ); - private: /** * @brief Saves the cache. @@ -107,9 +93,14 @@ private: **/ void save(); - QVariantHash m_cache; + void load(); + + QList< ACLRegistry::User > m_cache; static ACLRegistry* s_instance; }; +Q_DECLARE_METATYPE( ACLRegistry::ACL ); +Q_DECLARE_METATYPE( ACLRegistry::User ); + #endif // TOMAHAWK_ACLREGISTRY_H diff --git a/src/libtomahawk/network/connection.cpp b/src/libtomahawk/network/connection.cpp index 8da4c9418..f162b7d51 100644 --- a/src/libtomahawk/network/connection.cpp +++ b/src/libtomahawk/network/connection.cpp @@ -199,20 +199,20 @@ Connection::checkACL() QString nodeid = property( "nodeid" ).toString(); tDebug( LOGVERBOSE ) << "Checking ACL for" << name(); - connect( ACLRegistry::instance(), SIGNAL( aclResult( QString, ACLRegistry::ACL ) ), this, SLOT( checkACLResult( QString, ACLRegistry::ACL ) ), Qt::QueuedConnection ); - QMetaObject::invokeMethod( ACLRegistry::instance(), "isAuthorizedPeer", Qt::QueuedConnection, Q_ARG( QString, nodeid ), Q_ARG( ACLRegistry::ACL, ACLRegistry::NotFound ), Q_ARG( QString, name() ) ); + connect( ACLRegistry::instance(), SIGNAL( aclResult( QString, QString, ACLRegistry::ACL ) ), this, SLOT( checkACLResult( QString, QString, ACLRegistry::ACL ) ), Qt::QueuedConnection ); + QMetaObject::invokeMethod( ACLRegistry::instance(), "isAuthorizedUser", Qt::QueuedConnection, Q_ARG( QString, nodeid ), Q_ARG( QString, name() ), Q_ARG( ACLRegistry::ACL, ACLRegistry::NotFound ) ); } void -Connection::checkACLResult( const QString &nodeid, ACLRegistry::ACL peerStatus ) +Connection::checkACLResult( const QString &nodeid, const QString &username, ACLRegistry::ACL peerStatus ) { - if ( nodeid != property( "nodeid" ).toString() ) + if ( nodeid != property( "nodeid" ).toString() || username != name() ) return; - disconnect( ACLRegistry::instance(), SIGNAL( aclResult( QString, ACLRegistry::ACL ) ) ); + disconnect( ACLRegistry::instance(), SIGNAL( aclResult( QString, QString, ACLRegistry::ACL ) ) ); tDebug( LOGVERBOSE ) << "ACL status is" << peerStatus; - if ( peerStatus == ACLRegistry::Allow || peerStatus == ACLRegistry::AllowOnce ) + if ( peerStatus == ACLRegistry::Stream ) { QTimer::singleShot( 0, this, SLOT( doSetup() ) ); return; diff --git a/src/libtomahawk/network/connection.h b/src/libtomahawk/network/connection.h index 275688da7..d5b5e93b2 100644 --- a/src/libtomahawk/network/connection.h +++ b/src/libtomahawk/network/connection.h @@ -120,7 +120,7 @@ private slots: void readyRead(); void doSetup(); void checkACL(); - void checkACLResult( const QString &id, ACLRegistry::ACL peerStatus ); + void checkACLResult( const QString &nodeid, const QString &username, ACLRegistry::ACL peerStatus ); void authCheckTimeout(); void bytesWritten( qint64 ); void calcStats(); diff --git a/src/libtomahawk/playlist.cpp b/src/libtomahawk/playlist.cpp index 8ba8e5670..c2fde61e1 100644 --- a/src/libtomahawk/playlist.cpp +++ b/src/libtomahawk/playlist.cpp @@ -316,6 +316,10 @@ Playlist::createNewRevision( const QString& newrev, const QString& oldrev, const foreach( const plentry_ptr& p, entries ) orderedguids << p->guid(); + qDebug() << "INSERTING ORDERED GUIDS:" << orderedguids << "and with new entries:"; + foreach( const plentry_ptr& p, added ) + qDebug() << p->guid(); + // source making the change (local user in this case) source_ptr author = SourceList::instance()->getLocal(); // command writes new rev to DB and calls setRevision, which emits our signal @@ -396,20 +400,38 @@ Playlist::setNewRevision( const QString& rev, // existing ones, and the ones that have been added QMap entriesmap; foreach ( const plentry_ptr& p, m_entries ) + { + qDebug() << p->guid() << p->query()->track() << p->query()->artist(); entriesmap.insert( p->guid(), p ); + } + QList entries; + qDebug() << "Going through neworderedguids:" << neworderedguids << neworderedguids.size(); foreach ( const QString& id, neworderedguids ) { if ( entriesmap.contains( id ) ) { + qDebug() << "Adding original entry to entries:" << id; entries.append( entriesmap.value( id ) ); } else if ( addedmap.contains( id ) ) { + qDebug() << "Adding new entry to entries:" << id << addedmap.value( id ); + if( ! addedmap.value( id ).isNull() ) qDebug() << addedmap.value( id )->query()->track() << addedmap.value( id )->query()->artist(); entries.append( addedmap.value( id ) ); if ( is_newest_rev ) - m_entries.append( addedmap.value( id ) ); + { + // We want to insert the new entries into the appropriate place in m_entries, not just at the end. so find the index in neworderedguids, and use that. since we go from 0, + // it should be valid + int insertIdx = neworderedguids.indexOf( id ); + if ( insertIdx < 0 || insertIdx > m_entries.size() ) + { + qWarning() << "Trying to insert new track in a playlist, but beyond the end! Appending at end to be safe"; + insertIdx = m_entries.size(); + } + m_entries.insert( insertIdx, addedmap.value( id ) ); + } } else { @@ -423,6 +445,7 @@ Playlist::setNewRevision( const QString& rev, Q_ASSERT( false ); // XXX } } + qDebug() << "and got:" << entries.size() << entries << m_entries.size() << m_entries; PlaylistRevision pr; pr.oldrevisionguid = m_currentrevision; @@ -535,16 +558,24 @@ Playlist::insertEntries( const QList< query_ptr >& queries, const int position, QList toInsert = entriesFromQueries( queries, true ); QList entries = m_entries; - Q_ASSERT( position < m_entries.size() ); - if ( position >= m_entries.size() ) + Q_ASSERT( position <= m_entries.size() ); + if ( position > m_entries.size() ) { qWarning() << "ERROR trying to insert tracks past end of playlist! Appending!!"; addEntries( queries, oldrev ); return; } - for ( QList< plentry_ptr >::iterator iter = toInsert.end(); iter != toInsert.begin(); iter-- ) - entries.insert( position, *iter ); + qDebug() << "inserting entries. GUIDs before:"; + foreach( const plentry_ptr& p, entries ) + qDebug() << p->guid(); + + for ( int i = toInsert.size()-1; i >= 0; --i ) + entries.insert( position, toInsert.at(i) ); + + qDebug() << "inserting entries. GUIDs AFTER:"; + foreach( const plentry_ptr& p, entries ) + qDebug() << p->guid(); const int prevSize = m_entries.size(); qDebug() << "Done inserting playlist entries in the middle of the playlist! Committing..."; diff --git a/src/libtomahawk/playlist/PlaylistUpdaterInterface.cpp b/src/libtomahawk/playlist/PlaylistUpdaterInterface.cpp index 6102538c1..56a8a688e 100644 --- a/src/libtomahawk/playlist/PlaylistUpdaterInterface.cpp +++ b/src/libtomahawk/playlist/PlaylistUpdaterInterface.cpp @@ -54,7 +54,6 @@ PlaylistUpdaterInterface::loadForPlaylist( const playlist_ptr& pl ) if ( !updater ) { - Q_ASSERT( false ); return 0; } updater->setAutoUpdate( s->value( QString( "%1/autoupdate" ).arg( key ) ).toBool() ); diff --git a/src/libtomahawk/playlist/playlistmodel.cpp b/src/libtomahawk/playlist/playlistmodel.cpp index 97264accc..2a87b7488 100644 --- a/src/libtomahawk/playlist/playlistmodel.cpp +++ b/src/libtomahawk/playlist/playlistmodel.cpp @@ -91,6 +91,11 @@ PlaylistModel::loadPlaylist( const Tomahawk::playlist_ptr& playlist, bool loadEn } QList entries = playlist->entries(); + + qDebug() << "playlist loading entries:"; + foreach( const plentry_ptr& p, entries ) + qDebug() << p->guid(); + append( entries ); m_isLoading = false; diff --git a/src/libtomahawk/tomahawksettings.cpp b/src/libtomahawk/tomahawksettings.cpp index 58eded73c..ff40668fb 100644 --- a/src/libtomahawk/tomahawksettings.cpp +++ b/src/libtomahawk/tomahawksettings.cpp @@ -628,19 +628,19 @@ TomahawkSettings::setProxyDns( bool lookupViaProxy ) } -QVariantHash +QVariantList TomahawkSettings::aclEntries() const { - QVariant retVal = value( "acl/entries", QVariantHash() ); - if ( retVal.isValid() && retVal.canConvert< QVariantHash >() ) - return retVal.toHash(); + QVariant retVal = value( "acl/entries", QVariantList() ); + if ( retVal.isValid() && retVal.canConvert< QVariantList >() ) + return retVal.toList(); - return QVariantHash(); + return QVariantList(); } void -TomahawkSettings::setAclEntries( const QVariantHash &entries ) +TomahawkSettings::setAclEntries( const QVariantList &entries ) { setValue( "acl/entries", entries ); } diff --git a/src/libtomahawk/tomahawksettings.h b/src/libtomahawk/tomahawksettings.h index 3cdfe7b45..5200bc524 100644 --- a/src/libtomahawk/tomahawksettings.h +++ b/src/libtomahawk/tomahawksettings.h @@ -163,8 +163,8 @@ public: void setProxyDns( bool lookupViaProxy ); /// ACL settings - QVariantHash aclEntries() const; - void setAclEntries( const QVariantHash &entries ); + QVariantList aclEntries() const; + void setAclEntries( const QVariantList &entries ); /// XMPP Component Settings QString xmppBotServer() const;