mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-04-13 12:31:52 +02:00
first saving non-working commit
This commit is contained in:
parent
b45c254081
commit
5b23b6ad81
@ -118,7 +118,7 @@ public:
|
||||
// these need to exist and be public for the json serialization stuff
|
||||
// you SHOULD NOT call them. They are used for an alternate CTOR method from json.
|
||||
// maybe friend QObjectHelper and make them private?
|
||||
Playlist( const source_ptr& author )
|
||||
explicit Playlist( const source_ptr& author )
|
||||
: m_source( author )
|
||||
, m_lastmodified( 0 )
|
||||
{
|
||||
@ -155,7 +155,7 @@ public slots:
|
||||
|
||||
void resolve();
|
||||
|
||||
private:
|
||||
protected:
|
||||
// called from loadAllPlaylists DB cmd:
|
||||
explicit Playlist( const source_ptr& src,
|
||||
const QString& currentrevision,
|
||||
@ -173,9 +173,14 @@ private:
|
||||
const QString& info,
|
||||
const QString& creator,
|
||||
bool shared );
|
||||
|
||||
void rundb();
|
||||
|
||||
|
||||
QList<plentry_ptr> newEntries( const QList< plentry_ptr >& entries );
|
||||
PlaylistRevision setNewRevision( const QString& rev,
|
||||
const QList<QString>& neworderedguids,
|
||||
const QList<QString>& oldorderedguids,
|
||||
bool is_newest_rev,
|
||||
const QMap< QString, Tomahawk::plentry_ptr >& addedmap );
|
||||
private:
|
||||
source_ptr m_source;
|
||||
QString m_currentrevision;
|
||||
QString m_guid, m_title, m_info, m_creator;
|
||||
|
@ -11,6 +11,7 @@ namespace Tomahawk
|
||||
class Collection;
|
||||
class Playlist;
|
||||
class PlaylistEntry;
|
||||
class DynamicPlaylist;
|
||||
class Query;
|
||||
class Result;
|
||||
class Source;
|
||||
@ -18,6 +19,7 @@ namespace Tomahawk
|
||||
typedef QSharedPointer<Collection> collection_ptr;
|
||||
typedef QSharedPointer<Playlist> playlist_ptr;
|
||||
typedef QSharedPointer<PlaylistEntry> plentry_ptr;
|
||||
typedef QSharedPointer<DynamicPlaylist> dynplaylist_ptr;
|
||||
typedef QSharedPointer<Query> query_ptr;
|
||||
typedef QSharedPointer<Result> result_ptr;
|
||||
typedef QSharedPointer<Source> source_ptr;
|
||||
|
@ -91,6 +91,10 @@ SET( tomahawkSources ${tomahawkSources}
|
||||
database/databasecommand_updatesearchindex.cpp
|
||||
database/databasecollection.cpp
|
||||
|
||||
dynamic/dynamicplaylist.cpp
|
||||
dynamic/dynamiccontrol.cpp
|
||||
dynamic/generatorfactory.cpp
|
||||
|
||||
scrobbler.cpp
|
||||
xmppbot/xmppbot.cpp
|
||||
web/api_v1.cpp
|
||||
@ -222,6 +226,11 @@ SET( tomahawkHeaders ${tomahawkHeaders}
|
||||
network/filetransferconnection.h
|
||||
network/dbsyncconnection.h
|
||||
|
||||
dynamic/dynamicplaylist.h
|
||||
dynamic/dynamiccontrol.h
|
||||
dynamic/generatorfactory.h
|
||||
dynamic/generatorinterface.h
|
||||
|
||||
musicscanner.h
|
||||
scriptresolver.h
|
||||
tomahawksettings.h
|
||||
@ -308,6 +317,7 @@ INCLUDE_DIRECTORIES(
|
||||
sourcetree
|
||||
topbar
|
||||
utils
|
||||
dynamic
|
||||
|
||||
../rtaudio
|
||||
../alsa-playback
|
||||
|
0
src/dynamic/dynamiccontrol.cpp
Normal file
0
src/dynamic/dynamiccontrol.cpp
Normal file
6
src/dynamic/dynamiccontrol.h
Normal file
6
src/dynamic/dynamiccontrol.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef DYNAMIC_PLAYLIST_CONTROL
|
||||
#define DYNAMIC_PLAYLIST_CONTROL
|
||||
|
||||
|
||||
|
||||
#endif
|
238
src/dynamic/dynamicplaylist.cpp
Normal file
238
src/dynamic/dynamicplaylist.cpp
Normal file
@ -0,0 +1,238 @@
|
||||
#include "dynamicplaylist.h"
|
||||
|
||||
#include "tomahawk/tomahawkapp.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
// Called by loadAllPlaylists command
|
||||
DynamicPlaylist::DynamicPlaylist ( const Tomahawk::source_ptr& src,
|
||||
const QString& currentrevision,
|
||||
const QString& title,
|
||||
const QString& info,
|
||||
const QString& creator,
|
||||
const QString& type,
|
||||
bool shared,
|
||||
int lastmod,
|
||||
const QString& guid )
|
||||
: Playlist( src, currentrevision, title, info, creator, shared, lastmod, guid )
|
||||
{
|
||||
qDebug() << "Creating Dynamic Playlist 1";
|
||||
// TODO instantiate generator
|
||||
}
|
||||
|
||||
|
||||
// called when a new playlist is created (no currentrevision, new guid)
|
||||
DynamicPlaylist::DynamicPlaylist ( const Tomahawk::source_ptr& author,
|
||||
const QString& guid,
|
||||
const QString& title,
|
||||
const QString& info,
|
||||
const QString& creator,
|
||||
const QString& type,
|
||||
bool shared )
|
||||
: Playlist ( author, guid, title, info, creator, shared )
|
||||
{
|
||||
qDebug() << "Creating Dynamic Playlist 2";
|
||||
// TODO instantiate generator
|
||||
}
|
||||
|
||||
dynplaylist_ptr DynamicPlaylist::create( const Tomahawk::source_ptr& author,
|
||||
const QString& guid,
|
||||
const QString& title,
|
||||
const QString& info,
|
||||
const QString& creator,
|
||||
bool shared )
|
||||
{
|
||||
// TODO default generator?
|
||||
QString type = "default_generator";
|
||||
dynplaylist_ptr dynplaylist = new dynplaylist_ptr( new DynamicPlaylist( author, guid, title, info, creator, type, shared ) );
|
||||
|
||||
DatabaseCommand_CreateDynamicPlaylist* cmd = new DatabaseCommand_CreateDynamicPlaylist( author, dynplaylist );
|
||||
connect( cmd, SIGNAL(finished()), dynplaylist.data(), SIGNAL(created()) );
|
||||
APP->database()->enqueue( QSharedPointer<DatabaseCommand>(cmd) );
|
||||
dynplaylist->reportCreated( dynplaylist );
|
||||
return dynplaylist;
|
||||
|
||||
}
|
||||
|
||||
// create a new revision that will be a static playlist, as it has entries
|
||||
void DynamicPlaylist::createNewRevision( const QString& newrev,
|
||||
const QString& oldrev,
|
||||
const QString& type,
|
||||
const QList< dyncontrol_ptr>& controls,
|
||||
const QList< plentry_ptr >& entries )
|
||||
{
|
||||
// get the newly added tracks
|
||||
QList< plentry_ptr > added = newEntries( entries );
|
||||
|
||||
QStringList orderedguids;
|
||||
foreach( plentry_ptr p, entries )
|
||||
orderedguids << p->guid();
|
||||
|
||||
// no conflict resolution or partial updating for controls. all or nothing baby
|
||||
|
||||
// source making the change (localy user in this case)
|
||||
source_ptr author = APP->sourcelist().getLocal();
|
||||
// command writes new rev to DB and calls setRevision, which emits our signal
|
||||
DatabaseCommand_SetDynamicPlaylistRevision* cmd =
|
||||
new DatabaseCommand_SetDynamicPlaylistRevision( author,
|
||||
guid(),
|
||||
newrev,
|
||||
oldrev,
|
||||
orderedguids,
|
||||
added,
|
||||
type,
|
||||
STATIC,
|
||||
controls );
|
||||
APP->database()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||
}
|
||||
|
||||
// create a new revision that will be an ondemand playlist, as it has no entries
|
||||
void DynamicPlaylist::createNewRevision( const QString& newrev,
|
||||
const QString& oldrev,
|
||||
const QString& type,
|
||||
const QList< dyncontrol_ptr>& controls )
|
||||
{
|
||||
// can skip the entry stuff. just overwrite with new info
|
||||
source_ptr author = APP->sourcelist().getLocal();
|
||||
// command writes new rev to DB and calls setRevision, which emits our signal
|
||||
DatabaseCommand_SetDynamicPlaylistRevision* cmd =
|
||||
new DatabaseCommand_SetDynamicPlaylistRevision( author,
|
||||
guid(),
|
||||
newrev,
|
||||
oldrev,
|
||||
type,
|
||||
STATIC,
|
||||
controls );
|
||||
APP->database()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||
}
|
||||
|
||||
void DynamicPlaylist::loadRevision( const QString& rev )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
DatabaseCommand_LoadDynamicPlaylist* cmd =
|
||||
new DatabaseCommand_LoadDynamicPlaylist( rev.isEmpty() ? currentrevision() : rev, m_generator->mode() );
|
||||
|
||||
if( m_generator->mode() == ONDEMAND ) {
|
||||
connect( cmd, SIGNAL( done( QString,
|
||||
bool,
|
||||
const QString,
|
||||
QList< dyncontrol_ptr>,
|
||||
bool ) ),
|
||||
SLOT( setRevision( QString,
|
||||
bool,
|
||||
const QString,
|
||||
QList< dyncontrol_ptr>,
|
||||
bool) ) );
|
||||
} else if( m_generator->mode() == STATIC ) {
|
||||
connect( cmd, SIGNAL( done( QString,
|
||||
QList< QString >,
|
||||
QList< QString >,
|
||||
QString,
|
||||
QList< dyncontrol_ptr>,
|
||||
bool,
|
||||
const QMap< QString, Tomahawk::plentry_ptr >,
|
||||
bool ) ),
|
||||
SLOT( setRevision( QString,
|
||||
QList< QString >,
|
||||
QList< QString >,
|
||||
QString,
|
||||
QList< dyncontrol_ptr>,
|
||||
bool,
|
||||
const QMap< QString, Tomahawk::plentry_ptr >,
|
||||
bool ) ) );
|
||||
|
||||
}
|
||||
APP->database()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||
}
|
||||
|
||||
bool DynamicPlaylist::remove( const Tomahawk::dynplaylist_ptr& playlist )
|
||||
{
|
||||
return remove( playlist.staticCast<Tomahawk::playlist_ptr>() );
|
||||
}
|
||||
|
||||
void DynamicPlaylist::reportCreated( const Tomahawk::dynplaylist_ptr& self )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
Q_ASSERT( self.data() == this );
|
||||
// will emit Collection::playlistCreated(...)
|
||||
m_source->collection()->addPlaylist( self.staticCast<Tomahawk::playlist_ptr>() );
|
||||
}
|
||||
|
||||
void DynamicPlaylist::reportDeleted( const Tomahawk::dynplaylist_ptr& self )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
Q_ASSERT( self.data() == this );
|
||||
// will emit Collection::playlistCreated(...)
|
||||
m_source->collection()->deletePlaylist( self.staticCast<Tomahawk::playlist_ptr>() );
|
||||
}
|
||||
|
||||
// static version
|
||||
void DynamicPlaylist::setRevision( const QString& rev,
|
||||
const QList< QString >& neworderedguids,
|
||||
const QList< QString >& oldorderedguids,
|
||||
const QString& type,
|
||||
const QList< dyncontrol_ptr>& controls,
|
||||
bool is_newest_rev,
|
||||
const QMap< QString, plentry_ptr >& addedmap,
|
||||
bool applied )
|
||||
{
|
||||
// we're probably being called by a database worker thread
|
||||
if( QThread::currentThread() != thread() )
|
||||
{
|
||||
QMetaObject::invokeMethod( this,
|
||||
"setRevision",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_ARG( QString, rev ),
|
||||
Q_ARG( QList<QString>, neworderedguids ),
|
||||
Q_ARG( QList<QString>, oldorderedguids ),
|
||||
Q_ARG( QString, type ),
|
||||
QGenericArgument( "QList< dyncontrol_ptr >" , (const void*)&controls ),
|
||||
Q_ARG( bool, is_newest_rev ),
|
||||
QGenericArgument( "QMap< QString,Tomahawk::plentry_ptr >" , (const void*)&addedmap ),
|
||||
Q_ARG( bool, applied ) );
|
||||
return;
|
||||
}
|
||||
if( m_generator->type() != type ) { // new generator needed
|
||||
m_generator = generatorinterface_ptr( GeneratorFactory::create( type ) );
|
||||
}
|
||||
|
||||
m_generator->setControls( controls );
|
||||
m_generator->setMode( ONDEMAND )
|
||||
|
||||
DynamicPlaylistRevision pr = DynamicPlaylistRevision( setNewRevision( rev, neworderedguids, oldorderedguids, is_newest_rev, addedmap ) );
|
||||
pr.controls = controls;
|
||||
pr.type = type;
|
||||
pr.mode = STATIC;
|
||||
|
||||
if( applied )
|
||||
setCurrentRevision( rev );
|
||||
pr.applied = applied;
|
||||
|
||||
emit revisionLoaded( pr );
|
||||
}
|
||||
|
||||
// ondemand version
|
||||
void DynamicPlaylist::setRevision( const QString& rev,
|
||||
bool is_newest_rev,
|
||||
const QString& type,
|
||||
const QList< dyncontrol_ptr>& controls,
|
||||
bool applied )
|
||||
{
|
||||
if( m_generator->type() != type ) { // new generator needed
|
||||
m_generator = generatorinterface_ptr( GeneratorFactory::create( type ) );
|
||||
}
|
||||
|
||||
m_generator->setControls( controls );
|
||||
m_generator->setMode( ONDEMAND )
|
||||
|
||||
DynamicPlaylistRevision pr;
|
||||
pr.oldrevisionguid = m_currentrevision;
|
||||
pr.revisionguid = rev;
|
||||
pr.controls = controls;
|
||||
pr.type = type;
|
||||
pr.mode = ONDEMAND;
|
||||
|
||||
emit revisionLoaded( pr );
|
||||
}
|
||||
|
120
src/dynamic/dynamicplaylist.h
Normal file
120
src/dynamic/dynamicplaylist.h
Normal file
@ -0,0 +1,120 @@
|
||||
#ifndef DYNAMIC_PLAYLIST_H
|
||||
#define DYNAMIC_PLAYLIST_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QList>
|
||||
#include <QSharedPointer>
|
||||
|
||||
#include "tomahawk/playlist.h"
|
||||
#include "dynamic/generatorinterface.h"
|
||||
|
||||
namespace Tomahawk {
|
||||
|
||||
/**
|
||||
* Subclass of playlist that adds the information needed to store a dynamic playlist.
|
||||
* It uses normal PlaylistEntries but also has a mode, a generator, and a list of controls
|
||||
*/
|
||||
|
||||
class DynamicPlaylist : public Playlist
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( GeneratorMode mode WRITE setMode READ mode )
|
||||
Q_PROPERTY( QString type WRITE setType READ type )
|
||||
|
||||
public:
|
||||
enum DynamicPlaylistMode {
|
||||
OnDemand = 0,
|
||||
StaticPlaylist
|
||||
};
|
||||
|
||||
/// Generate an empty dynamic playlist with default generator
|
||||
static Tomahawk::dynplaylist_ptr create( const source_ptr& author,
|
||||
const QString& guid,
|
||||
const QString& title,
|
||||
const QString& info,
|
||||
const QString& creator,
|
||||
bool shared
|
||||
);
|
||||
static bool remove( const dynplaylist_ptr& playlist );
|
||||
|
||||
virtual void loadRevision( const QString& rev = "" );
|
||||
|
||||
GeneratorMode mode() const { return m_generator->mode(); }
|
||||
QString type() const { return m_generator->type(); }
|
||||
generatorinterface_ptr generator() const { return m_generator; }
|
||||
|
||||
// <IGNORE hack="true">
|
||||
// these need to exist and be public for the json serialization stuff
|
||||
// you SHOULD NOT call them. They are used for an alternate CTOR method from json.
|
||||
// maybe friend QObjectHelper and make them private?
|
||||
explicit DynamicPlaylist( const source_ptr& author )
|
||||
: Playlist( author )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "JSON";
|
||||
}
|
||||
void setMode( GeneratorMode mode ) { m_generator->setMode( mode ); }
|
||||
void setType( const QString& type ) { /** TODO */; }
|
||||
void setGenerator( const generatorinterface_ptr& gen_ptr ) { m_generator = gen_ptr; }
|
||||
// </IGNORE>
|
||||
|
||||
signals:
|
||||
/// emitted when the playlist revision changes (whenever the playlist changes)
|
||||
void revisionLoaded( Tomahawk::DynamicPlaylistRevision );
|
||||
|
||||
public slots:
|
||||
// want to update the playlist from the model?
|
||||
// generate a newrev using uuid() and call this:
|
||||
// if this is a static playlist, pass it a new list of entries. implicitly sets mode to static
|
||||
void createNewRevision( const QString& newrev, const QString& oldrev, const QString& type, const QList< dyncontrol_ptr>& controls, const QList< plentry_ptr >& entries );
|
||||
// if it is ondemand, no entries are needed implicitly sets mode to ondemand
|
||||
void createNewRevision( const QString& newrev, const QString& oldrev, const QString& type, const QList< dyncontrol_ptr>& controls );
|
||||
|
||||
void reportCreated( const Tomahawk::dynplaylist_ptr& self );
|
||||
void reportDeleted( const Tomahawk::dynplaylist_ptr& self );
|
||||
|
||||
// called from setdynamicplaylistrevision db cmd
|
||||
// static version
|
||||
void setRevision( const QString& rev,
|
||||
const QList<QString>& neworderedguids,
|
||||
const QList<QString>& oldorderedguids,
|
||||
const QString& type,
|
||||
const QList< dyncontrol_ptr>& controls,
|
||||
bool is_newest_rev,
|
||||
const QMap< QString, Tomahawk::plentry_ptr >& addedmap,
|
||||
bool applied );
|
||||
|
||||
// ondemand version
|
||||
void setRevision( const QString& rev,
|
||||
bool is_newest_rev,
|
||||
const QString& type,
|
||||
const QList< dyncontrol_ptr>& controls,
|
||||
bool applied );
|
||||
private:
|
||||
// called from loadAllPlaylists DB cmd:
|
||||
explicit DynamicPlaylist( const source_ptr& src,
|
||||
const QString& currentrevision,
|
||||
const QString& title,
|
||||
const QString& info,
|
||||
const QString& creator,
|
||||
const QString& type,
|
||||
bool shared,
|
||||
int lastmod,
|
||||
const QString& guid = "" ); // populate db
|
||||
|
||||
// called when creating new playlist
|
||||
explicit DynamicPlaylist( const source_ptr& author,
|
||||
const QString& guid,
|
||||
const QString& title,
|
||||
const QString& info,
|
||||
const QString& creator,
|
||||
const QString& type,
|
||||
bool shared );
|
||||
|
||||
private:
|
||||
generatorinterface_ptr m_generator;
|
||||
};
|
||||
|
||||
}; // namespace
|
||||
|
||||
#endif
|
23
src/dynamic/generatorfactory.cpp
Normal file
23
src/dynamic/generatorfactory.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "generatorfactory.h"
|
||||
|
||||
Tomahawk::GeneratorFactory::GeneratorFactory()
|
||||
{
|
||||
}
|
||||
|
||||
Tomahawk::GeneratorFactory::~GeneratorFactory()
|
||||
{
|
||||
qDeleteAll( m_factories.values() );
|
||||
}
|
||||
|
||||
generatorinterface_ptr Tomahawk::GeneratorFactory::create ( const QString& type )
|
||||
{
|
||||
if( !m_factories.contains( type ) )
|
||||
return generatorinterface_ptr();
|
||||
|
||||
return generatorinterface_ptr( m_factories.value( type )->create() );
|
||||
}
|
||||
|
||||
void Tomahawk::GeneratorFactory::registerFactory ( const QString& type, Tomahawk::GeneratorFactoryInterface* interface )
|
||||
{
|
||||
m_factories.insert( type, interface );
|
||||
}
|
39
src/dynamic/generatorfactory.h
Normal file
39
src/dynamic/generatorfactory.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef GENERATOR_FACTORY_H
|
||||
#define GENERATOR_FACTORY_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QString>
|
||||
|
||||
namespace Tomahawk {
|
||||
|
||||
/**
|
||||
* Generators should subclass this and have it create the custom Generator
|
||||
*/
|
||||
class GeneratorFactoryInterface
|
||||
{
|
||||
public:
|
||||
GeneratorInterface* create() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple factory that generates Generators from string type descriptors
|
||||
*/
|
||||
class GeneratorFactory
|
||||
{
|
||||
public:
|
||||
GeneratorFactory();
|
||||
~GeneratorFactory();
|
||||
|
||||
generatorinterface_ptr create( const QString& type );
|
||||
|
||||
void registerFactory( const QString& type, GeneratorFactoryInterface* interface );
|
||||
|
||||
private:
|
||||
QHash<QString, GeneratorFactoryInterface*> m_factories;
|
||||
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
52
src/dynamic/generatorinterface.h
Normal file
52
src/dynamic/generatorinterface.h
Normal file
@ -0,0 +1,52 @@
|
||||
#ifndef GENERATOR_INTERFACE_H
|
||||
#define GENERATOR_INTERFACE_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
namespace Tomahawk {
|
||||
|
||||
enum GeneratorMode {
|
||||
OnDemand = 0,
|
||||
Static
|
||||
};
|
||||
|
||||
/**
|
||||
* The abstract interface for Dynamic Playlist Generators. Generators have the following features:
|
||||
* - They create new DynamicControls that are appropriate for the generator
|
||||
* - They expose a list of controls that this generator currently is operating on
|
||||
* - They have a state of OnDemand or Static
|
||||
*/
|
||||
class GeneratorInterface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY( QString type READ type )
|
||||
Q_PROPERTY( GeneratorMode mode READ mode WRITE setMode );
|
||||
Q_ENUMS( GeneratorMode )
|
||||
|
||||
public:
|
||||
explicit GeneratorInterface() {}
|
||||
virtual ~GeneratorInterface() {}
|
||||
|
||||
// Can't make it pure otherwise we can't shove it in QVariants :-/
|
||||
virtual dyncontrol_ptr createControl() const {}
|
||||
|
||||
/// The type of this generator
|
||||
virtual QString type() const { return m_type; }
|
||||
|
||||
virtual GeneratorMode mode() const { return m_mode; }
|
||||
virtual void setMode( GeneratorMode mode ) { m_mode = mode; }
|
||||
|
||||
// control functions
|
||||
virtual QList< dyncontrol_ptr > controls() const { return m_controls; }
|
||||
virtual void addControl( const dyncontrol_ptr& control ) { m_controls << control; }
|
||||
virtual void clearControls() { m_controls.clear(); }
|
||||
virtual void setControls( const QList< dyncontrol_ptr>& controls ) { m_controls = controls; }
|
||||
private:
|
||||
QString m_type;
|
||||
GeneratorMode m_mode;
|
||||
QList< dyncontrol_ptr > m_controls;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
201
src/playlist.cpp
201
src/playlist.cpp
@ -168,21 +168,11 @@ void
|
||||
Playlist::createNewRevision( const QString& newrev, const QString& oldrev, const QList< plentry_ptr >& entries )
|
||||
{
|
||||
// qDebug() << "m_entries guids:";
|
||||
// foreach( plentry_ptr pp, m_entries ) qDebug() << pp->guid();
|
||||
|
||||
QSet<QString> currentguids;
|
||||
foreach( plentry_ptr p, m_entries )
|
||||
currentguids.insert( p->guid() ); // could be cached as member?
|
||||
|
||||
// calc list of newly added entries:
|
||||
QList<plentry_ptr> added;
|
||||
QList<plentry_ptr> added = newEntries( entries );
|
||||
QStringList orderedguids;
|
||||
foreach( plentry_ptr p, entries )
|
||||
{
|
||||
orderedguids << p->guid();
|
||||
if( !currentguids.contains(p->guid()) )
|
||||
added << p;
|
||||
}
|
||||
|
||||
// source making the change (localy user in this case)
|
||||
source_ptr author = APP->sourcelist().getLocal();
|
||||
@ -225,87 +215,9 @@ Playlist::setRevision( const QString& rev,
|
||||
);
|
||||
return;
|
||||
}
|
||||
//qDebug() << Q_FUNC_INFO << (qlonglong)this
|
||||
// << rev << neworderedguids << oldorderedguids
|
||||
// << "isnewest:" << is_newest_rev << addedmap << applied << m_entries
|
||||
// ;
|
||||
|
||||
// build up correctly ordered new list of plentry_ptrs from
|
||||
// existing ones, and the ones that have been added
|
||||
QMap<QString, plentry_ptr> entriesmap;
|
||||
foreach( const plentry_ptr& p, m_entries )
|
||||
entriesmap.insert( p->guid(), p );
|
||||
|
||||
//qDebug() << "Entries map:" << entriesmap;
|
||||
|
||||
QList<plentry_ptr> entries;
|
||||
//qDebug() << "m_entries:" << m_entries.count() << m_entries;
|
||||
|
||||
//qDebug() << "counters:" << neworderedguids.count() << entriesmap.count() << addedmap.count();
|
||||
foreach( const QString& id, neworderedguids )
|
||||
{
|
||||
//qDebug() << "id:" << id;
|
||||
//qDebug() << "newordered:" << neworderedguids.count() << neworderedguids;
|
||||
//qDebug() << "entriesmap:" << entriesmap.count() << entriesmap;
|
||||
//qDebug() << "addedmap:" << addedmap.count() << addedmap;
|
||||
//qDebug() << "m_entries" << m_entries;
|
||||
|
||||
if( entriesmap.contains( id ) )
|
||||
{
|
||||
entries.append( entriesmap.value( id ) );
|
||||
}
|
||||
else if( addedmap.contains( id ) )
|
||||
{
|
||||
entries.append( addedmap.value( id ) );
|
||||
if( is_newest_rev ) m_entries.append( addedmap.value( id ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_ASSERT( false ); // XXX
|
||||
}
|
||||
}
|
||||
|
||||
//qDebug() << Q_FUNC_INFO << rev << entries.length() << applied;
|
||||
|
||||
PlaylistRevision pr;
|
||||
pr.oldrevisionguid = m_currentrevision;
|
||||
pr.revisionguid = rev;
|
||||
|
||||
// entries that have been removed:
|
||||
QSet<QString> removedguids = oldorderedguids.toSet().subtract( neworderedguids.toSet() );
|
||||
//qDebug() << "Removedguids:" << removedguids << "oldorederedguids" << oldorderedguids << "newog" << neworderedguids;
|
||||
foreach( QString remid, removedguids )
|
||||
{
|
||||
// NB: entriesmap will contain old/removed entries only if the removal was done
|
||||
// in the same session - after a restart, history is not in memory.
|
||||
if( entriesmap.contains( remid ) )
|
||||
{
|
||||
pr.removed << entriesmap.value( remid );
|
||||
if( is_newest_rev )
|
||||
{
|
||||
//qDebug() << "Removing from m_entries" << remid;
|
||||
for( int k = 0 ; k<m_entries.length(); ++k )
|
||||
{
|
||||
if( m_entries.at(k)->guid() == remid )
|
||||
{
|
||||
//qDebug() << "removed at " << k;
|
||||
m_entries.removeAt(k);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pr.added = addedmap.values();
|
||||
|
||||
//qDebug() << "Revision set:" << rev
|
||||
// << "added" << pr.added.size()
|
||||
// << "removed" << pr.removed.size()
|
||||
// << "total entries" << m_entries.size();
|
||||
|
||||
pr.newlist = entries;
|
||||
|
||||
|
||||
PlaylistRevision pr = setNewRevision( rev, neworderedguids, oldorderedguids, is_newest_rev, addedmap );
|
||||
|
||||
if( applied )
|
||||
m_currentrevision = rev;
|
||||
pr.applied = applied;
|
||||
@ -313,6 +225,94 @@ Playlist::setRevision( const QString& rev,
|
||||
emit revisionLoaded( pr );
|
||||
}
|
||||
|
||||
PlaylistRevision
|
||||
Playlist::setNewRevision( const QString& rev,
|
||||
const QList<QString>& neworderedguids,
|
||||
const QList<QString>& oldorderedguids,
|
||||
bool is_newest_rev,
|
||||
const QMap< QString, Tomahawk::plentry_ptr >& addedmap )
|
||||
{
|
||||
//qDebug() << Q_FUNC_INFO << (qlonglong)this
|
||||
// << rev << neworderedguids << oldorderedguids
|
||||
// << "isnewest:" << is_newest_rev << addedmap << applied << m_entries
|
||||
// ;
|
||||
|
||||
// build up correctly ordered new list of plentry_ptrs from
|
||||
// existing ones, and the ones that have been added
|
||||
QMap<QString, plentry_ptr> entriesmap;
|
||||
foreach( const plentry_ptr& p, m_entries )
|
||||
entriesmap.insert( p->guid(), p );
|
||||
|
||||
//qDebug() << "Entries map:" << entriesmap;
|
||||
|
||||
QList<plentry_ptr> entries;
|
||||
//qDebug() << "m_entries:" << m_entries.count() << m_entries;
|
||||
|
||||
//qDebug() << "counters:" << neworderedguids.count() << entriesmap.count() << addedmap.count();
|
||||
foreach( const QString& id, neworderedguids )
|
||||
{
|
||||
//qDebug() << "id:" << id;
|
||||
//qDebug() << "newordered:" << neworderedguids.count() << neworderedguids;
|
||||
//qDebug() << "entriesmap:" << entriesmap.count() << entriesmap;
|
||||
//qDebug() << "addedmap:" << addedmap.count() << addedmap;
|
||||
//qDebug() << "m_entries" << m_entries;
|
||||
|
||||
if( entriesmap.contains( id ) )
|
||||
{
|
||||
entries.append( entriesmap.value( id ) );
|
||||
}
|
||||
else if( addedmap.contains( id ) )
|
||||
{
|
||||
entries.append( addedmap.value( id ) );
|
||||
if( is_newest_rev ) m_entries.append( addedmap.value( id ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_ASSERT( false ); // XXX
|
||||
}
|
||||
}
|
||||
|
||||
//qDebug() << Q_FUNC_INFO << rev << entries.length() << applied;
|
||||
|
||||
PlaylistRevision pr;
|
||||
pr.oldrevisionguid = m_currentrevision;
|
||||
pr.revisionguid = rev;
|
||||
|
||||
// entries that have been removed:
|
||||
QSet<QString> removedguids = oldorderedguids.toSet().subtract( neworderedguids.toSet() );
|
||||
//qDebug() << "Removedguids:" << removedguids << "oldorederedguids" << oldorderedguids << "newog" << neworderedguids;
|
||||
foreach( QString remid, removedguids )
|
||||
{
|
||||
// NB: entriesmap will contain old/removed entries only if the removal was done
|
||||
// in the same session - after a restart, history is not in memory.
|
||||
if( entriesmap.contains( remid ) )
|
||||
{
|
||||
pr.removed << entriesmap.value( remid );
|
||||
if( is_newest_rev )
|
||||
{
|
||||
//qDebug() << "Removing from m_entries" << remid;
|
||||
for( int k = 0 ; k<m_entries.length(); ++k )
|
||||
{
|
||||
if( m_entries.at(k)->guid() == remid )
|
||||
{
|
||||
//qDebug() << "removed at " << k;
|
||||
m_entries.removeAt(k);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pr.added = addedmap.values();
|
||||
|
||||
//qDebug() << "Revision set:" << rev
|
||||
// << "added" << pr.added.size()
|
||||
// << "removed" << pr.removed.size()
|
||||
// << "total entries" << m_entries.size();
|
||||
|
||||
pr.newlist = entries;
|
||||
}
|
||||
|
||||
void Playlist::resolve()
|
||||
{
|
||||
@ -361,3 +361,20 @@ Playlist::addEntries( const QList<query_ptr>& queries, const QString& oldrev )
|
||||
QString newrev = uuid();
|
||||
createNewRevision( newrev, oldrev, el );
|
||||
}
|
||||
|
||||
QList< plentry_ptr >
|
||||
Playlist::newEntries( const QList< plentry_ptr > entries )
|
||||
{
|
||||
QSet<QString> currentguids;
|
||||
foreach( plentry_ptr p, m_entries )
|
||||
currentguids.insert( p->guid() ); // could be cached as member?
|
||||
|
||||
// calc list of newly added entries:
|
||||
QList<plentry_ptr> added;
|
||||
foreach( plentry_ptr p, entries )
|
||||
{
|
||||
if( !currentguids.contains(p->guid()) )
|
||||
added << p;
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user