diff --git a/src/dynamic/widgets/DynamicControlList.cpp b/src/dynamic/widgets/DynamicControlList.cpp index dae76e92a..1d5030fb5 100644 --- a/src/dynamic/widgets/DynamicControlList.cpp +++ b/src/dynamic/widgets/DynamicControlList.cpp @@ -82,6 +82,10 @@ DynamicControlList::init() void DynamicControlList::setControls( const geninterface_ptr& generator, const QList< dyncontrol_ptr >& controls) { + if( !m_controls.isEmpty() ) { + qDeleteAll( m_controls ); + m_controls.clear(); + } m_generator = generator; if( controls.isEmpty() ) { m_controls << new DynamicControlWidget( generator->createControl(), false, false, false, this ); @@ -138,10 +142,14 @@ void DynamicControlList::addNewControl() m_controls.last()->setShowCollapseButton( false ); m_controls.last()->setShowPlusButton( false ); m_controls.last()->setShowMinusButton( true ); - m_controls.append( new DynamicControlWidget( m_generator->createControl(), true, false, true, this ) ); + dyncontrol_ptr control = m_generator->createControl(); + m_controls.append( new DynamicControlWidget( control, true, false, true, this ) ); m_layout->addWidget( m_controls.last() ); connect( m_controls.last(), SIGNAL( addNewControl() ), this, SLOT( addNewControl() ) ); connect( m_controls.last(), SIGNAL( removeControl() ), this, SLOT( removeControl() ) ); + connect( m_controls.last(), SIGNAL( changed() ), this, SLOT( controlChanged() ) ); + + emit controlsChanged(); } void DynamicControlList::removeControl() @@ -153,8 +161,18 @@ void DynamicControlList::removeControl() m_controls.last()->setShowCollapseButton( true ); m_controls.last()->setShowPlusButton( true ); m_controls.last()->setShowMinusButton( false ); + + emit controlsChanged(); } +void DynamicControlList::controlChanged() +{ + Q_ASSERT( sender() && qobject_cast(sender()) ); + + emit controlChanged( qobject_cast(sender())->control() ); +} + + void DynamicControlList::paintEvent(QPaintEvent* ) { } diff --git a/src/dynamic/widgets/DynamicControlList.h b/src/dynamic/widgets/DynamicControlList.h index 436a47909..d465b9b6e 100644 --- a/src/dynamic/widgets/DynamicControlList.h +++ b/src/dynamic/widgets/DynamicControlList.h @@ -46,11 +46,16 @@ public: virtual void paintEvent(QPaintEvent* ); +signals: + void controlsChanged(); + void controlChanged( const dyncontrol_ptr& control ); + public slots: virtual void onHidden(QWidget* ); virtual void onShown(QWidget* ); void addNewControl(); void removeControl(); + void controlChanged(); private: void init(); diff --git a/src/dynamic/widgets/DynamicControlWidget.cpp b/src/dynamic/widgets/DynamicControlWidget.cpp index 1e2de0006..2717e66d2 100644 --- a/src/dynamic/widgets/DynamicControlWidget.cpp +++ b/src/dynamic/widgets/DynamicControlWidget.cpp @@ -74,8 +74,8 @@ DynamicControlWidget::DynamicControlWidget( const Tomahawk::dyncontrol_ptr& cont m_collapseL->setCurrentIndex( 0 ); connect( m_collapseButton, SIGNAL( clicked( bool ) ), this, SIGNAL( collapse() ) ); - - connect( m_typeSelector, SIGNAL( currentIndexChanged( QString ) ), SLOT( typeSelectorChanged( QString ) ) ); + connect( m_typeSelector, SIGNAL( currentIndexChanged( QString ) ), SLOT( typeSelectorChanged( QString ) ) ); + connect( m_control.data(), SIGNAL( changed() ), this, SIGNAL( changed() ) ); m_layout->addWidget( m_typeSelector, 0, Qt::AlignLeft ); @@ -149,6 +149,7 @@ DynamicControlWidget::typeSelectorChanged( QString type ) m_control->inputField()->show(); } + emit changed(); } void diff --git a/src/dynamic/widgets/DynamicControlWidget.h b/src/dynamic/widgets/DynamicControlWidget.h index 00da98041..305b82abc 100644 --- a/src/dynamic/widgets/DynamicControlWidget.h +++ b/src/dynamic/widgets/DynamicControlWidget.h @@ -55,6 +55,7 @@ signals: void addNewControl(); void collapse(); void removeControl(); + void changed(); private slots: void typeSelectorChanged( QString ); diff --git a/src/dynamic/widgets/DynamicWidget.cpp b/src/dynamic/widgets/DynamicWidget.cpp index 3f097f1cd..e0ede92d7 100644 --- a/src/dynamic/widgets/DynamicWidget.cpp +++ b/src/dynamic/widgets/DynamicWidget.cpp @@ -81,8 +81,11 @@ DynamicWidget::DynamicWidget( const Tomahawk::dynplaylist_ptr& playlist, QWidget m_splitter->show( 0, false ); loadDynamicPlaylist( playlist ); - + setLayout( m_layout ); + + connect( m_controls, SIGNAL( controlChanged( dyncontrol_ptr ) ), this, SLOT( controlChanged( dyncontrol_ptr ) ), Qt::QueuedConnection ); + connect( m_controls, SIGNAL( controlsChanged() ), this, SLOT( controlsChanged() ), Qt::QueuedConnection ); } DynamicWidget::~DynamicWidget() @@ -141,3 +144,15 @@ DynamicWidget::tracksGenerated( const QList< query_ptr >& queries ) m_playlist->addEntries( queries, m_playlist->currentrevision() ); m_playlist->resolve(); } + +void DynamicWidget::controlsChanged() +{ + // save the current playlist + m_playlist->createNewRevision(); +} + +void DynamicWidget::controlChanged(const Tomahawk::dyncontrol_ptr& control) +{ + +} + diff --git a/src/dynamic/widgets/DynamicWidget.h b/src/dynamic/widgets/DynamicWidget.h index 6e8320113..febd0ca7a 100644 --- a/src/dynamic/widgets/DynamicWidget.h +++ b/src/dynamic/widgets/DynamicWidget.h @@ -18,8 +18,10 @@ #define DYNAMIC_WIDGET_H #include -#include -#include + +#include "typedefs.h" +#include "dynamic/DynamicPlaylist.h" +#include "dynamic/DynamicControl.h" class QVBoxLayout; class QHBoxLayout; @@ -57,6 +59,9 @@ private slots: void generate(); void tracksGenerated( const QList< Tomahawk::query_ptr>& queries ); + void controlsChanged(); + void controlChanged( const dyncontrol_ptr& control ); + private: dynplaylist_ptr m_playlist; QVBoxLayout* m_layout; diff --git a/src/libtomahawk/database/databasecommand_loaddynamicplaylist.cpp b/src/libtomahawk/database/databasecommand_loaddynamicplaylist.cpp index a17df77fc..4a45fa17e 100644 --- a/src/libtomahawk/database/databasecommand_loaddynamicplaylist.cpp +++ b/src/libtomahawk/database/databasecommand_loaddynamicplaylist.cpp @@ -7,6 +7,7 @@ #include "tomahawksqlquery.h" #include "dynamic/DynamicControl.h" #include "dynamic/GeneratorInterface.h" +#include using namespace Tomahawk; @@ -27,12 +28,29 @@ DatabaseCommand_LoadDynamicPlaylist::exec( DatabaseImpl* dbi ) controlsQuery.addBindValue( revisionGuid() ); controlsQuery.exec(); - QList< dyncontrol_ptr > controls; + QString type; + GeneratorMode mode; + + QList< QVariantMap > controls; QString playlist_guid; - if( controlsQuery.next() ) + qDebug() << "Loading controls..." << revisionGuid(); + qDebug() << "SELECT playlist_revision.playlist, controls, plmode, pltype " + "FROM dynamic_playlist_revision, playlist_revision " + "WHERE dynamic_playlist_revision.guid = "<< revisionGuid() << " AND playlist_revision.guid = dynamic_playlist_revision.guid"; + if( controlsQuery.first() ) { playlist_guid = controlsQuery.value( 0 ).toString(); - QStringList controlIds = controlsQuery.value( 1 ).toStringList(); + QJson::Parser parser; + bool ok; + QVariant v = parser.parse( controlsQuery.value(1).toByteArray(), &ok ); + Q_ASSERT( ok && v.type() == QVariant::List ); //TODO + + + type = controlsQuery.value( 3 ).toString(); + GeneratorMode mode = static_cast( controlsQuery.value( 2 ).toInt() ); + + QStringList controlIds = v.toStringList(); + qDebug() << "Got controls in dynamic playlist, loading:" << controlIds << controlsQuery.value(1); foreach( const QString& controlId, controlIds ) { TomahawkSqlQuery controlQuery = dbi->newquery(); @@ -43,27 +61,30 @@ DatabaseCommand_LoadDynamicPlaylist::exec( DatabaseImpl* dbi ) 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() ); + QVariantMap c; + c[ "type" ] = type; + c[ "id" ] = controlId; + c[ "selectedType" ] = controlQuery.value( 0 ).toString(); + c["match" ] = controlQuery.value( 1 ).toString(); + c[ "input" ] = controlQuery.value( 2 ).toString(); controls << c; } } + } else { + // No controls, lets load the info we need directly from the playlist table + TomahawkSqlQuery info = dbi->newquery(); + info.prepare( QString( "SELECT dynamic_playlist.pltype, dynamic_playlist.plmode FROM playlist, dynamic_playlist WHERE playlist.guid = \"%1\" AND playlist.guid = dynamic_playlist.guid" ).arg( playlist_guid ) ); + if( !info.exec() ) { + qWarning() << "Failed to load dynplaylist info.."; + return; + } else if( !info.first() ) { + qWarning() << "Noo results for queryL:" << info.lastQuery(); + return; + } + type = info.value( 0 ).toString(); + mode = static_cast( info.value( 1 ).toInt() ); } - - TomahawkSqlQuery info = dbi->newquery(); - info.prepare( QString( "SELECT dynamic_playlist.pltype, dynamic_playlist.plmode FROM playlist, dynamic_playlist WHERE playlist.guid = \"%1\" AND playlist.guid = dynamic_playlist.guid" ).arg( playlist_guid ) ); - if( !info.exec() ) { - qWarning() << "Failed to load dynplaylist info.."; - return; - } else if( !info.first() ) { - qWarning() << "Noo results for queryL:" << info.lastQuery(); - return; - } - QString type = info.value( 0 ).toString(); - GeneratorMode mode = static_cast( info.value( 1 ).toInt() ); + if( mode == OnDemand ) { Q_ASSERT( m_entrymap.isEmpty() ); // ondemand should have no entry diff --git a/src/libtomahawk/database/databasecommand_loaddynamicplaylist.h b/src/libtomahawk/database/databasecommand_loaddynamicplaylist.h index e9599a8bb..8b7205f73 100644 --- a/src/libtomahawk/database/databasecommand_loaddynamicplaylist.h +++ b/src/libtomahawk/database/databasecommand_loaddynamicplaylist.h @@ -29,14 +29,14 @@ signals: void done( QString, bool, QString, - QList< Tomahawk::dyncontrol_ptr>, + QList< QVariantMap>, bool ); // used when loading a static playlist void done( QString, QList< QString >, QList< QString >, QString, - QList< Tomahawk::dyncontrol_ptr>, + QList< QVariantMap>, bool, QMap< QString, Tomahawk::plentry_ptr >, bool ); diff --git a/src/libtomahawk/database/databasecommand_setdynamicplaylistrevision.cpp b/src/libtomahawk/database/databasecommand_setdynamicplaylistrevision.cpp index e06b97cbd..1f8c2fa36 100644 --- a/src/libtomahawk/database/databasecommand_setdynamicplaylistrevision.cpp +++ b/src/libtomahawk/database/databasecommand_setdynamicplaylistrevision.cpp @@ -73,16 +73,7 @@ DatabaseCommand_SetDynamicPlaylistRevision::postCommitHook() 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 @@ -140,6 +131,7 @@ DatabaseCommand_SetDynamicPlaylistRevision::exec( DatabaseImpl* lib ) "VALUES( ?, ?, ?, ?, ? )" ); foreach( const dyncontrol_ptr& control, m_controls ) { + qDebug() << "inserting dynamic control:" << control->id() << m_playlistguid << control->selectedType() << control->match() << control->input(); controlsQuery.addBindValue( control->id() ); controlsQuery.addBindValue( m_playlistguid ); controlsQuery.addBindValue( control->selectedType() ); diff --git a/src/libtomahawk/database/databaseworker.cpp b/src/libtomahawk/database/databaseworker.cpp index 126d45b7b..10ff554dc 100644 --- a/src/libtomahawk/database/databaseworker.cpp +++ b/src/libtomahawk/database/databaseworker.cpp @@ -167,7 +167,7 @@ DatabaseWorker::logOp( DatabaseCommandLoggable* command ) QVariantMap variant = QJson::QObjectHelper::qobject2qvariant( command ); QByteArray ba = m_serializer.serialize( variant ); - qDebug() << "OP JSON:" << ba.isNull() << ba << "from:" << variant; // debug +// qDebug() << "OP JSON:" << ba.isNull() << ba << "from:" << variant; // debug bool compressed = false; if( ba.length() >= 512 ) diff --git a/src/libtomahawk/dynamic/DynamicControl.h b/src/libtomahawk/dynamic/DynamicControl.h index 80fa047a7..44264a701 100644 --- a/src/libtomahawk/dynamic/DynamicControl.h +++ b/src/libtomahawk/dynamic/DynamicControl.h @@ -39,6 +39,7 @@ namespace Tomahawk class DynamicControl : public QObject { Q_OBJECT + Q_PROPERTY( QString type READ type WRITE setType ) // the generator type associated with this control Q_PROPERTY( QString id READ id WRITE setId ) Q_PROPERTY( QString selectedType READ selectedType WRITE setSelectedType ) Q_PROPERTY( QString match READ match WRITE setMatch ) @@ -83,6 +84,12 @@ public: }; void setId( const QString& id ) { m_id = id; } + void setType( const QString& type ) { m_type = type; } + QString type() const { return m_type; } + +signals: + void changed(); + public slots: /** * Sets the type to the newly specified one. Note that this will update the matchSelector @@ -98,6 +105,7 @@ protected: QString m_input; private: + QString m_type; QString m_selectedType; QStringList m_typeSelectors; QString m_id; diff --git a/src/libtomahawk/dynamic/DynamicPlaylist.cpp b/src/libtomahawk/dynamic/DynamicPlaylist.cpp index 1de686bff..56fa17bd8 100644 --- a/src/libtomahawk/dynamic/DynamicPlaylist.cpp +++ b/src/libtomahawk/dynamic/DynamicPlaylist.cpp @@ -125,6 +125,19 @@ DynamicPlaylist::create( const Tomahawk::source_ptr& author, } +void +DynamicPlaylist::createNewRevision( const QString& newUuid ) +{ + if( mode() == Static ) + { + createNewRevision( newUuid.isEmpty() ? uuid() : newUuid, currentrevision(), type(), generator()->controls(), entries() ); + } else if( mode() == OnDemand ) + { + createNewRevision( newUuid.isEmpty() ? uuid() : newUuid, currentrevision(), type(), generator()->controls()); + } +} + + // create a new revision that will be a static playlist, as it has entries void DynamicPlaylist::createNewRevision( const QString& newrev, @@ -190,19 +203,19 @@ DynamicPlaylist::loadRevision( const QString& rev ) connect( cmd, SIGNAL( done( QString, bool, QString, - QList< Tomahawk::dyncontrol_ptr>, + QList< QVariantMap >, bool ) ), SLOT( setRevision( QString, bool, QString, - QList< Tomahawk::dyncontrol_ptr>, + QList< QVariantMap >, bool) ) ); } else if( m_generator->mode() == Static ) { connect( cmd, SIGNAL( done( QString, QList< QString >, QList< QString >, QString, - QList< Tomahawk::dyncontrol_ptr>, + QList< QVariantMap >, bool, QMap< QString, Tomahawk::plentry_ptr >, bool ) ), @@ -210,7 +223,7 @@ DynamicPlaylist::loadRevision( const QString& rev ) QList< QString >, QList< QString >, QString, - QList< Tomahawk::dyncontrol_ptr>, + QList< QVariantMap >, bool, QMap< QString, Tomahawk::plentry_ptr >, bool ) ) ); @@ -264,16 +277,14 @@ void DynamicPlaylist::addEntry(const Tomahawk::query_ptr& query, const QString& addEntries( queries, oldrev ); } -// static version -void -DynamicPlaylist::setRevision( const QString& rev, - const QList< QString >& neworderedguids, - const QList< QString >& oldorderedguids, - const QString& type, - const QList< Tomahawk::dyncontrol_ptr>& controls, - bool is_newest_rev, - const QMap< QString, Tomahawk::plentry_ptr >& addedmap, - bool applied ) +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() ) @@ -307,17 +318,46 @@ DynamicPlaylist::setRevision( const QString& rev, if( applied ) setCurrentrevision( rev ); -// qDebug() << "EMITTING REVISION LOADED 1!"; - emit dynamicRevisionLoaded( dpr ); + // qDebug() << "EMITTING REVISION LOADED 1!"; + emit dynamicRevisionLoaded( dpr ); } -// ondemand version + void DynamicPlaylist::setRevision( const QString& rev, - bool is_newest_rev, + const QList< QString >& neworderedguids, + const QList< QString >& oldorderedguids, const QString& type, - const QList< Tomahawk::dyncontrol_ptr>& controls, + const QList< QVariantMap>& controlsV, + bool is_newest_rev, + const QMap< QString, Tomahawk::plentry_ptr >& addedmap, bool applied ) +{ + if( QThread::currentThread() != thread() ) + { + QMetaObject::invokeMethod( this, + "setRevision", + Qt::BlockingQueuedConnection, + Q_ARG( QString, rev ), + Q_ARG( QList , neworderedguids ), + Q_ARG( QList , oldorderedguids ), + Q_ARG( QString , type ), + QGenericArgument( "QList< QVariantMap > " , (const void*)&controlsV ), + Q_ARG( bool, is_newest_rev ), + QGenericArgument( "QMap< QString,Tomahawk::plentry_ptr > " , (const void*)&addedmap ), + Q_ARG( bool, applied ) ); + } + + QList controls = variantsToControl( controlsV ); + setRevision( rev, neworderedguids, oldorderedguids, type, controls, is_newest_rev, addedmap, applied ); + +} + +void DynamicPlaylist::setRevision( const QString& rev, + bool is_newest_rev, + const QString& type, + const QList< dyncontrol_ptr >& controls, + bool applied ) { if( QThread::currentThread() != thread() ) { @@ -334,7 +374,7 @@ DynamicPlaylist::setRevision( const QString& rev, if( m_generator->type() != type ) { // new generator needed m_generator = geninterface_ptr( GeneratorFactory::create( type ) ); } - + m_generator->setControls( controls ); m_generator->setMode( OnDemand ); @@ -345,7 +385,43 @@ DynamicPlaylist::setRevision( const QString& rev, dpr.type = type; dpr.mode = OnDemand; -// qDebug() << "EMITTING REVISION LOADED 2!"; - emit dynamicRevisionLoaded( dpr ); + // qDebug() << "EMITTING REVISION LOADED 2!"; + emit dynamicRevisionLoaded( dpr ); +} + + +void +DynamicPlaylist::setRevision( const QString& rev, + bool is_newest_rev, + const QString& type, + const QList< QVariantMap>& controlsV, + 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< QVariantMap >" , (const void*)&controlsV ), + Q_ARG( bool, applied ) ); + return; + } + + QList controls = variantsToControl( controlsV ); + setRevision( rev, is_newest_rev, type, controls, applied ); +} + +QList< dyncontrol_ptr > DynamicPlaylist::variantsToControl( const QList< QVariantMap >& controlsV ) +{ + QList realControls; + foreach( QVariantMap controlV, controlsV ) { + dyncontrol_ptr control = GeneratorFactory::createControl( controlV.value( "type" ).toString(), controlV.value( "selectedType" ).toString() ); + QJson::QObjectHelper::qvariant2qobject( controlV, control.data() ); + realControls << control; + } + return realControls; } diff --git a/src/libtomahawk/dynamic/DynamicPlaylist.h b/src/libtomahawk/dynamic/DynamicPlaylist.h index 396442f13..b13442f3d 100644 --- a/src/libtomahawk/dynamic/DynamicPlaylist.h +++ b/src/libtomahawk/dynamic/DynamicPlaylist.h @@ -87,6 +87,10 @@ public: QString type() const; geninterface_ptr generator() const; + // Creates a new revision from the playlist in memory. Use this is you change the controls or + // mode of a playlist and want to save it to db/others. + void createNewRevision( const QString& uuid = QString() ); + virtual void addEntries( const QList< query_ptr >& queries, const QString& oldrev ); virtual void addEntry( const Tomahawk::query_ptr& query, const QString& oldrev ); @@ -116,21 +120,37 @@ public slots: void reportDeleted( const Tomahawk::dynplaylist_ptr& self ); // called from setdynamicplaylistrevision db cmd - // static version + // 4 options, because dbcmds can't create qwidgets: + // static version, qvariant controls + // static version, dyncontrol_ptr controls + // ondemand version, qvariant controls + // ondemand version, dyncontrol_ptr controls void setRevision( const QString& rev, const QList& neworderedguids, const QList& oldorderedguids, const QString& type, - const QList< Tomahawk::dyncontrol_ptr>& controls, + const QList< QVariantMap >& controls, bool is_newest_rev, const QMap< QString, Tomahawk::plentry_ptr >& addedmap, bool applied ); - + void setRevision( const QString& rev, + const QList& neworderedguids, + const QList& 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< Tomahawk::dyncontrol_ptr>& controls, + const QList< QVariantMap>& controls, + bool applied ); + 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: @@ -155,6 +175,7 @@ private: bool shared ); private: + QList< dyncontrol_ptr > variantsToControl( const QList< QVariantMap >& controlsV ); geninterface_ptr m_generator; }; diff --git a/src/libtomahawk/dynamic/GeneratorFactory.cpp b/src/libtomahawk/dynamic/GeneratorFactory.cpp index 794909911..8b33af936 100644 --- a/src/libtomahawk/dynamic/GeneratorFactory.cpp +++ b/src/libtomahawk/dynamic/GeneratorFactory.cpp @@ -5,7 +5,8 @@ using namespace Tomahawk; QHash< QString, GeneratorFactoryInterface* > GeneratorFactory::s_factories = QHash< QString, GeneratorFactoryInterface* >(); -geninterface_ptr GeneratorFactory::create ( const QString& type ) +geninterface_ptr +GeneratorFactory::create ( const QString& type ) { if( type.isEmpty() && !s_factories.isEmpty() ) // default, return first return geninterface_ptr( s_factories.begin().value()->create() ); @@ -16,12 +17,33 @@ geninterface_ptr GeneratorFactory::create ( const QString& type ) return geninterface_ptr( s_factories.value( type )->create() ); } -void GeneratorFactory::registerFactory ( const QString& type, GeneratorFactoryInterface* interface ) +dyncontrol_ptr +GeneratorFactory::createControl(const QString& generatorType, const QString& controlType) +{ + if( generatorType.isEmpty() || !s_factories.contains( generatorType ) ) + return dyncontrol_ptr(); + + return s_factories.value( generatorType )->createControl( controlType ); +} + + +void +GeneratorFactory::registerFactory ( const QString& type, GeneratorFactoryInterface* interface ) { s_factories.insert( type, interface ); } -QStringList GeneratorFactory::types() +QStringList +GeneratorFactory::types() { return s_factories.keys(); } + +QStringList +GeneratorFactory::typeSelectors(const QString& type) +{ + if( !s_factories.contains( type ) ) + return QStringList(); + + return s_factories.value( type )->typeSelectors(); +} diff --git a/src/libtomahawk/dynamic/GeneratorFactory.h b/src/libtomahawk/dynamic/GeneratorFactory.h index 204c06ec4..0a6f464de 100644 --- a/src/libtomahawk/dynamic/GeneratorFactory.h +++ b/src/libtomahawk/dynamic/GeneratorFactory.h @@ -5,6 +5,7 @@ #include #include "dynamic/GeneratorInterface.h" +#include "typedefs.h" namespace Tomahawk { @@ -17,6 +18,13 @@ public: GeneratorFactoryInterface() {} virtual GeneratorInterface* create() = 0; + /** + * Create a control for this generator, not tied to this generator itself. Used when loading dynamic + * playlists from a dbcmd. + */ + virtual dyncontrol_ptr createControl( const QString& controlType = QString() ) = 0; + + virtual QStringList typeSelectors() const = 0; }; /** @@ -26,8 +34,12 @@ class GeneratorFactory { public: static geninterface_ptr create( const QString& type ); + // only used when loading from dbcmd + static dyncontrol_ptr createControl( const QString& generatorType, const QString& controlType = QString() ); + static void registerFactory( const QString& type, GeneratorFactoryInterface* interface ); static QStringList types(); + static QStringList typeSelectors( const QString& type ); private: static QHash s_factories; diff --git a/src/libtomahawk/dynamic/GeneratorInterface.cpp b/src/libtomahawk/dynamic/GeneratorInterface.cpp index 40813fa59..48e19ae9d 100644 --- a/src/libtomahawk/dynamic/GeneratorInterface.cpp +++ b/src/libtomahawk/dynamic/GeneratorInterface.cpp @@ -60,8 +60,9 @@ Tomahawk::GeneratorInterface::setControls( const QList< Tomahawk::dyncontrol_ptr m_controls = controls; } -Tomahawk::dyncontrol_ptr Tomahawk::GeneratorInterface::createControl(const QString& type) +Tomahawk::dyncontrol_ptr +Tomahawk::GeneratorInterface::createControl(const QString& type) { + Q_ASSERT( false ); return dyncontrol_ptr(); } - diff --git a/src/libtomahawk/dynamic/GeneratorInterface.h b/src/libtomahawk/dynamic/GeneratorInterface.h index e5ad2284b..62ac295b1 100644 --- a/src/libtomahawk/dynamic/GeneratorInterface.h +++ b/src/libtomahawk/dynamic/GeneratorInterface.h @@ -75,9 +75,7 @@ public: void addControl( const dyncontrol_ptr& control ); void clearControls(); void setControls( const QList< dyncontrol_ptr>& controls ); - - QStringList typeSelectors() const { return m_typeSelectors; } - + signals: void generated( const QList< Tomahawk::query_ptr>& queries ); @@ -85,7 +83,6 @@ protected: QString m_type; GeneratorMode m_mode; QList< dyncontrol_ptr > m_controls; - QStringList m_typeSelectors; }; typedef QSharedPointer geninterface_ptr; diff --git a/src/libtomahawk/dynamic/echonest/EchonestControl.cpp b/src/libtomahawk/dynamic/echonest/EchonestControl.cpp index dc1ace2f1..8e7f8b99f 100644 --- a/src/libtomahawk/dynamic/echonest/EchonestControl.cpp +++ b/src/libtomahawk/dynamic/echonest/EchonestControl.cpp @@ -22,9 +22,10 @@ #include -Tomahawk::EchonestControl::EchonestControl( const QString& type, const QStringList& typeSelectors, QObject* parent ) - : DynamicControl ( type.isEmpty() ? "Artist" : type, typeSelectors, parent ) +Tomahawk::EchonestControl::EchonestControl( const QString& selectedType, const QStringList& typeSelectors, QObject* parent ) + : DynamicControl ( selectedType.isEmpty() ? "Artist" : selectedType, typeSelectors, parent ) { + setType( "echonest" ); updateWidgets(); } @@ -80,7 +81,9 @@ Tomahawk::EchonestControl::updateWidgets() input->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Fixed ); connect( match, SIGNAL( currentIndexChanged(int) ), this, SLOT( updateData() ) ); + connect( match, SIGNAL( currentIndexChanged(int) ), this, SIGNAL( changed() ) ); connect( input, SIGNAL( textChanged(QString) ), this, SLOT( updateData() ) ); + connect( input, SIGNAL( editingFinished() ), this, SIGNAL( changed() ) ); match->hide(); input->hide(); diff --git a/src/libtomahawk/dynamic/echonest/EchonestControl.h b/src/libtomahawk/dynamic/echonest/EchonestControl.h index 1215ce69e..dbb153bb9 100644 --- a/src/libtomahawk/dynamic/echonest/EchonestControl.h +++ b/src/libtomahawk/dynamic/echonest/EchonestControl.h @@ -34,15 +34,15 @@ public: /// Converts this to an echonest suitable parameter Echonest::DynamicPlaylist::PlaylistParamData toENParam() const; + /// DO NOT USE IF YOU ARE NOT A DBCMD + explicit EchonestControl( const QString& type, const QStringList& typeSelectors, QObject* parent = 0 ); + public slots: virtual void setSelectedType ( const QString& type ); private slots: void updateData(); -protected: - explicit EchonestControl( const QString& type, const QStringList& typeSelectors, QObject* parent = 0 ); - private: void updateWidgets(); diff --git a/src/libtomahawk/dynamic/echonest/EchonestGenerator.cpp b/src/libtomahawk/dynamic/echonest/EchonestGenerator.cpp index 1d8106ead..d67c16211 100644 --- a/src/libtomahawk/dynamic/echonest/EchonestGenerator.cpp +++ b/src/libtomahawk/dynamic/echonest/EchonestGenerator.cpp @@ -30,12 +30,24 @@ EchonestFactory::create() return new EchonestGenerator(); } +dyncontrol_ptr +EchonestFactory::createControl( const QString& controlType ) +{ + return dyncontrol_ptr( new EchonestControl( controlType, typeSelectors() ) ); +} + +QStringList +EchonestFactory::typeSelectors() const +{ + return QStringList() << "Artist" << "Variety" << "Description" << "Tempo" << "Duration" << "Loudness" + << "Danceability" << "Energy" << "Artist Familiarity" << "Artist Hotttnesss" << "Song Familiarity" + << "Longitude" << "Latitude" << "Mode" << "Key" << "Sorting"; +} + + EchonestGenerator::EchonestGenerator ( QObject* parent ) : GeneratorInterface ( parent ) { - m_typeSelectors << "Artist" << "Variety" << "Description" << "Tempo" << "Duration" << "Loudness" - << "Danceability" << "Energy" << "Artist Familiarity" << "Artist Hotttnesss" << "Song Familiarity" - << "Longitude" << "Latitude" << "Mode" << "Key" << "Sorting"; m_type = "echonest"; m_mode = OnDemand; @@ -49,7 +61,7 @@ EchonestGenerator::~EchonestGenerator() dyncontrol_ptr EchonestGenerator::createControl( const QString& type ) { - m_controls << dyncontrol_ptr( new EchonestControl( type, m_typeSelectors ) ); + m_controls << dyncontrol_ptr( new EchonestControl( type, GeneratorFactory::typeSelectors( m_type ) ) ); return m_controls.last(); } diff --git a/src/libtomahawk/dynamic/echonest/EchonestGenerator.h b/src/libtomahawk/dynamic/echonest/EchonestGenerator.h index cfbdd5b05..82cbbd4ff 100644 --- a/src/libtomahawk/dynamic/echonest/EchonestGenerator.h +++ b/src/libtomahawk/dynamic/echonest/EchonestGenerator.h @@ -32,7 +32,8 @@ public: EchonestFactory(); virtual GeneratorInterface* create(); - + virtual dyncontrol_ptr createControl( const QString& controlType = QString() ); + virtual QStringList typeSelectors() const; }; class EchonestGenerator : public GeneratorInterface