1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-07-31 19:30:21 +02:00

first compiling+linking dynamic code. lots of forward declaring fixes so it touches a lot of headers

This commit is contained in:
Leo Franchi
2010-12-06 20:44:39 -05:00
parent 228cab7080
commit 6a4a4a18e9
44 changed files with 977 additions and 132 deletions

View File

@@ -14,9 +14,10 @@
#include <QDebug> #include <QDebug>
#include "tomahawk/functimeout.h" #include "tomahawk/functimeout.h"
#include "tomahawk/playlist.h"
#include "tomahawk/source.h" #include "tomahawk/source.h"
#include "tomahawk/typedefs.h" #include "tomahawk/typedefs.h"
#include "typedefs.h"
#include "dynamic/dynamicplaylist.h"
namespace Tomahawk namespace Tomahawk
{ {
@@ -33,12 +34,19 @@ public:
virtual void loadPlaylists() { qDebug() << Q_FUNC_INFO; } virtual void loadPlaylists() { qDebug() << Q_FUNC_INFO; }
virtual void loadTracks() { qDebug() << Q_FUNC_INFO; } virtual void loadTracks() { qDebug() << Q_FUNC_INFO; }
virtual void loadDynamicPlaylists() { qDebug() << Q_FUNC_INFO ; }
virtual Tomahawk::playlist_ptr playlist( const QString& guid ); virtual Tomahawk::playlist_ptr playlist( const QString& guid );
virtual Tomahawk::dynplaylist_ptr dynamicPlaylist( const QString& guid );
virtual void addPlaylist( const Tomahawk::playlist_ptr& p ); virtual void addPlaylist( const Tomahawk::playlist_ptr& p );
virtual void deletePlaylist( const Tomahawk::playlist_ptr& p ); virtual void deletePlaylist( const Tomahawk::playlist_ptr& p );
virtual void addDynamicPlaylist( const Tomahawk::dynplaylist_ptr& p );
virtual void deleteDynamicPlaylist( const Tomahawk::dynplaylist_ptr& p );
virtual QList< Tomahawk::playlist_ptr > playlists() { return m_playlists; } virtual QList< Tomahawk::playlist_ptr > playlists() { return m_playlists; }
virtual QList< Tomahawk::dynplaylist_ptr > dynamicPlaylists() { return m_dynplaylists; }
virtual QList< Tomahawk::query_ptr > tracks() { return m_tracks; } virtual QList< Tomahawk::query_ptr > tracks() { return m_tracks; }
const source_ptr& source() const { return m_source; } const source_ptr& source() const { return m_source; }
@@ -51,6 +59,9 @@ signals:
void playlistsAdded( const QList<Tomahawk::playlist_ptr>& ); void playlistsAdded( const QList<Tomahawk::playlist_ptr>& );
void playlistsDeleted( const QList<Tomahawk::playlist_ptr>& ); void playlistsDeleted( const QList<Tomahawk::playlist_ptr>& );
void dynamicPlaylistsAdded( const QList<Tomahawk::dynplaylist_ptr>& );
void dynamicPlaylistsDeleted( const QList<Tomahawk::dynplaylist_ptr>& );
public slots: public slots:
virtual void addTracks( const QList<QVariant> &newitems ) = 0; virtual void addTracks( const QList<QVariant> &newitems ) = 0;
@@ -59,6 +70,7 @@ public slots:
void setPlaylists( const QList<Tomahawk::playlist_ptr>& plists ); void setPlaylists( const QList<Tomahawk::playlist_ptr>& plists );
void setTracks( const QList<Tomahawk::query_ptr>& tracks, Tomahawk::collection_ptr collection ); void setTracks( const QList<Tomahawk::query_ptr>& tracks, Tomahawk::collection_ptr collection );
void setDynamicPlaylistS( const QList< Tomahawk::dynplaylist_ptr >& dynplists );
protected: protected:
QString m_name; QString m_name;
unsigned int m_lastmodified; // unix time of last change to collection unsigned int m_lastmodified; // unix time of last change to collection
@@ -67,6 +79,7 @@ private:
source_ptr m_source; source_ptr m_source;
QList< Tomahawk::playlist_ptr > m_playlists; QList< Tomahawk::playlist_ptr > m_playlists;
QList< Tomahawk::query_ptr > m_tracks; QList< Tomahawk::query_ptr > m_tracks;
QList< Tomahawk::dynplaylist_ptr > m_dynplaylists;
}; };
}; // ns }; // ns

View File

@@ -3,6 +3,7 @@
#include <QObject> #include <QObject>
#include <QList> #include <QList>
#include <QDebug>
#include <QSharedPointer> #include <QSharedPointer>
#include "tomahawk/query.h" #include "tomahawk/query.h"
@@ -119,12 +120,7 @@ public:
// these need to exist and be public for the json serialization stuff // 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. // you SHOULD NOT call them. They are used for an alternate CTOR method from json.
// maybe friend QObjectHelper and make them private? // maybe friend QObjectHelper and make them private?
explicit Playlist( const source_ptr& author ) explicit Playlist( const source_ptr& author );
: m_source( author )
, m_lastmodified( 0 )
{
qDebug() << Q_FUNC_INFO << "JSON";
}
void setCurrentrevision( const QString& s ) { m_currentrevision = s; } void setCurrentrevision( const QString& s ) { m_currentrevision = s; }
void setTitle( const QString& s ) { m_title = s; } void setTitle( const QString& s ) { m_title = s; }
void setInfo( const QString& s ) { m_info = s; } void setInfo( const QString& s ) { m_info = s; }
@@ -182,6 +178,8 @@ protected:
bool is_newest_rev, bool is_newest_rev,
const QMap< QString, Tomahawk::plentry_ptr >& addedmap ); const QMap< QString, Tomahawk::plentry_ptr >& addedmap );
private: private:
Playlist();
source_ptr m_source; source_ptr m_source;
QString m_currentrevision; QString m_currentrevision;
QString m_guid, m_title, m_info, m_creator; QString m_guid, m_title, m_info, m_creator;

View File

@@ -6,7 +6,7 @@
#include <QList> #include <QList>
#include <QVariant> #include <QVariant>
#include "tomahawk/collection.h" // #include "tomahawk/collection.h"
#include "tomahawk/result.h" #include "tomahawk/result.h"
#include "tomahawk/typedefs.h" #include "tomahawk/typedefs.h"

View File

@@ -1,12 +1,11 @@
#ifndef RESULT_H #ifndef RESULT_H
#define RESULT_H #define RESULT_H
#include <qvariant.h>
#include <QObject> #include <QObject>
#include <QVariant>
#include "tomahawk/typedefs.h" #include "tomahawk/typedefs.h"
#include "collection.h"
#include "artist.h"
#include "album.h"
namespace Tomahawk namespace Tomahawk
{ {
@@ -17,14 +16,16 @@ Q_OBJECT
public: public:
explicit Result( const QVariant& v, const collection_ptr& collection ); explicit Result( const QVariant& v, const collection_ptr& collection );
virtual ~Result();
QVariant toVariant() const { return m_v; } QVariant toVariant() const { return m_v; }
float score() const; float score() const;
RID id() const; RID id() const;
collection_ptr collection() const { return m_collection; } collection_ptr collection() const;
Tomahawk::artist_ptr artist() const { return m_artist; } Tomahawk::artist_ptr artist() const;
Tomahawk::album_ptr album() const { return m_album; } Tomahawk::album_ptr album() const;
QString track() const { return m_track; } QString track() const { return m_track; }
QString url() const { return m_url; } QString url() const { return m_url; }
QString mimetype() const { return m_mimetype; } QString mimetype() const { return m_mimetype; }

View File

@@ -21,7 +21,7 @@ Q_OBJECT
public: public:
explicit Source( const QString& username, ControlConnection* cc ); explicit Source( const QString& username, ControlConnection* cc );
explicit Source( const QString& username ); explicit Source( const QString& username = QString() );
virtual ~Source(); virtual ~Source();
bool isLocal() const { return m_isLocal; } bool isLocal() const { return m_isLocal; }

View File

@@ -15,6 +15,8 @@ namespace Tomahawk
class Query; class Query;
class Result; class Result;
class Source; class Source;
class DynamicControl;
class GeneratorInterface;
typedef QSharedPointer<Collection> collection_ptr; typedef QSharedPointer<Collection> collection_ptr;
typedef QSharedPointer<Playlist> playlist_ptr; typedef QSharedPointer<Playlist> playlist_ptr;
@@ -25,10 +27,19 @@ namespace Tomahawk
typedef QSharedPointer<Source> source_ptr; typedef QSharedPointer<Source> source_ptr;
typedef QSharedPointer<Artist> artist_ptr; typedef QSharedPointer<Artist> artist_ptr;
typedef QSharedPointer<Album> album_ptr; typedef QSharedPointer<Album> album_ptr;
typedef QSharedPointer<DynamicControl> dyncontrol_ptr;
typedef QSharedPointer<GeneratorInterface> geninterface_ptr;
// let's keep these typesafe, they are different kinds of GUID: // let's keep these typesafe, they are different kinds of GUID:
typedef QString QID; //query id typedef QString QID; //query id
typedef QString RID; //result id typedef QString RID; //result id
enum GeneratorMode {
OnDemand = 0,
Static
};
}; // ns }; // ns

View File

@@ -89,10 +89,16 @@ SET( tomahawkSources ${tomahawkSources}
database/databasecommand_renameplaylist.cpp database/databasecommand_renameplaylist.cpp
database/databasecommand_loadops.cpp database/databasecommand_loadops.cpp
database/databasecommand_updatesearchindex.cpp database/databasecommand_updatesearchindex.cpp
database/databasecommand_loadallplaylists.cpp
database/databasecommand_setdynamicplaylistrevision.cpp
database/databasecommand_createdynamicplaylist.cpp
database/databasecommand_loaddynamicplaylist.cpp
database/databasecollection.cpp database/databasecollection.cpp
dynamic/dynamicplaylist.cpp dynamic/dynamicplaylist.cpp
dynamic/dynamiccontrol.cpp
dynamic/generatorfactory.cpp dynamic/generatorfactory.cpp
dynamic/generatorinterface.cpp
dynamic/echonest/echonestgenerator.cpp dynamic/echonest/echonestgenerator.cpp
dynamic/echonest/echonestcontrol.cpp dynamic/echonest/echonestcontrol.cpp
@@ -207,6 +213,9 @@ SET( tomahawkHeaders ${tomahawkHeaders}
database/databasecommand_loadallplaylists.h database/databasecommand_loadallplaylists.h
database/databasecommand_createplaylist.h database/databasecommand_createplaylist.h
database/databasecommand_deleteplaylist.h database/databasecommand_deleteplaylist.h
database/databasecommand_setdynamicplaylistrevision.h
database/databasecommand_createdynamicplaylist.h
database/databasecommand_loaddynamicplaylist.h
database/databasecommand_renameplaylist.h database/databasecommand_renameplaylist.h
database/databasecommand_loadops.h database/databasecommand_loadops.h
database/databasecommand_updatesearchindex.h database/databasecommand_updatesearchindex.h

View File

@@ -4,6 +4,7 @@
#include <QGenericArgument> #include <QGenericArgument>
#include "tomahawk/playlist.h" #include "tomahawk/playlist.h"
#include "dynamic/dynamicplaylist.h"
using namespace Tomahawk; using namespace Tomahawk;
@@ -45,6 +46,20 @@ Collection::addPlaylist( const Tomahawk::playlist_ptr& p )
emit playlistsAdded( toadd ); emit playlistsAdded( toadd );
} }
void
Collection::addDynamicPlaylist( const Tomahawk::dynplaylist_ptr& p )
{
qDebug() << Q_FUNC_INFO;
QList<dynplaylist_ptr> toadd;
toadd << p;
m_dynplaylists.append( toadd );
qDebug() << Q_FUNC_INFO << "Collection name" << name()
<< "from source id" << source()->id()
<< "numplaylists:" << m_playlists.length();
emit dynamicPlaylistsAdded( toadd );
}
void void
Collection::deletePlaylist( const Tomahawk::playlist_ptr& p ) Collection::deletePlaylist( const Tomahawk::playlist_ptr& p )
@@ -60,6 +75,20 @@ Collection::deletePlaylist( const Tomahawk::playlist_ptr& p )
emit playlistsDeleted( todelete ); emit playlistsDeleted( todelete );
} }
void
Collection::deleteDynamicPlaylist( const Tomahawk::dynplaylist_ptr& p )
{
qDebug() << Q_FUNC_INFO;
QList<dynplaylist_ptr> todelete;
todelete << p;
m_dynplaylists.removeAll( p );
qDebug() << Q_FUNC_INFO << "Collection name" << name()
<< "from source id" << source()->id()
<< "numplaylists:" << m_playlists.length();
emit dynamicPlaylistsDeleted( todelete );
}
playlist_ptr playlist_ptr
Collection::playlist( const QString& guid ) Collection::playlist( const QString& guid )
@@ -74,6 +103,19 @@ Collection::playlist( const QString& guid )
} }
dynplaylist_ptr
Collection::dynamicPlaylist( const QString& guid )
{
foreach( const dynplaylist_ptr& pp, m_dynplaylists )
{
if( pp->guid() == guid )
return pp;
}
return dynplaylist_ptr();
}
void void
Collection::setPlaylists( const QList<Tomahawk::playlist_ptr>& plists ) Collection::setPlaylists( const QList<Tomahawk::playlist_ptr>& plists )
{ {
@@ -83,6 +125,14 @@ Collection::setPlaylists( const QList<Tomahawk::playlist_ptr>& plists )
emit playlistsAdded( plists ); emit playlistsAdded( plists );
} }
void
Collection::setDynamicPlaylistS( const QList< Tomahawk::dynplaylist_ptr >& plists )
{
qDebug() << Q_FUNC_INFO << plists.count();
m_dynplaylists.append( plists );
emit dynamicPlaylistsAdded( plists );
}
void void
Collection::setTracks( const QList<Tomahawk::query_ptr>& tracks, Tomahawk::collection_ptr collection ) Collection::setTracks( const QList<Tomahawk::query_ptr>& tracks, Tomahawk::collection_ptr collection )

View File

@@ -27,6 +27,19 @@ DatabaseCollection::loadPlaylists()
TomahawkApp::instance()->database()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) ); TomahawkApp::instance()->database()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
} }
void
DatabaseCollection::loadDynamicPlaylists()
{
qDebug() << Q_FUNC_INFO;
// DatabaseCommand_LoadAllDynamicPlaylists* cmd = new DatabaseCommand_LoadAllDynamicPlaylists( source() );
//
// connect( cmd, SIGNAL( done( const QList<Tomahawk::dynplaylist_ptr>& ) ),
// SLOT( setDynamicPlaylists( const QList<Tomahawk::dynplaylist_ptr>& ) ) );
//
// TomahawkApp::instance()->database()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
}
void void
DatabaseCollection::loadTracks() DatabaseCollection::loadTracks()
@@ -77,6 +90,19 @@ DatabaseCollection::playlists()
return Collection::playlists(); return Collection::playlists();
} }
QList< dynplaylist_ptr > DatabaseCollection::dynamicPlaylists()
{
qDebug() << Q_FUNC_INFO;
if ( Collection::dynamicPlaylists().isEmpty() )
{
loadDynamicPlaylists();
}
return Collection::dynamicPlaylists();
}
QList< Tomahawk::query_ptr > QList< Tomahawk::query_ptr >
DatabaseCollection::tracks() DatabaseCollection::tracks()

View File

@@ -17,9 +17,11 @@ public:
virtual void loadTracks(); virtual void loadTracks();
virtual void loadPlaylists(); virtual void loadPlaylists();
virtual void loadDynamicPlaylists();
virtual QList< Tomahawk::playlist_ptr > playlists(); virtual QList< Tomahawk::playlist_ptr > playlists();
virtual QList< Tomahawk::query_ptr > tracks(); virtual QList< Tomahawk::query_ptr > tracks();
virtual QList< Tomahawk::dynplaylist_ptr > dynamicPlaylists();
public slots: public slots:
virtual void addTracks( const QList<QVariant> &newitems ); virtual void addTracks( const QList<QVariant> &newitems );

View File

@@ -0,0 +1,79 @@
#include "databasecommand_createdynamicplaylist.h"
#include <QSqlQuery>
#include "tomahawk/tomahawkapp.h"
#include "dynamic/dynamicplaylist.h"
#include "dynamic/dynamiccontrol.h"
#include "dynamic/generatorinterface.h"
using namespace Tomahawk;
DatabaseCommand_CreateDynamicPlaylist::DatabaseCommand_CreateDynamicPlaylist( QObject* parent )
: DatabaseCommand_CreatePlaylist( parent )
{
qDebug() << Q_FUNC_INFO << "creating dynamiccreatecommand 1";
}
DatabaseCommand_CreateDynamicPlaylist::DatabaseCommand_CreateDynamicPlaylist( const source_ptr& author,
const dynplaylist_ptr& playlist )
: DatabaseCommand_CreatePlaylist( author, playlist.staticCast<Playlist>() )
, m_playlist( playlist )
{
qDebug() << Q_FUNC_INFO << "creating dynamiccreatecommand 2";
}
void
DatabaseCommand_CreateDynamicPlaylist::exec( DatabaseImpl* lib )
{
qDebug() << Q_FUNC_INFO;
Q_ASSERT( !m_playlist.isNull() );
Q_ASSERT( !source().isNull() );
DatabaseCommand_CreatePlaylist::exec( lib );
TomahawkSqlQuery cre = lib->newquery();
cre.prepare( "INSERT INTO dynamic_playlist( guid, pltype, plmode) "
"VALUES( :guid, :pltype, :plmode )" );
cre.bindValue( ":guid", m_playlist->guid() );
cre.bindValue( ":pltype", m_playlist->type() );
cre.bindValue( ":plmode", m_playlist->mode() );
qDebug() << "CREATE DYNPLAYLIST:" << cre.boundValues();
cre.exec();
// save the controls
cre = lib->newquery();
cre.prepare( "INSERT INTO dynamic_playlist_controls( id, selectedType, match, input) "
"VALUES( :id, :selectedType, :match, :input )" );
foreach( const dyncontrol_ptr& control, m_playlist->generator()->controls() ) {
cre.bindValue( ":id", control->id() );
cre.bindValue( ":selectedType", control->selectedType() );
cre.bindValue( ":match", control->match() );
cre.bindValue( ":input", control->input() );
qDebug() << "CREATE DYNPLAYLIST CONTROL:" << cre.boundValues();
cre.exec();
}
}
void
DatabaseCommand_CreateDynamicPlaylist::postCommitHook()
{
qDebug() << Q_FUNC_INFO;
if( report() == false )
return;
qDebug() << Q_FUNC_INFO << "..reporting..";
m_playlist->reportCreated( m_playlist );
if( source()->isLocal() )
APP->servent().triggerDBSync();
}

View File

@@ -0,0 +1,43 @@
#ifndef DATABASECOMMAND_CREATEDYNAMICPLAYLIST_H
#define DATABASECOMMAND_CREATEDYNAMICPLAYLIST_H
#include "databaseimpl.h"
#include "databasecommand_createplaylist.h"
#include "dynamic/dynamicplaylist.h"
#include "tomahawk/typedefs.h"
class DatabaseCommand_CreateDynamicPlaylist : public DatabaseCommand_CreatePlaylist
{
Q_OBJECT
Q_PROPERTY( QVariant playlist READ playlistV WRITE setPlaylistV )
public:
explicit DatabaseCommand_CreateDynamicPlaylist( QObject* parent = 0 );
explicit DatabaseCommand_CreateDynamicPlaylist( const Tomahawk::source_ptr& author, const Tomahawk::dynplaylist_ptr& playlist );
QString commandname() const { return "createdynamicplaylist"; }
virtual void exec( DatabaseImpl* lib );
virtual void postCommitHook();
virtual bool doesMutates() const { return true; }
QVariant playlistV() const
{
return QJson::QObjectHelper::qobject2qvariant( (QObject*)m_playlist.data() );
}
void setPlaylistV( const QVariant& v )
{
qDebug() << "***********" << Q_FUNC_INFO << v;
using namespace Tomahawk;
DynamicPlaylist* p = new DynamicPlaylist( source() );
QJson::QObjectHelper::qvariant2qobject( v.toMap(), p );
m_playlist = dynplaylist_ptr( p );
}
private:
Tomahawk::dynplaylist_ptr m_playlist;
};
#endif // DATABASECOMMAND_CREATEDYNAMICPLAYLIST_H

View File

@@ -35,6 +35,9 @@ public:
QJson::QObjectHelper::qvariant2qobject( v.toMap(), p ); QJson::QObjectHelper::qvariant2qobject( v.toMap(), p );
m_playlist = playlist_ptr( p ); m_playlist = playlist_ptr( p );
} }
protected:
bool report() { return m_report; }
private: private:
Tomahawk::playlist_ptr m_playlist; Tomahawk::playlist_ptr m_playlist;

View File

@@ -0,0 +1,64 @@
#include "databasecommand_loaddynamicplaylist.h"
#include <QSqlQuery>
#include <QString>
#include "databaseimpl.h"
#include "tomahawksqlquery.h"
#include "dynamic/dynamiccontrol.h"
#include "dynamic/generatorinterface.h"
using namespace Tomahawk;
void
DatabaseCommand_LoadDynamicPlaylist::exec( DatabaseImpl* dbi )
{
qDebug() << "Loading dynamic playlist revision" << guid();
// load the entries first
generateEntries( dbi );
// now load the controls etc
TomahawkSqlQuery controlsQuery = dbi->newquery();
controlsQuery.prepare("SELECT controls, plmode, pltype"
"FROM dynamic_playlist_revision "
"WHERE guid = :guid");
controlsQuery.bindValue( ":guid", guid() );
controlsQuery.exec();
QList< dyncontrol_ptr > controls;
if( controlsQuery.next() )
{
QStringList controlIds = controlsQuery.value( 0 ).toStringList();
foreach( const QString& controlId, controlIds )
{
TomahawkSqlQuery controlQuery = dbi->newquery();
controlQuery.prepare( "SELECT selectedType, match, input"
"FROM dynamic_playlist_controls"
"WHERE id = :id" );
controlQuery.bindValue( ":id", controlId );
controlQuery.exec();
if( controlQuery.next() )
{
dyncontrol_ptr c = dyncontrol_ptr( new DynamicControl );
c->setId( controlId );
c->setSelectedType( controlQuery.value( 0 ).toString() );
c->setMatch( controlQuery.value( 1 ).toString() );
c->setInput( controlQuery.value( 2 ).toString() );
controls << c;
}
}
}
QString type = controlsQuery.value( 2 ).toString();
GeneratorMode mode = static_cast<GeneratorMode>( controlsQuery.value( 1 ).toInt() );
if( mode == OnDemand ) {
Q_ASSERT( m_entrymap.isEmpty() ); // ondemand should have no entry
emit done( guid(), m_islatest, type, controls, true );
} else {
emit done( guid(), m_guids, m_oldentries, type, controls, m_islatest, m_entrymap, true );
}
}

View File

@@ -0,0 +1,47 @@
#ifndef DATABASECOMMAND_LOADDYNAMICPLAYLIST_H
#define DATABASECOMMAND_LOADDYNAMICPLAYLIST_H
#include <QObject>
#include <QVariantMap>
#include "tomahawk/typedefs.h"
#include "databasecommand.h"
#include "databasecommand_loadplaylistentries.h"
#include "tomahawk/playlist.h"
#include "dynamic/dynamiccontrol.h"
class DatabaseCommand_LoadDynamicPlaylist : public DatabaseCommand_LoadPlaylistEntries
{
Q_OBJECT
public:
explicit DatabaseCommand_LoadDynamicPlaylist( QString revision_guid, QObject* parent = 0 )
: DatabaseCommand_LoadPlaylistEntries( revision_guid, parent )
{}
virtual void exec( DatabaseImpl* );
virtual bool doesMutates() const { return false; }
virtual QString commandname() const { return "loaddynamicplaylist"; }
signals:
// used if loading an ondemand playlist
void done( QString,
bool,
const QString,
QList< Tomahawk::dyncontrol_ptr>,
bool );
// used when loading a static playlist
void done( QString,
QList< QString >,
QList< QString >,
QString,
QList< Tomahawk::dyncontrol_ptr>,
bool,
const QMap< QString, Tomahawk::plentry_ptr >,
bool );
private:
};
#endif // DATABASECOMMAND_LOADDYNAMICPLAYLIST_H

View File

@@ -11,67 +11,69 @@ void
DatabaseCommand_LoadPlaylistEntries::exec( DatabaseImpl* dbi ) DatabaseCommand_LoadPlaylistEntries::exec( DatabaseImpl* dbi )
{ {
qDebug() << "Loading playlist entries for revision" << m_guid; qDebug() << "Loading playlist entries for revision" << m_guid;
generateEntries( dbi );
emit done( m_guid, m_guids, m_oldentries, m_islatest, m_entrymap, true );
}
void DatabaseCommand_LoadPlaylistEntries::generateEntries( DatabaseImpl* dbi )
{
TomahawkSqlQuery query_entries = dbi->newquery(); TomahawkSqlQuery query_entries = dbi->newquery();
query_entries.prepare("SELECT entries, playlist, author, timestamp, previous_revision " query_entries.prepare("SELECT entries, playlist, author, timestamp, previous_revision "
"FROM playlist_revision " "FROM playlist_revision "
"WHERE guid = :guid"); "WHERE guid = :guid");
query_entries.bindValue( ":guid", m_guid ); query_entries.bindValue( ":guid", m_guid );
query_entries.exec(); query_entries.exec();
QStringList guids;
QMap< QString, plentry_ptr > entrymap;
bool islatest = true;
QStringList oldentries;
QString prevrev; QString prevrev;
QJson::Parser parser; bool ok; QJson::Parser parser; bool ok;
if( query_entries.next() ) if( query_entries.next() )
{ {
// entries should be a list of strings: // entries should be a list of strings:
QVariant v = parser.parse( query_entries.value(0).toByteArray(), &ok ); QVariant v = parser.parse( query_entries.value(0).toByteArray(), &ok );
Q_ASSERT( ok && v.type() == QVariant::List ); //TODO Q_ASSERT( ok && v.type() == QVariant::List ); //TODO
guids = v.toStringList(); m_guids = v.toStringList();
// qDebug() << "Entries:" << guids; // qDebug() << "Entries:" << guids;
QString inclause = QString("('%1')").arg(guids.join("', '")); QString inclause = QString("('%1')").arg(m_guids.join("', '"));
TomahawkSqlQuery query = dbi->newquery(); TomahawkSqlQuery query = dbi->newquery();
QString sql = QString("SELECT guid, trackname, artistname, albumname, annotation, " QString sql = QString("SELECT guid, trackname, artistname, albumname, annotation, "
"duration, addedon, addedby, result_hint " "duration, addedon, addedby, result_hint "
"FROM playlist_item " "FROM playlist_item "
"WHERE guid IN %1").arg( inclause ); "WHERE guid IN %1").arg( inclause );
//qDebug() << sql; //qDebug() << sql;
query.exec( sql ); query.exec( sql );
while( query.next() ) while( query.next() )
{ {
plentry_ptr e( new PlaylistEntry ); plentry_ptr e( new PlaylistEntry );
e->setGuid( query.value( 0 ).toString() ); e->setGuid( query.value( 0 ).toString() );
e->setAnnotation( query.value( 4 ).toString() ); e->setAnnotation( query.value( 4 ).toString() );
e->setDuration( query.value( 5 ).toUInt() ); e->setDuration( query.value( 5 ).toUInt() );
e->setLastmodified( 0 ); // TODO e->lastmodified = query.value(6).toInt(); e->setLastmodified( 0 ); // TODO e->lastmodified = query.value(6).toInt();
e->setResulthint( query.value( 8 ).toString() ); e->setResulthint( query.value( 8 ).toString() );
QVariantMap m; QVariantMap m;
m.insert( "artist", query.value( 2 ).toString() ); m.insert( "artist", query.value( 2 ).toString() );
m.insert( "album", query.value( 3 ).toString() ); m.insert( "album", query.value( 3 ).toString() );
m.insert( "track", query.value( 1 ).toString() ); m.insert( "track", query.value( 1 ).toString() );
m.insert( "qid", uuid() ); m.insert( "qid", uuid() );
Tomahawk::query_ptr q( new Tomahawk::Query( m ) ); Tomahawk::query_ptr q( new Tomahawk::Query( m ) );
e->setQuery( q ); e->setQuery( q );
entrymap.insert( e->guid(), e ); m_entrymap.insert( e->guid(), e );
} }
prevrev = query_entries.value( 4 ).toString(); prevrev = query_entries.value( 4 ).toString();
} }
else else
{ {
qDebug() << "Playlist has no current revision data"; qDebug() << "Playlist has no current revision data";
} }
if( prevrev.length() ) if( prevrev.length() )
{ {
TomahawkSqlQuery query_entries_old = dbi->newquery(); TomahawkSqlQuery query_entries_old = dbi->newquery();
@@ -82,21 +84,19 @@ DatabaseCommand_LoadPlaylistEntries::exec( DatabaseImpl* dbi )
query_entries_old.addBindValue( m_guid ); query_entries_old.addBindValue( m_guid );
query_entries_old.addBindValue( query_entries.value( 1 ).toString() ); query_entries_old.addBindValue( query_entries.value( 1 ).toString() );
query_entries_old.addBindValue( prevrev ); query_entries_old.addBindValue( prevrev );
query_entries_old.exec(); query_entries_old.exec();
if( !query_entries_old.next() ) if( !query_entries_old.next() )
{ {
return; return;
Q_ASSERT( false ); Q_ASSERT( false );
} }
QVariant v = parser.parse( query_entries_old.value( 0 ).toByteArray(), &ok ); QVariant v = parser.parse( query_entries_old.value( 0 ).toByteArray(), &ok );
Q_ASSERT( ok && v.type() == QVariant::List ); //TODO Q_ASSERT( ok && v.type() == QVariant::List ); //TODO
oldentries = v.toStringList(); m_oldentries = v.toStringList();
islatest = query_entries_old.value( 1 ).toBool(); m_islatest = query_entries_old.value( 1 ).toBool();
} }
qDebug() << Q_FUNC_INFO << "entrymap:" << entrymap; qDebug() << Q_FUNC_INFO << "entrymap:" << m_entrymap;
emit done( m_guid, guids, oldentries, islatest, entrymap, true );
} }

View File

@@ -28,6 +28,14 @@ signals:
const QMap< QString, Tomahawk::plentry_ptr >& added, const QMap< QString, Tomahawk::plentry_ptr >& added,
bool applied ); bool applied );
protected:
void generateEntries( DatabaseImpl* dbi );
QStringList m_guids;
QMap< QString, Tomahawk::plentry_ptr > m_entrymap;
bool m_islatest;
QStringList m_oldentries;
private: private:
QString m_guid; QString m_guid;
}; };

View File

@@ -0,0 +1,212 @@
#include "databasecommand_setdynamicplaylistrevision.h"
#include <QSqlQuery>
#include "tomahawksqlquery.h"
#include "dynamic/dynamicplaylist.h"
#include "dynamic/dynamiccontrol.h"
#include "tomahawk/tomahawkapp.h"
DatabaseCommand_SetDynamicPlaylistRevision::DatabaseCommand_SetDynamicPlaylistRevision(const Tomahawk::source_ptr& s,
const QString& playlistguid,
const QString& newrev,
const QString& oldrev,
const QStringList& orderedguids,
const QList< plentry_ptr >& addedentries,
const QString& type,
GeneratorMode mode,
const QList< dyncontrol_ptr >& controls )
: DatabaseCommand_SetPlaylistRevision( s, playlistguid, newrev, oldrev, orderedguids, addedentries )
, m_type( type )
, m_mode( mode )
, m_controls( controls )
{
}
DatabaseCommand_SetDynamicPlaylistRevision::DatabaseCommand_SetDynamicPlaylistRevision(const Tomahawk::source_ptr& s,
const QString& playlistguid,
const QString& newrev,
const QString& oldrev,
const QString& type,
GeneratorMode mode,
const QList< dyncontrol_ptr >& controls )
: DatabaseCommand_SetPlaylistRevision( s, playlistguid, newrev, oldrev, QStringList(), QList< plentry_ptr >() )
, m_type( type )
, m_mode( mode )
, m_controls( controls )
{
}
QVariantList DatabaseCommand_SetDynamicPlaylistRevision::controlsV()
{
if( m_controls.isEmpty() )
return m_controlsV;
if( !m_controls.isEmpty() && m_controlsV.isEmpty() )
{
foreach( const dyncontrol_ptr& control, m_controls )
{
m_controlsV << QJson::QObjectHelper::qobject2qvariant( control.data() );
}
}
return m_controlsV;
}
void
DatabaseCommand_SetDynamicPlaylistRevision::postCommitHook()
{
qDebug() << Q_FUNC_INFO;
QStringList orderedentriesguids;
foreach( const QVariant& v, orderedguids() )
orderedentriesguids << v.toString();
// private, but we are a friend. will recall itself in its own thread:
dynplaylist_ptr playlist = source()->collection()->dynamicPlaylist( playlistguid() );
if ( playlist.isNull() )
{
qDebug() << playlistguid();
Q_ASSERT( !playlist.isNull() );
return;
}
if( m_controls.isEmpty() && !m_controlsV.isEmpty() ) // we were creatd from JSON, not programmatically. construct the controls fromthe playlist now
{
foreach( const QVariant& contrl, m_controlsV ) {
dyncontrol_ptr control = playlist->generator()->createControl( m_type );
QJson::QObjectHelper::qvariant2qobject( contrl.toMap(), control.data( ));
m_controls << control;
}
}
if( m_mode == OnDemand )
playlist->setRevision( newrev(),
true, // this *is* the newest revision so far
m_type,
m_controls,
m_applied );
else
playlist->setRevision( newrev(),
orderedentriesguids,
m_previous_rev_orderedguids,
m_type,
m_controls,
true, // this *is* the newest revision so far
m_addedmap,
m_applied );
if( source()->isLocal() )
APP->servent().triggerDBSync();
}
void
DatabaseCommand_SetDynamicPlaylistRevision::exec( DatabaseImpl* lib )
{
/*using namespace Tomahawk;
QString currentrevision;
// get the current revision for this playlist
// this also serves to check the playlist exists.
TomahawkSqlQuery chkq = lib->newquery();
chkq.prepare("SELECT currentrevision FROM playlist WHERE guid = ?");
chkq.addBindValue( m_playlistguid );
if( chkq.exec() && chkq.next() )
{
currentrevision = chkq.value( 0 ).toString();
//qDebug() << Q_FUNC_INFO << "pl guid" << m_playlistguid << " curr rev" << currentrevision;
}
else
{
throw "No such playlist, WTF?";
return;
}
QVariantList vlist = m_orderedguids;
QJson::Serializer ser;
const QByteArray entries = ser.serialize( vlist );
// add any new items:
TomahawkSqlQuery adde = lib->newquery();
QString sql = "INSERT INTO playlist_item( guid, playlist, trackname, artistname, albumname, "
"annotation, duration, addedon, addedby, result_hint ) "
"VALUES( ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )";
adde.prepare( sql );
qDebug() << "Num new playlist_items to add:" << m_addedentries.length();
foreach( const plentry_ptr& e, m_addedentries )
{
m_addedmap.insert( e->guid(), e ); // needed in postcommithook
adde.bindValue( 0, e->guid() );
adde.bindValue( 1, m_playlistguid );
adde.bindValue( 2, e->query()->track() );
adde.bindValue( 3, e->query()->artist() );
adde.bindValue( 4, e->query()->album() );
adde.bindValue( 5, e->annotation() );
adde.bindValue( 6, (int) e->duration() );
adde.bindValue( 7, e->lastmodified() );
adde.bindValue( 8, source()->isLocal() ? QVariant(QVariant::Int) : source()->id() );
adde.bindValue( 9, "" );
adde.exec();
}
// add the new revision:
//qDebug() << "Adding new playlist revision, guid:" << m_newrev
// << entries;
TomahawkSqlQuery query = lib->newquery();
sql = "INSERT INTO playlist_revision(guid, playlist, entries, author, timestamp, previous_revision) "
"VALUES(?, ?, ?, ?, ?, ?)";
query.prepare( sql );
query.addBindValue( m_newrev );
query.addBindValue( m_playlistguid );
query.addBindValue( entries );
query.addBindValue( source()->isLocal() ? QVariant(QVariant::Int) : source()->id() );
query.addBindValue( 0 ); //ts
query.addBindValue( m_oldrev.isEmpty() ? QVariant(QVariant::String) : m_oldrev );
query.exec();
qDebug() << "Currentrevision:" << currentrevision << "oldrev:" << m_oldrev;
// if optimistic locking is ok, update current revision to this new one
if( currentrevision == m_oldrev )
{
TomahawkSqlQuery query2 = lib->newquery();
qDebug() << "updating current revision, optimistic locking ok";
query2.prepare("UPDATE playlist SET currentrevision = ? WHERE guid = ?");
query2.bindValue( 0, m_newrev );
query2.bindValue( 1, m_playlistguid );
query2.exec();
m_applied = true;
// load previous revision entries, which we need to pass on
// so the change can be diffed
TomahawkSqlQuery query_entries = lib->newquery();
query_entries.prepare( "SELECT entries, playlist, author, timestamp, previous_revision "
"FROM playlist_revision "
"WHERE guid = :guid" );
query_entries.bindValue( ":guid", m_oldrev );
query_entries.exec();
if( query_entries.next() )
{
// entries should be a list of strings:
bool ok;
QJson::Parser parser;
QVariant v = parser.parse( query_entries.value(0).toByteArray(), &ok );
Q_ASSERT( ok && v.type() == QVariant::List ); //TODO
m_previous_rev_orderedguids = v.toStringList();
}
}
else
{
qDebug() << "Not updating current revision, optimistic locking fail";
} */
}

View File

@@ -0,0 +1,68 @@
#ifndef DATABASECOMMAND_SETDYNAMICPLAYLISTREVISION_H
#define DATABASECOMMAND_SETDYNAMICPLAYLISTREVISION_H
#include "databasecommand_setplaylistrevision.h"
#include "databaseimpl.h"
#include "tomahawk/collection.h"
#include "tomahawk/playlist.h"
#include <generatorinterface.h>
using namespace Tomahawk;
class DatabaseCommand_SetDynamicPlaylistRevision : public DatabaseCommand_SetPlaylistRevision
{
Q_OBJECT
Q_PROPERTY( QString type READ type WRITE setType )
Q_PROPERTY( GeneratorMode mode READ mode WRITE setMode )
Q_PROPERTY( QVariantList controls READ controlsV WRITE setControlsV )
public:
explicit DatabaseCommand_SetDynamicPlaylistRevision( QObject* parent = 0 )
: DatabaseCommand_SetPlaylistRevision( parent )
{}
explicit DatabaseCommand_SetDynamicPlaylistRevision( const source_ptr& s,
const QString& playlistguid,
const QString& newrev,
const QString& oldrev,
const QStringList& orderedguids,
const QList<Tomahawk::plentry_ptr>& addedentries,
const QString& type,
GeneratorMode mode,
const QList< dyncontrol_ptr >& controls );
explicit DatabaseCommand_SetDynamicPlaylistRevision( const source_ptr& s,
const QString& playlistguid,
const QString& newrev,
const QString& oldrev,
const QString& type,
GeneratorMode mode,
const QList< dyncontrol_ptr >& controls );
QString commandname() const { return "setdynamicplaylistrevision"; }
virtual void exec( DatabaseImpl* lib );
virtual void postCommitHook();
virtual bool doesMutates() const { return true; }
void setControlsV( const QVariantList& vlist )
{
m_controlsV = vlist;
}
QVariantList controlsV();
QString type() const { return m_type; }
GeneratorMode mode() const { return m_mode; }
void setType( const QString& type ) { m_type = type; }
void setMode( GeneratorMode mode ) { m_mode = mode; }
private:
QString m_type;
GeneratorMode m_mode;
QList< dyncontrol_ptr > m_controls;
QList< QVariant > m_controlsV;
};
#endif // DATABASECOMMAND_SETDYNAMICPLAYLISTREVISION_H

View File

@@ -13,11 +13,11 @@ DatabaseCommand_SetPlaylistRevision::DatabaseCommand_SetPlaylistRevision(
const QString& oldrev, const QString& oldrev,
const QStringList& orderedguids, const QStringList& orderedguids,
const QList<plentry_ptr>& addedentries ) const QList<plentry_ptr>& addedentries )
: DatabaseCommandLoggable( s ) : DatabaseCommandLoggable( s )
, m_applied( false )
, m_newrev( newrev ) , m_newrev( newrev )
, m_oldrev( oldrev ) , m_oldrev( oldrev )
, m_addedentries( addedentries ) , m_addedentries( addedentries )
, m_applied( false )
{ {
setPlaylistguid( playlistguid ); setPlaylistguid( playlistguid );

View File

@@ -69,14 +69,16 @@ public:
void setOrderedguids( const QVariantList& l ) { m_orderedguids = l; } void setOrderedguids( const QVariantList& l ) { m_orderedguids = l; }
QVariantList orderedguids() const { return m_orderedguids; } QVariantList orderedguids() const { return m_orderedguids; }
protected:
bool m_applied;
QStringList m_previous_rev_orderedguids;
QMap<QString, Tomahawk::plentry_ptr> m_addedmap;
private: private:
QString m_playlistguid; QString m_playlistguid;
QString m_newrev, m_oldrev; QString m_newrev, m_oldrev;
QVariantList m_orderedguids; QVariantList m_orderedguids;
QStringList m_previous_rev_orderedguids;
QList<Tomahawk::plentry_ptr> m_addedentries; QList<Tomahawk::plentry_ptr> m_addedentries;
bool m_applied;
QMap<QString, Tomahawk::plentry_ptr> m_addedmap;
}; };
#endif // DATABASECOMMAND_SETPLAYLISTREVISION_H #endif // DATABASECOMMAND_SETPLAYLISTREVISION_H

View File

@@ -97,6 +97,28 @@ CREATE TABLE IF NOT EXISTS playlist_revision (
previous_revision TEXT REFERENCES playlist_revision(guid) DEFERRABLE INITIALLY DEFERRED previous_revision TEXT REFERENCES playlist_revision(guid) DEFERRABLE INITIALLY DEFERRED
); );
CREATE TABLE IF NOT EXISTS dynamic_playlist {
guid TEXT PRIMARY KEY,
pltype TEXT, -- the generator type
plmode INTEGER -- the mode of this playlist
};
-- list of controls in each playlist. each control saves a selectedType, a match, and an input
CREATE TABLE IF NOT EXISTS dynamic_playlist_controls {
id TEXT PRIMARY KEY,
playlist TEXT NOT NULL REFERENCES playlist(guid) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,
selectedType TEXT,
match TEXT,
input TEXT
};
CREATE TABLE IF NOT EXISTS dynamic_playlist_revision {
guid TEXT PRIMARY KEY,
controls TEXT, -- qlist( id, id, id )
plmode INTEGER REFERENCES dynamic_playlist( plmode ) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,
pltype TEXT REFERENCES dynamic_playlist( pltype ) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED
};
--INSERT INTO playlist_revision(guid, playlist, entries) --INSERT INTO playlist_revision(guid, playlist, entries)
-- VALUES('revisionguid-1', 'playlistguid-1', '["itemguid-2","itemguid-1","itemguid-3"]'); -- VALUES('revisionguid-1', 'playlistguid-1', '["itemguid-2","itemguid-1","itemguid-3"]');

View File

@@ -3,6 +3,7 @@
// subclass QSqlQuery so that it prints the error msg if a query fails // subclass QSqlQuery so that it prints the error msg if a query fails
#include <QSqlQuery> #include <QSqlQuery>
#include <QSqlError>
#include <QTime> #include <QTime>
#define TOMAHAWK_QUERY_THRESHOLD 20 #define TOMAHAWK_QUERY_THRESHOLD 20

View File

@@ -0,0 +1,34 @@
/****************************************************************************************
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify it under *
* the terms of the GNU General Public License as published by the Free Software *
* Foundation; either version 2 of the License, or (at your option) any later *
* version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT ANY *
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
* PARTICULAR PURPOSE. See the GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License along with *
* this program. If not, see <http://www.gnu.org/licenses/>. *
****************************************************************************************/
#include "dynamiccontrol.h"
Tomahawk::DynamicControl::DynamicControl()
{
}
Tomahawk::DynamicControl::~DynamicControl()
{
}
Tomahawk::DynamicControl::DynamicControl(const QString& selectedType, QObject* parent)
: QObject(parent)
, m_selectedType( selectedType )
{
}

View File

@@ -21,6 +21,7 @@
#include <QtCore/QSharedPointer> #include <QtCore/QSharedPointer>
#include <QStringList> #include <QStringList>
#include <QtGui/QWidget> #include <QtGui/QWidget>
#include <tomahawk/typedefs.h>
namespace Tomahawk namespace Tomahawk
{ {
@@ -38,40 +39,63 @@ namespace Tomahawk
class DynamicControl : public QObject class DynamicControl : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY( QString id READ id WRITE setId )
Q_PROPERTY( QString selectedType READ selectedType WRITE setSelectedType ) Q_PROPERTY( QString selectedType READ selectedType WRITE setSelectedType )
Q_PROPERTY( QStringList typeSelectors READ typeSelectors ) Q_PROPERTY( QString match READ match WRITE setMatch )
Q_PROPERTY( QString input READ input WRITE setInput )
public: public:
// eff this :P
DynamicControl();
virtual ~DynamicControl(); virtual ~DynamicControl();
/// The current type of this control /// The current type of this control
QString selectedType() const { return m_selectedType; } QString selectedType() const { return m_selectedType; }
/// The match selector widget based on this control's type /// The match selector widget based on this control's type
virtual QWidget* matchSelector() { return 0; } virtual QWidget* matchSelector() { Q_ASSERT( false ); return 0; }
/// The input field widget that is associated with this type /// The input field widget that is associated with this type
virtual QWidget* inputField() { return 0; } virtual QWidget* inputField() { Q_ASSERT( false ); return 0; }
/// the serializable value of the match
QString match() const { Q_ASSERT( false ); return QString(); }
/// the serializable value of the input
QString input() const { Q_ASSERT( false ); return QString(); }
// used by JSON serialization
void setMatch( const QString& match ) { m_match = match; }
void setInput( const QString& input ) { m_input = input; }
/// All the potential type selectors for this control /// All the potential type selectors for this control
QStringList typeSelectors() const { return m_typeSelectors; } QStringList typeSelectors() const { return m_typeSelectors; }
QString id() {
if( m_id.isEmpty() )
m_id = uuid();
return m_id;
};
void setId( const QString& id ) { m_id = id; }
public slots: public slots:
/** /**
* Sets the type to the newly specified one. Note that this will update the matchSelector * Sets the type to the newly specified one. Note that this will update the matchSelector
* and inputField widgets, so you should fetch the new widgets for use immediately. * and inputField widgets, so you should fetch the new widgets for use immediately.
*/ */
virtual void setSelectedType( const QString& type ) { m_selectedType = type; } virtual void setSelectedType( const QString& selectedType ) { m_selectedType = selectedType; }
protected: protected:
// Private constructor, you can't make one. Get it from your Generator. // Private constructor, you can't make one. Get it from your Generator.
explicit DynamicControl( const QString& type, const QStringList& typeSelectors, QObject* parent = 0 ) : QObject( parent ), m_selectedType( type ), m_typeSelectors( typeSelectors ) {} explicit DynamicControl( const QString& selectedType, QObject* parent = 0 );
QString m_match;
QString m_input;
private: private:
QString m_selectedType; QString m_selectedType;
QStringList m_typeSelectors; QStringList m_typeSelectors;
QString m_id;
}; };
typedef QSharedPointer<DynamicControl> dyncontrol_ptr;
}; };
#endif #endif

View File

@@ -20,9 +20,24 @@
#include "generatorfactory.h" #include "generatorfactory.h"
#include "database.h" #include "database.h"
#include "databasecommand.h" #include "databasecommand.h"
#include "databasecommand_createdynamicplaylist.h"
#include "databasecommand_setdynamicplaylistrevision.h"
#include "databasecommand_loaddynamicplaylist.h"
using namespace Tomahawk; using namespace Tomahawk;
DynamicPlaylist::DynamicPlaylist(const Tomahawk::source_ptr& author)
: Playlist(author)
{
qDebug() << Q_FUNC_INFO << "JSON";
}
DynamicPlaylist::~DynamicPlaylist()
{
}
// Called by loadAllPlaylists command // Called by loadAllPlaylists command
DynamicPlaylist::DynamicPlaylist ( const Tomahawk::source_ptr& src, DynamicPlaylist::DynamicPlaylist ( const Tomahawk::source_ptr& src,
const QString& currentrevision, const QString& currentrevision,
@@ -54,6 +69,33 @@ DynamicPlaylist::DynamicPlaylist ( const Tomahawk::source_ptr& author,
// TODO instantiate generator // TODO instantiate generator
} }
geninterface_ptr DynamicPlaylist::generator() const
{
return m_generator;
}
GeneratorMode DynamicPlaylist::mode() const
{
return m_generator->mode();
}
void DynamicPlaylist::setGenerator(const Tomahawk::geninterface_ptr& gen_ptr)
{
m_generator = gen_ptr;
}
QString DynamicPlaylist::type() const
{
return m_generator->type();
}
void DynamicPlaylist::setMode(GeneratorMode mode)
{
m_generator->setMode( mode );
}
dynplaylist_ptr DynamicPlaylist::create( const Tomahawk::source_ptr& author, dynplaylist_ptr DynamicPlaylist::create( const Tomahawk::source_ptr& author,
const QString& guid, const QString& guid,
const QString& title, const QString& title,
@@ -129,8 +171,7 @@ void DynamicPlaylist::loadRevision( const QString& rev )
{ {
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
DatabaseCommand_LoadDynamicPlaylist* cmd = DatabaseCommand_LoadDynamicPlaylist* cmd = new DatabaseCommand_LoadDynamicPlaylist( rev.isEmpty() ? currentrevision() : rev );
new DatabaseCommand_LoadDynamicPlaylist( rev.isEmpty() ? currentrevision() : rev, m_generator->mode() );
if( m_generator->mode() == OnDemand ) { if( m_generator->mode() == OnDemand ) {
connect( cmd, SIGNAL( done( QString, connect( cmd, SIGNAL( done( QString,
@@ -238,6 +279,18 @@ void DynamicPlaylist::setRevision( const QString& rev,
const QList< dyncontrol_ptr>& controls, const QList< dyncontrol_ptr>& controls,
bool applied ) bool applied )
{ {
if( QThread::currentThread() != thread() )
{
QMetaObject::invokeMethod( this,
"setRevision",
Qt::BlockingQueuedConnection,
Q_ARG( QString, rev ),
Q_ARG( bool, is_newest_rev ),
Q_ARG( QString, type ),
QGenericArgument( "QList< dyncontrol_ptr >" , (const void*)&controls ),
Q_ARG( bool, applied ) );
return;
}
if( m_generator->type() != type ) { // new generator needed if( m_generator->type() != type ) { // new generator needed
m_generator = geninterface_ptr( GeneratorFactory::create( type ) ); m_generator = geninterface_ptr( GeneratorFactory::create( type ) );
} }

View File

@@ -22,7 +22,8 @@
#include <QSharedPointer> #include <QSharedPointer>
#include "tomahawk/playlist.h" #include "tomahawk/playlist.h"
#include "dynamic/generatorinterface.h" #include "tomahawk/typedefs.h"
#include "dynamic/dynamiccontrol.h"
namespace Tomahawk { namespace Tomahawk {
@@ -42,6 +43,8 @@ struct DynamicPlaylistRevision : PlaylistRevision
revisionguid = other.revisionguid; revisionguid = other.revisionguid;
oldrevisionguid = other.oldrevisionguid; oldrevisionguid = other.oldrevisionguid;
newlist = other.newlist; newlist = other.newlist;
added = other.added;
removed = other.removed;
applied = other.applied; applied = other.applied;
} }
@@ -56,6 +59,8 @@ class DynamicPlaylist : public Playlist
Q_PROPERTY( QString type WRITE setType READ type ) Q_PROPERTY( QString type WRITE setType READ type )
public: public:
virtual ~DynamicPlaylist();
/// Generate an empty dynamic playlist with default generator /// Generate an empty dynamic playlist with default generator
static Tomahawk::dynplaylist_ptr create( const source_ptr& author, static Tomahawk::dynplaylist_ptr create( const source_ptr& author,
const QString& guid, const QString& guid,
@@ -68,22 +73,18 @@ public:
virtual void loadRevision( const QString& rev = "" ); virtual void loadRevision( const QString& rev = "" );
GeneratorMode mode() const { return m_generator->mode(); } GeneratorMode mode() const;
QString type() const { return m_generator->type(); } QString type() const;
geninterface_ptr generator() const { return m_generator; } geninterface_ptr generator() const;
// <IGNORE hack="true"> // <IGNORE hack="true">
// these need to exist and be public for the json serialization stuff // 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. // you SHOULD NOT call them. They are used for an alternate CTOR method from json.
// maybe friend QObjectHelper and make them private? // maybe friend QObjectHelper and make them private?
explicit DynamicPlaylist( const source_ptr& author ) explicit DynamicPlaylist( const source_ptr& author );
: Playlist( author ) void setMode( GeneratorMode mode );
{
qDebug() << Q_FUNC_INFO << "JSON";
}
void setMode( GeneratorMode mode ) { m_generator->setMode( mode ); }
void setType( const QString& type ) { /** TODO */; } void setType( const QString& type ) { /** TODO */; }
void setGenerator( const geninterface_ptr& gen_ptr ) { m_generator = gen_ptr; } void setGenerator( const geninterface_ptr& gen_ptr );
// </IGNORE> // </IGNORE>
signals: signals:
@@ -140,6 +141,7 @@ private:
bool shared ); bool shared );
private: private:
Q_DISABLE_COPY(DynamicPlaylist)
geninterface_ptr m_generator; geninterface_ptr m_generator;
}; };

View File

@@ -22,8 +22,8 @@
#include <QLineEdit> #include <QLineEdit>
Tomahawk::EchonestControl::EchonestControl( const QString& type, const QStringList& typeSelectors, QObject* parent ) Tomahawk::EchonestControl::EchonestControl( const QString& type, QObject* parent )
: DynamicControl ( type, typeSelectors, parent ) : DynamicControl ( type, parent )
{ {
updateWidgets(); updateWidgets();
} }
@@ -76,11 +76,11 @@ Tomahawk::EchonestControl::updateWidgets()
void Tomahawk::EchonestControl::updateData() void Tomahawk::EchonestControl::updateData()
{ {
if( selectedType() == "Artist" ) { if( selectedType() == "Artist" ) {
QWeakPointer<QComboBox> combo = qWeakPointerCast( m_match ); QWeakPointer<QComboBox> combo = qWeakPointerCast<QComboBox, QWidget>( m_match );
if( !combo.isNull() ) if( !combo.isNull() )
m_data.first = static_cast<Echonest::DynamicPlaylist::PlaylistParam>( combo.data()->itemData( combo->currentIndex() ) ); m_data.first = static_cast<Echonest::DynamicPlaylist::PlaylistParam>( combo.data()->itemData( combo.data()->currentIndex() ).toInt() );
QWeakPointer<QLineEdit> edit = qWeakPointerCast( m_input ); QWeakPointer<QLineEdit> edit = qWeakPointerCast<QLineEdit, QWidget>( m_input );
if( !edit.isNull() ) if( !edit.isNull() )
m_data.second = qWeakPointerCast->text(); m_data.second = edit.data()->text();
} }
} }

View File

@@ -36,13 +36,13 @@ public:
public slots: public slots:
virtual void setSelectedType ( const QString& type ); virtual void setSelectedType ( const QString& type );
protected:
explicit EchonestControl( const QString& type, const QStringList& typeSelectors, QObject* parent = 0 );
private slots: private slots:
void updateData(); void updateData();
protected:
explicit EchonestControl( const QString& type, QObject* parent = 0 );
private: private:
void updateWidgets(); void updateWidgets();
@@ -50,6 +50,8 @@ private:
QWeakPointer< QWidget > m_match; QWeakPointer< QWidget > m_match;
Echonest::DynamicPlaylist::PlaylistParamData m_data; Echonest::DynamicPlaylist::PlaylistParamData m_data;
friend class EchonestGenerator;
}; };
typedef QSharedPointer<EchonestControl> encontrol_ptr; typedef QSharedPointer<EchonestControl> encontrol_ptr;

View File

@@ -16,12 +16,12 @@
#include "echonest/echonestgenerator.h" #include "echonest/echonestgenerator.h"
#include "echonest/echonestcontrol.h" #include "echonest/echonestcontrol.h"
#include "query.h" #include "tomahawk/query.h"
using namespace Tomahawk; using namespace Tomahawk;
EchonestFactory::GeneratorFactoryInterface() EchonestFactory::EchonestFactory()
{} {}
GeneratorInterface* GeneratorInterface*
@@ -32,12 +32,12 @@ EchonestFactory::create()
EchonestGenerator::EchonestGenerator ( QObject* parent ) EchonestGenerator::EchonestGenerator ( QObject* parent )
: GeneratorInterface ( parent ) : GeneratorInterface ( parent )
, m_type( "echonest" )
, m_mode( OnDemand )
{ {
m_typeSelectors << "Variety" << "Artist" << "Description" << "Tempo" << "Duration" << "Loudness" m_typeSelectors << "Variety" << "Artist" << "Description" << "Tempo" << "Duration" << "Loudness"
<< "Danceability" << "Energy" << "Artist Familiarity" << "Artist Hotttnesss" << "Song Familiarity" << "Danceability" << "Energy" << "Artist Familiarity" << "Artist Hotttnesss" << "Song Familiarity"
<< "Longitude" << "Latitude" << "Mode" << "Key" << "Sorting"; << "Longitude" << "Latitude" << "Mode" << "Key" << "Sorting";
m_type = "echonest";
m_mode = OnDemand;
} }
@@ -49,7 +49,7 @@ EchonestGenerator::~EchonestGenerator()
dyncontrol_ptr dyncontrol_ptr
EchonestGenerator::createControl( const QString& type ) const EchonestGenerator::createControl( const QString& type ) const
{ {
return dyncontrol_ptr( new EchonestControl( type, m_typeSelectors ) ); return dyncontrol_ptr( new EchonestControl( type ) );
} }
void void

View File

@@ -39,7 +39,7 @@ class EchonestGenerator : public GeneratorInterface
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit EchonestGenerator( QObject* parent ); explicit EchonestGenerator( QObject* parent = 0 );
virtual ~EchonestGenerator(); virtual ~EchonestGenerator();
virtual dyncontrol_ptr createControl( const QString& type = QString() ) const; virtual dyncontrol_ptr createControl( const QString& type = QString() ) const;

View File

@@ -1,24 +1,19 @@
#include "dynamic/generatorfactory.h" #include "dynamic/generatorfactory.h"
#include "dynamic/generatorinterface.h" #include "dynamic/generatorinterface.h"
Tomahawk::GeneratorFactory::GeneratorFactory() using namespace Tomahawk;
{
}
Tomahawk::GeneratorFactory::~GeneratorFactory() QHash< QString, GeneratorFactoryInterface* > GeneratorFactory::s_factories = QHash< QString, GeneratorFactoryInterface* >();
{
qDeleteAll( m_factories.values() );
}
generatorinterface_ptr Tomahawk::GeneratorFactory::create ( const QString& type ) geninterface_ptr GeneratorFactory::create ( const QString& type )
{ {
if( !m_factories.contains( type ) ) if( !s_factories.contains( type ) )
return geninterface_ptr(); return geninterface_ptr();
return geninterface_ptr( m_factories.value( type )->create() ); return geninterface_ptr( s_factories.value( type )->create() );
} }
void Tomahawk::GeneratorFactory::registerFactory ( const QString& type, Tomahawk::GeneratorFactoryInterface* interface ) void GeneratorFactory::registerFactory ( const QString& type, GeneratorFactoryInterface* interface )
{ {
m_factories.insert( type, interface ); s_factories.insert( type, interface );
} }

View File

@@ -29,7 +29,7 @@ public:
static void registerFactory( const QString& type, GeneratorFactoryInterface* interface ); static void registerFactory( const QString& type, GeneratorFactoryInterface* interface );
private: private:
static QHash<QString, GeneratorFactoryInterface*> m_factories; static QHash<QString, GeneratorFactoryInterface*> s_factories;
}; };

View File

@@ -0,0 +1,33 @@
/****************************************************************************************
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify it under *
* the terms of the GNU General Public License as published by the Free Software *
* Foundation; either version 2 of the License, or (at your option) any later *
* version. *
* *
* This program is distributed in the hope that it will be useful, but WITHOUT ANY *
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
* PARTICULAR PURPOSE. See the GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License along with *
* this program. If not, see <http://www.gnu.org/licenses/>. *
****************************************************************************************/
#include "dynamic/generatorinterface.h"
// lame
Tomahawk::GeneratorInterface::GeneratorInterface()
{
}
Tomahawk::GeneratorInterface::GeneratorInterface( QObject* parent ): QObject( parent )
{
}
Tomahawk::GeneratorInterface::~GeneratorInterface()
{
}

View File

@@ -24,12 +24,7 @@
#include <tomahawk/typedefs.h> #include <tomahawk/typedefs.h>
namespace Tomahawk { namespace Tomahawk {
enum GeneratorMode {
OnDemand = 0,
Static
};
/** /**
* The abstract interface for Dynamic Playlist Generators. Generators have the following features: * The abstract interface for Dynamic Playlist Generators. Generators have the following features:
* - They create new DynamicControls that are appropriate for the generator * - They create new DynamicControls that are appropriate for the generator
@@ -43,11 +38,12 @@ class GeneratorInterface : public QObject
Q_OBJECT Q_OBJECT
Q_PROPERTY( QString type READ type ) Q_PROPERTY( QString type READ type )
Q_PROPERTY( GeneratorMode mode READ mode WRITE setMode ); Q_PROPERTY( GeneratorMode mode READ mode WRITE setMode );
Q_ENUMS( GeneratorMode )
public: public:
explicit GeneratorInterface( QObject* parent = 0 ) : QObject( parent ) {} // can't inline constructors/destructors for forward declared shared pointer types
virtual ~GeneratorInterface() {} GeneratorInterface();
explicit GeneratorInterface( QObject* parent = 0 );
virtual ~GeneratorInterface();
// Can't make it pure otherwise we can't shove it in QVariants :-/ // Can't make it pure otherwise we can't shove it in QVariants :-/
// empty QString means use default // empty QString means use default
@@ -85,6 +81,9 @@ protected:
GeneratorMode m_mode; GeneratorMode m_mode;
QList< dyncontrol_ptr > m_controls; QList< dyncontrol_ptr > m_controls;
QStringList m_typeSelectors; QStringList m_typeSelectors;
private:
Q_DISABLE_COPY(GeneratorInterface)
}; };
typedef QSharedPointer<GeneratorInterface> geninterface_ptr; typedef QSharedPointer<GeneratorInterface> geninterface_ptr;

View File

@@ -1,3 +1,4 @@
#ifndef FILETRANSFERCONNECTION_H #ifndef FILETRANSFERCONNECTION_H
#define FILETRANSFERCONNECTION_H #define FILETRANSFERCONNECTION_H
@@ -7,6 +8,7 @@
#include "connection.h" #include "connection.h"
#include "tomahawk/result.h" #include "tomahawk/result.h"
#include "tomahawk/source.h"
class ControlConnection; class ControlConnection;
class BufferIODevice; class BufferIODevice;

View File

@@ -28,6 +28,13 @@ PlaylistEntry::queryvariant() const
} }
Playlist::Playlist( const source_ptr& author )
: m_source( author )
, m_lastmodified( 0 )
{
qDebug() << Q_FUNC_INFO << "JSON";
}
// used when loading from DB: // used when loading from DB:
Playlist::Playlist( const source_ptr& src, Playlist::Playlist( const source_ptr& src,
const QString& currentrevision, const QString& currentrevision,

View File

@@ -1,6 +1,7 @@
#include "plitem.h" #include "plitem.h"
#include "utils/tomahawkutils.h" #include "utils/tomahawkutils.h"
#include "tomahawk/playlist.h"
#include <QDebug> #include <QDebug>
@@ -66,6 +67,18 @@ PlItem::PlItem( const Tomahawk::plentry_ptr& entry, PlItem* parent, int row )
setupItem( entry->query(), parent, row ); setupItem( entry->query(), parent, row );
} }
const Tomahawk::plentry_ptr&
PlItem::entry() const
{
return m_entry;
}
const Tomahawk::query_ptr&
PlItem::query() const
{
if ( !m_entry.isNull() ) return m_entry->query(); else return m_query;
}
void void
PlItem::setupItem( const Tomahawk::query_ptr& query, PlItem* parent, int row ) PlItem::setupItem( const Tomahawk::query_ptr& query, PlItem* parent, int row )

View File

@@ -2,11 +2,11 @@
#define PLITEM_H #define PLITEM_H
#include <QHash> #include <QHash>
#include <QVector>
#include <QPersistentModelIndex> #include <QPersistentModelIndex>
#include <QAbstractItemModel> #include <QAbstractItemModel>
#include "tomahawk/query.h" #include "tomahawk/result.h"
#include "tomahawk/typedefs.h" #include "tomahawk/typedefs.h"
class PlItem : public QObject class PlItem : public QObject
@@ -14,15 +14,15 @@ class PlItem : public QObject
Q_OBJECT Q_OBJECT
public: public:
~PlItem(); virtual ~PlItem();
explicit PlItem( PlItem* parent = 0, QAbstractItemModel* model = 0 ); explicit PlItem( PlItem* parent = 0, QAbstractItemModel* model = 0 );
explicit PlItem( const QString& caption, PlItem* parent = 0 ); explicit PlItem( const QString& caption, PlItem* parent = 0 );
explicit PlItem( const Tomahawk::query_ptr& query, PlItem* parent = 0, int row = -1 ); explicit PlItem( const Tomahawk::query_ptr& query, PlItem* parent = 0, int row = -1 );
explicit PlItem( const Tomahawk::plentry_ptr& entry, PlItem* parent = 0, int row = -1 ); explicit PlItem( const Tomahawk::plentry_ptr& entry, PlItem* parent = 0, int row = -1 );
const Tomahawk::plentry_ptr& entry() const { return m_entry; }; const Tomahawk::plentry_ptr& entry() const;
const Tomahawk::query_ptr& query() const { if ( !m_entry.isNull() ) return m_entry->query(); else return m_query; }; const Tomahawk::query_ptr& query() const;
bool isPlaying() { return m_isPlaying; } bool isPlaying() { return m_isPlaying; }
void setIsPlaying( bool b ) { m_isPlaying = b; emit dataChanged(); } void setIsPlaying( bool b ) { m_isPlaying = b; emit dataChanged(); }

View File

@@ -30,6 +30,25 @@ Result::Result( const QVariant& v, const collection_ptr& collection )
connect( m_collection->source().data(), SIGNAL( offline() ), SIGNAL( becomingUnavailable() ), Qt::QueuedConnection ); connect( m_collection->source().data(), SIGNAL( offline() ), SIGNAL( becomingUnavailable() ), Qt::QueuedConnection );
} }
Result::~Result() {}
artist_ptr
Result::artist() const
{
return m_artist;
}
album_ptr
Result::album() const
{
return m_album;
}
collection_ptr
Result::collection() const
{
return m_collection;
}
float float
Result::score() const Result::score() const

View File

@@ -10,7 +10,6 @@
using namespace Tomahawk; using namespace Tomahawk;
Source::Source( const QString &username, ControlConnection* cc ) Source::Source( const QString &username, ControlConnection* cc )
: QObject() : QObject()
, m_isLocal( false ) , m_isLocal( false )

View File

@@ -3,6 +3,8 @@
#include <QWheelEvent> #include <QWheelEvent>
#include "tomahawk/tomahawkapp.h" #include "tomahawk/tomahawkapp.h"
#include "tomahawk/artist.h"
#include "audio/audioengine.h" #include "audio/audioengine.h"
#include "tomahawkwindow.h" #include "tomahawkwindow.h"

View File

@@ -16,6 +16,7 @@
#include "tomahawk/functimeout.h" #include "tomahawk/functimeout.h"
#include "tomahawk/playlist.h" #include "tomahawk/playlist.h"
#include "tomahawk/query.h" #include "tomahawk/query.h"
#include "tomahawk/artist.h"
#include "database/databasecommand_collectionstats.h" #include "database/databasecommand_collectionstats.h"
#include "topbar/topbar.h" #include "topbar/topbar.h"

View File

@@ -4,6 +4,7 @@
#include <QVBoxLayout> #include <QVBoxLayout>
#include "tomahawk/tomahawkapp.h" #include "tomahawk/tomahawkapp.h"
#include "tomahawk/artist.h"
#include "network/filetransferconnection.h" #include "network/filetransferconnection.h"
#include "network/servent.h" #include "network/servent.h"