mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-17 19:37:09 +02:00
lots of work on dynamic playlists. loading, saving, updating, working, etc.
crashes on loading still
This commit is contained in:
@@ -82,6 +82,10 @@ DynamicControlList::init()
|
|||||||
void
|
void
|
||||||
DynamicControlList::setControls( const geninterface_ptr& generator, const QList< dyncontrol_ptr >& controls)
|
DynamicControlList::setControls( const geninterface_ptr& generator, const QList< dyncontrol_ptr >& controls)
|
||||||
{
|
{
|
||||||
|
if( !m_controls.isEmpty() ) {
|
||||||
|
qDeleteAll( m_controls );
|
||||||
|
m_controls.clear();
|
||||||
|
}
|
||||||
m_generator = generator;
|
m_generator = generator;
|
||||||
if( controls.isEmpty() ) {
|
if( controls.isEmpty() ) {
|
||||||
m_controls << new DynamicControlWidget( generator->createControl(), false, false, false, this );
|
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()->setShowCollapseButton( false );
|
||||||
m_controls.last()->setShowPlusButton( false );
|
m_controls.last()->setShowPlusButton( false );
|
||||||
m_controls.last()->setShowMinusButton( true );
|
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() );
|
m_layout->addWidget( m_controls.last() );
|
||||||
connect( m_controls.last(), SIGNAL( addNewControl() ), this, SLOT( addNewControl() ) );
|
connect( m_controls.last(), SIGNAL( addNewControl() ), this, SLOT( addNewControl() ) );
|
||||||
connect( m_controls.last(), SIGNAL( removeControl() ), this, SLOT( removeControl() ) );
|
connect( m_controls.last(), SIGNAL( removeControl() ), this, SLOT( removeControl() ) );
|
||||||
|
connect( m_controls.last(), SIGNAL( changed() ), this, SLOT( controlChanged() ) );
|
||||||
|
|
||||||
|
emit controlsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DynamicControlList::removeControl()
|
void DynamicControlList::removeControl()
|
||||||
@@ -153,8 +161,18 @@ void DynamicControlList::removeControl()
|
|||||||
m_controls.last()->setShowCollapseButton( true );
|
m_controls.last()->setShowCollapseButton( true );
|
||||||
m_controls.last()->setShowPlusButton( true );
|
m_controls.last()->setShowPlusButton( true );
|
||||||
m_controls.last()->setShowMinusButton( false );
|
m_controls.last()->setShowMinusButton( false );
|
||||||
|
|
||||||
|
emit controlsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DynamicControlList::controlChanged()
|
||||||
|
{
|
||||||
|
Q_ASSERT( sender() && qobject_cast<DynamicControlWidget*>(sender()) );
|
||||||
|
|
||||||
|
emit controlChanged( qobject_cast<DynamicControlWidget*>(sender())->control() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DynamicControlList::paintEvent(QPaintEvent* )
|
void DynamicControlList::paintEvent(QPaintEvent* )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@@ -46,11 +46,16 @@ public:
|
|||||||
|
|
||||||
virtual void paintEvent(QPaintEvent* );
|
virtual void paintEvent(QPaintEvent* );
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void controlsChanged();
|
||||||
|
void controlChanged( const dyncontrol_ptr& control );
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
virtual void onHidden(QWidget* );
|
virtual void onHidden(QWidget* );
|
||||||
virtual void onShown(QWidget* );
|
virtual void onShown(QWidget* );
|
||||||
void addNewControl();
|
void addNewControl();
|
||||||
void removeControl();
|
void removeControl();
|
||||||
|
void controlChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init();
|
void init();
|
||||||
|
@@ -74,8 +74,8 @@ DynamicControlWidget::DynamicControlWidget( const Tomahawk::dyncontrol_ptr& cont
|
|||||||
m_collapseL->setCurrentIndex( 0 );
|
m_collapseL->setCurrentIndex( 0 );
|
||||||
|
|
||||||
connect( m_collapseButton, SIGNAL( clicked( bool ) ), this, SIGNAL( collapse() ) );
|
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 );
|
m_layout->addWidget( m_typeSelector, 0, Qt::AlignLeft );
|
||||||
|
|
||||||
@@ -149,6 +149,7 @@ DynamicControlWidget::typeSelectorChanged( QString type )
|
|||||||
m_control->inputField()->show();
|
m_control->inputField()->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@@ -55,6 +55,7 @@ signals:
|
|||||||
void addNewControl();
|
void addNewControl();
|
||||||
void collapse();
|
void collapse();
|
||||||
void removeControl();
|
void removeControl();
|
||||||
|
void changed();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void typeSelectorChanged( QString );
|
void typeSelectorChanged( QString );
|
||||||
|
@@ -83,6 +83,9 @@ DynamicWidget::DynamicWidget( const Tomahawk::dynplaylist_ptr& playlist, QWidget
|
|||||||
loadDynamicPlaylist( playlist );
|
loadDynamicPlaylist( playlist );
|
||||||
|
|
||||||
setLayout( m_layout );
|
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()
|
DynamicWidget::~DynamicWidget()
|
||||||
@@ -141,3 +144,15 @@ DynamicWidget::tracksGenerated( const QList< query_ptr >& queries )
|
|||||||
m_playlist->addEntries( queries, m_playlist->currentrevision() );
|
m_playlist->addEntries( queries, m_playlist->currentrevision() );
|
||||||
m_playlist->resolve();
|
m_playlist->resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DynamicWidget::controlsChanged()
|
||||||
|
{
|
||||||
|
// save the current playlist
|
||||||
|
m_playlist->createNewRevision();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicWidget::controlChanged(const Tomahawk::dyncontrol_ptr& control)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -18,8 +18,10 @@
|
|||||||
#define DYNAMIC_WIDGET_H
|
#define DYNAMIC_WIDGET_H
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <typedefs.h>
|
|
||||||
#include <dynamic/DynamicPlaylist.h>
|
#include "typedefs.h"
|
||||||
|
#include "dynamic/DynamicPlaylist.h"
|
||||||
|
#include "dynamic/DynamicControl.h"
|
||||||
|
|
||||||
class QVBoxLayout;
|
class QVBoxLayout;
|
||||||
class QHBoxLayout;
|
class QHBoxLayout;
|
||||||
@@ -57,6 +59,9 @@ private slots:
|
|||||||
void generate();
|
void generate();
|
||||||
void tracksGenerated( const QList< Tomahawk::query_ptr>& queries );
|
void tracksGenerated( const QList< Tomahawk::query_ptr>& queries );
|
||||||
|
|
||||||
|
void controlsChanged();
|
||||||
|
void controlChanged( const dyncontrol_ptr& control );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
dynplaylist_ptr m_playlist;
|
dynplaylist_ptr m_playlist;
|
||||||
QVBoxLayout* m_layout;
|
QVBoxLayout* m_layout;
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
#include "tomahawksqlquery.h"
|
#include "tomahawksqlquery.h"
|
||||||
#include "dynamic/DynamicControl.h"
|
#include "dynamic/DynamicControl.h"
|
||||||
#include "dynamic/GeneratorInterface.h"
|
#include "dynamic/GeneratorInterface.h"
|
||||||
|
#include <dynamic/GeneratorFactory.h>
|
||||||
|
|
||||||
using namespace Tomahawk;
|
using namespace Tomahawk;
|
||||||
|
|
||||||
@@ -27,12 +28,29 @@ DatabaseCommand_LoadDynamicPlaylist::exec( DatabaseImpl* dbi )
|
|||||||
controlsQuery.addBindValue( revisionGuid() );
|
controlsQuery.addBindValue( revisionGuid() );
|
||||||
controlsQuery.exec();
|
controlsQuery.exec();
|
||||||
|
|
||||||
QList< dyncontrol_ptr > controls;
|
QString type;
|
||||||
|
GeneratorMode mode;
|
||||||
|
|
||||||
|
QList< QVariantMap > controls;
|
||||||
QString playlist_guid;
|
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();
|
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<GeneratorMode>( controlsQuery.value( 2 ).toInt() );
|
||||||
|
|
||||||
|
QStringList controlIds = v.toStringList();
|
||||||
|
qDebug() << "Got controls in dynamic playlist, loading:" << controlIds << controlsQuery.value(1);
|
||||||
foreach( const QString& controlId, controlIds )
|
foreach( const QString& controlId, controlIds )
|
||||||
{
|
{
|
||||||
TomahawkSqlQuery controlQuery = dbi->newquery();
|
TomahawkSqlQuery controlQuery = dbi->newquery();
|
||||||
@@ -43,16 +61,17 @@ DatabaseCommand_LoadDynamicPlaylist::exec( DatabaseImpl* dbi )
|
|||||||
controlQuery.exec();
|
controlQuery.exec();
|
||||||
if( controlQuery.next() )
|
if( controlQuery.next() )
|
||||||
{
|
{
|
||||||
dyncontrol_ptr c = dyncontrol_ptr( new DynamicControl );
|
QVariantMap c;
|
||||||
c->setId( controlId );
|
c[ "type" ] = type;
|
||||||
c->setSelectedType( controlQuery.value( 0 ).toString() );
|
c[ "id" ] = controlId;
|
||||||
c->setMatch( controlQuery.value( 1 ).toString() );
|
c[ "selectedType" ] = controlQuery.value( 0 ).toString();
|
||||||
c->setInput( controlQuery.value( 2 ).toString() );
|
c["match" ] = controlQuery.value( 1 ).toString();
|
||||||
|
c[ "input" ] = controlQuery.value( 2 ).toString();
|
||||||
controls << c;
|
controls << c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
// No controls, lets load the info we need directly from the playlist table
|
||||||
TomahawkSqlQuery info = dbi->newquery();
|
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 ) );
|
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() ) {
|
if( !info.exec() ) {
|
||||||
@@ -62,8 +81,10 @@ DatabaseCommand_LoadDynamicPlaylist::exec( DatabaseImpl* dbi )
|
|||||||
qWarning() << "Noo results for queryL:" << info.lastQuery();
|
qWarning() << "Noo results for queryL:" << info.lastQuery();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QString type = info.value( 0 ).toString();
|
type = info.value( 0 ).toString();
|
||||||
GeneratorMode mode = static_cast<GeneratorMode>( info.value( 1 ).toInt() );
|
mode = static_cast<GeneratorMode>( info.value( 1 ).toInt() );
|
||||||
|
}
|
||||||
|
|
||||||
if( mode == OnDemand ) {
|
if( mode == OnDemand ) {
|
||||||
Q_ASSERT( m_entrymap.isEmpty() ); // ondemand should have no entry
|
Q_ASSERT( m_entrymap.isEmpty() ); // ondemand should have no entry
|
||||||
|
|
||||||
|
@@ -29,14 +29,14 @@ signals:
|
|||||||
void done( QString,
|
void done( QString,
|
||||||
bool,
|
bool,
|
||||||
QString,
|
QString,
|
||||||
QList< Tomahawk::dyncontrol_ptr>,
|
QList< QVariantMap>,
|
||||||
bool );
|
bool );
|
||||||
// used when loading a static playlist
|
// used when loading a static playlist
|
||||||
void done( QString,
|
void done( QString,
|
||||||
QList< QString >,
|
QList< QString >,
|
||||||
QList< QString >,
|
QList< QString >,
|
||||||
QString,
|
QString,
|
||||||
QList< Tomahawk::dyncontrol_ptr>,
|
QList< QVariantMap>,
|
||||||
bool,
|
bool,
|
||||||
QMap< QString, Tomahawk::plentry_ptr >,
|
QMap< QString, Tomahawk::plentry_ptr >,
|
||||||
bool );
|
bool );
|
||||||
|
@@ -74,15 +74,6 @@ DatabaseCommand_SetDynamicPlaylistRevision::postCommitHook()
|
|||||||
return;
|
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 )
|
if( m_mode == OnDemand )
|
||||||
playlist->setRevision( newrev(),
|
playlist->setRevision( newrev(),
|
||||||
true, // this *is* the newest revision so far
|
true, // this *is* the newest revision so far
|
||||||
@@ -140,6 +131,7 @@ DatabaseCommand_SetDynamicPlaylistRevision::exec( DatabaseImpl* lib )
|
|||||||
"VALUES( ?, ?, ?, ?, ? )" );
|
"VALUES( ?, ?, ?, ?, ? )" );
|
||||||
foreach( const dyncontrol_ptr& control, m_controls )
|
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( control->id() );
|
||||||
controlsQuery.addBindValue( m_playlistguid );
|
controlsQuery.addBindValue( m_playlistguid );
|
||||||
controlsQuery.addBindValue( control->selectedType() );
|
controlsQuery.addBindValue( control->selectedType() );
|
||||||
|
@@ -167,7 +167,7 @@ DatabaseWorker::logOp( DatabaseCommandLoggable* command )
|
|||||||
QVariantMap variant = QJson::QObjectHelper::qobject2qvariant( command );
|
QVariantMap variant = QJson::QObjectHelper::qobject2qvariant( command );
|
||||||
QByteArray ba = m_serializer.serialize( variant );
|
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;
|
bool compressed = false;
|
||||||
if( ba.length() >= 512 )
|
if( ba.length() >= 512 )
|
||||||
|
@@ -39,6 +39,7 @@ namespace Tomahawk
|
|||||||
class DynamicControl : public QObject
|
class DynamicControl : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
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 id READ id WRITE setId )
|
||||||
Q_PROPERTY( QString selectedType READ selectedType WRITE setSelectedType )
|
Q_PROPERTY( QString selectedType READ selectedType WRITE setSelectedType )
|
||||||
Q_PROPERTY( QString match READ match WRITE setMatch )
|
Q_PROPERTY( QString match READ match WRITE setMatch )
|
||||||
@@ -83,6 +84,12 @@ public:
|
|||||||
};
|
};
|
||||||
void setId( const QString& id ) { m_id = id; }
|
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:
|
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
|
||||||
@@ -98,6 +105,7 @@ protected:
|
|||||||
QString m_input;
|
QString m_input;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QString m_type;
|
||||||
QString m_selectedType;
|
QString m_selectedType;
|
||||||
QStringList m_typeSelectors;
|
QStringList m_typeSelectors;
|
||||||
QString m_id;
|
QString m_id;
|
||||||
|
@@ -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
|
// create a new revision that will be a static playlist, as it has entries
|
||||||
void
|
void
|
||||||
DynamicPlaylist::createNewRevision( const QString& newrev,
|
DynamicPlaylist::createNewRevision( const QString& newrev,
|
||||||
@@ -190,19 +203,19 @@ DynamicPlaylist::loadRevision( const QString& rev )
|
|||||||
connect( cmd, SIGNAL( done( QString,
|
connect( cmd, SIGNAL( done( QString,
|
||||||
bool,
|
bool,
|
||||||
QString,
|
QString,
|
||||||
QList< Tomahawk::dyncontrol_ptr>,
|
QList< QVariantMap >,
|
||||||
bool ) ),
|
bool ) ),
|
||||||
SLOT( setRevision( QString,
|
SLOT( setRevision( QString,
|
||||||
bool,
|
bool,
|
||||||
QString,
|
QString,
|
||||||
QList< Tomahawk::dyncontrol_ptr>,
|
QList< QVariantMap >,
|
||||||
bool) ) );
|
bool) ) );
|
||||||
} else if( m_generator->mode() == Static ) {
|
} else if( m_generator->mode() == Static ) {
|
||||||
connect( cmd, SIGNAL( done( QString,
|
connect( cmd, SIGNAL( done( QString,
|
||||||
QList< QString >,
|
QList< QString >,
|
||||||
QList< QString >,
|
QList< QString >,
|
||||||
QString,
|
QString,
|
||||||
QList< Tomahawk::dyncontrol_ptr>,
|
QList< QVariantMap >,
|
||||||
bool,
|
bool,
|
||||||
QMap< QString, Tomahawk::plentry_ptr >,
|
QMap< QString, Tomahawk::plentry_ptr >,
|
||||||
bool ) ),
|
bool ) ),
|
||||||
@@ -210,7 +223,7 @@ DynamicPlaylist::loadRevision( const QString& rev )
|
|||||||
QList< QString >,
|
QList< QString >,
|
||||||
QList< QString >,
|
QList< QString >,
|
||||||
QString,
|
QString,
|
||||||
QList< Tomahawk::dyncontrol_ptr>,
|
QList< QVariantMap >,
|
||||||
bool,
|
bool,
|
||||||
QMap< QString, Tomahawk::plentry_ptr >,
|
QMap< QString, Tomahawk::plentry_ptr >,
|
||||||
bool ) ) );
|
bool ) ) );
|
||||||
@@ -264,16 +277,14 @@ void DynamicPlaylist::addEntry(const Tomahawk::query_ptr& query, const QString&
|
|||||||
addEntries( queries, oldrev );
|
addEntries( queries, oldrev );
|
||||||
}
|
}
|
||||||
|
|
||||||
// static version
|
void DynamicPlaylist::setRevision( const QString& rev,
|
||||||
void
|
|
||||||
DynamicPlaylist::setRevision( const QString& rev,
|
|
||||||
const QList< QString >& neworderedguids,
|
const QList< QString >& neworderedguids,
|
||||||
const QList< QString >& oldorderedguids,
|
const QList< QString >& oldorderedguids,
|
||||||
const QString& type,
|
const QString& type,
|
||||||
const QList< Tomahawk::dyncontrol_ptr>& controls,
|
const QList< dyncontrol_ptr >& controls,
|
||||||
bool is_newest_rev,
|
bool is_newest_rev,
|
||||||
const QMap< QString, Tomahawk::plentry_ptr >& addedmap,
|
const QMap< QString, plentry_ptr >& addedmap,
|
||||||
bool applied )
|
bool applied)
|
||||||
{
|
{
|
||||||
// we're probably being called by a database worker thread
|
// we're probably being called by a database worker thread
|
||||||
if( QThread::currentThread() != thread() )
|
if( QThread::currentThread() != thread() )
|
||||||
@@ -307,16 +318,45 @@ DynamicPlaylist::setRevision( const QString& rev,
|
|||||||
if( applied )
|
if( applied )
|
||||||
setCurrentrevision( rev );
|
setCurrentrevision( rev );
|
||||||
|
|
||||||
// qDebug() << "EMITTING REVISION LOADED 1!";
|
// qDebug() << "EMITTING REVISION LOADED 1!";
|
||||||
emit dynamicRevisionLoaded( dpr );
|
emit dynamicRevisionLoaded( dpr );
|
||||||
}
|
}
|
||||||
|
|
||||||
// ondemand version
|
|
||||||
void
|
void
|
||||||
DynamicPlaylist::setRevision( const QString& rev,
|
DynamicPlaylist::setRevision( const QString& rev,
|
||||||
|
const QList< QString >& neworderedguids,
|
||||||
|
const QList< QString >& oldorderedguids,
|
||||||
|
const QString& type,
|
||||||
|
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<QString> , neworderedguids ),
|
||||||
|
Q_ARG( QList<QString> , 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<dyncontrol_ptr> controls = variantsToControl( controlsV );
|
||||||
|
setRevision( rev, neworderedguids, oldorderedguids, type, controls, is_newest_rev, addedmap, applied );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicPlaylist::setRevision( const QString& rev,
|
||||||
bool is_newest_rev,
|
bool is_newest_rev,
|
||||||
const QString& type,
|
const QString& type,
|
||||||
const QList< Tomahawk::dyncontrol_ptr>& controls,
|
const QList< dyncontrol_ptr >& controls,
|
||||||
bool applied )
|
bool applied )
|
||||||
{
|
{
|
||||||
if( QThread::currentThread() != thread() )
|
if( QThread::currentThread() != thread() )
|
||||||
@@ -345,7 +385,43 @@ DynamicPlaylist::setRevision( const QString& rev,
|
|||||||
dpr.type = type;
|
dpr.type = type;
|
||||||
dpr.mode = OnDemand;
|
dpr.mode = OnDemand;
|
||||||
|
|
||||||
// qDebug() << "EMITTING REVISION LOADED 2!";
|
// qDebug() << "EMITTING REVISION LOADED 2!";
|
||||||
emit dynamicRevisionLoaded( dpr );
|
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<dyncontrol_ptr> controls = variantsToControl( controlsV );
|
||||||
|
setRevision( rev, is_newest_rev, type, controls, applied );
|
||||||
|
}
|
||||||
|
|
||||||
|
QList< dyncontrol_ptr > DynamicPlaylist::variantsToControl( const QList< QVariantMap >& controlsV )
|
||||||
|
{
|
||||||
|
QList<dyncontrol_ptr> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -87,6 +87,10 @@ public:
|
|||||||
QString type() const;
|
QString type() const;
|
||||||
geninterface_ptr generator() 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 addEntries( const QList< query_ptr >& queries, const QString& oldrev );
|
||||||
virtual void addEntry( const Tomahawk::query_ptr& query, 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 );
|
void reportDeleted( const Tomahawk::dynplaylist_ptr& self );
|
||||||
|
|
||||||
// called from setdynamicplaylistrevision db cmd
|
// 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,
|
void setRevision( const QString& rev,
|
||||||
const QList<QString>& neworderedguids,
|
const QList<QString>& neworderedguids,
|
||||||
const QList<QString>& oldorderedguids,
|
const QList<QString>& oldorderedguids,
|
||||||
const QString& type,
|
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<QString>& neworderedguids,
|
||||||
|
const QList<QString>& oldorderedguids,
|
||||||
|
const QString& type,
|
||||||
|
const QList< dyncontrol_ptr >& controls,
|
||||||
bool is_newest_rev,
|
bool is_newest_rev,
|
||||||
const QMap< QString, Tomahawk::plentry_ptr >& addedmap,
|
const QMap< QString, Tomahawk::plentry_ptr >& addedmap,
|
||||||
bool applied );
|
bool applied );
|
||||||
|
|
||||||
// ondemand version
|
// ondemand version
|
||||||
void setRevision( const QString& rev,
|
void setRevision( const QString& rev,
|
||||||
bool is_newest_rev,
|
bool is_newest_rev,
|
||||||
const QString& type,
|
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 );
|
bool applied );
|
||||||
private:
|
private:
|
||||||
// called from loadAllPlaylists DB cmd:
|
// called from loadAllPlaylists DB cmd:
|
||||||
@@ -155,6 +175,7 @@ private:
|
|||||||
bool shared );
|
bool shared );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QList< dyncontrol_ptr > variantsToControl( const QList< QVariantMap >& controlsV );
|
||||||
geninterface_ptr m_generator;
|
geninterface_ptr m_generator;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -5,7 +5,8 @@ using namespace Tomahawk;
|
|||||||
|
|
||||||
QHash< QString, GeneratorFactoryInterface* > GeneratorFactory::s_factories = QHash< QString, GeneratorFactoryInterface* >();
|
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
|
if( type.isEmpty() && !s_factories.isEmpty() ) // default, return first
|
||||||
return geninterface_ptr( s_factories.begin().value()->create() );
|
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() );
|
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 );
|
s_factories.insert( type, interface );
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList GeneratorFactory::types()
|
QStringList
|
||||||
|
GeneratorFactory::types()
|
||||||
{
|
{
|
||||||
return s_factories.keys();
|
return s_factories.keys();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList
|
||||||
|
GeneratorFactory::typeSelectors(const QString& type)
|
||||||
|
{
|
||||||
|
if( !s_factories.contains( type ) )
|
||||||
|
return QStringList();
|
||||||
|
|
||||||
|
return s_factories.value( type )->typeSelectors();
|
||||||
|
}
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#include "dynamic/GeneratorInterface.h"
|
#include "dynamic/GeneratorInterface.h"
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
namespace Tomahawk {
|
namespace Tomahawk {
|
||||||
|
|
||||||
@@ -17,6 +18,13 @@ public:
|
|||||||
GeneratorFactoryInterface() {}
|
GeneratorFactoryInterface() {}
|
||||||
|
|
||||||
virtual GeneratorInterface* create() = 0;
|
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:
|
public:
|
||||||
static geninterface_ptr create( const QString& type );
|
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 void registerFactory( const QString& type, GeneratorFactoryInterface* interface );
|
||||||
static QStringList types();
|
static QStringList types();
|
||||||
|
static QStringList typeSelectors( const QString& type );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static QHash<QString, GeneratorFactoryInterface*> s_factories;
|
static QHash<QString, GeneratorFactoryInterface*> s_factories;
|
||||||
|
@@ -60,8 +60,9 @@ Tomahawk::GeneratorInterface::setControls( const QList< Tomahawk::dyncontrol_ptr
|
|||||||
m_controls = controls;
|
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();
|
return dyncontrol_ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -76,8 +76,6 @@ public:
|
|||||||
void clearControls();
|
void clearControls();
|
||||||
void setControls( const QList< dyncontrol_ptr>& controls );
|
void setControls( const QList< dyncontrol_ptr>& controls );
|
||||||
|
|
||||||
QStringList typeSelectors() const { return m_typeSelectors; }
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void generated( const QList< Tomahawk::query_ptr>& queries );
|
void generated( const QList< Tomahawk::query_ptr>& queries );
|
||||||
|
|
||||||
@@ -85,7 +83,6 @@ protected:
|
|||||||
QString m_type;
|
QString m_type;
|
||||||
GeneratorMode m_mode;
|
GeneratorMode m_mode;
|
||||||
QList< dyncontrol_ptr > m_controls;
|
QList< dyncontrol_ptr > m_controls;
|
||||||
QStringList m_typeSelectors;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef QSharedPointer<GeneratorInterface> geninterface_ptr;
|
typedef QSharedPointer<GeneratorInterface> geninterface_ptr;
|
||||||
|
@@ -22,9 +22,10 @@
|
|||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
|
|
||||||
|
|
||||||
Tomahawk::EchonestControl::EchonestControl( const QString& type, const QStringList& typeSelectors, QObject* parent )
|
Tomahawk::EchonestControl::EchonestControl( const QString& selectedType, const QStringList& typeSelectors, QObject* parent )
|
||||||
: DynamicControl ( type.isEmpty() ? "Artist" : type, typeSelectors, parent )
|
: DynamicControl ( selectedType.isEmpty() ? "Artist" : selectedType, typeSelectors, parent )
|
||||||
{
|
{
|
||||||
|
setType( "echonest" );
|
||||||
updateWidgets();
|
updateWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +81,9 @@ Tomahawk::EchonestControl::updateWidgets()
|
|||||||
input->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Fixed );
|
input->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Fixed );
|
||||||
|
|
||||||
connect( match, SIGNAL( currentIndexChanged(int) ), this, SLOT( updateData() ) );
|
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( textChanged(QString) ), this, SLOT( updateData() ) );
|
||||||
|
connect( input, SIGNAL( editingFinished() ), this, SIGNAL( changed() ) );
|
||||||
|
|
||||||
match->hide();
|
match->hide();
|
||||||
input->hide();
|
input->hide();
|
||||||
|
@@ -34,15 +34,15 @@ public:
|
|||||||
/// Converts this to an echonest suitable parameter
|
/// Converts this to an echonest suitable parameter
|
||||||
Echonest::DynamicPlaylist::PlaylistParamData toENParam() const;
|
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:
|
public slots:
|
||||||
virtual void setSelectedType ( const QString& type );
|
virtual void setSelectedType ( const QString& type );
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void updateData();
|
void updateData();
|
||||||
|
|
||||||
protected:
|
|
||||||
explicit EchonestControl( const QString& type, const QStringList& typeSelectors, QObject* parent = 0 );
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateWidgets();
|
void updateWidgets();
|
||||||
|
|
||||||
|
@@ -30,12 +30,24 @@ EchonestFactory::create()
|
|||||||
return new EchonestGenerator();
|
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 )
|
EchonestGenerator::EchonestGenerator ( QObject* parent )
|
||||||
: GeneratorInterface ( 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_type = "echonest";
|
||||||
m_mode = OnDemand;
|
m_mode = OnDemand;
|
||||||
|
|
||||||
@@ -49,7 +61,7 @@ EchonestGenerator::~EchonestGenerator()
|
|||||||
dyncontrol_ptr
|
dyncontrol_ptr
|
||||||
EchonestGenerator::createControl( const QString& type )
|
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();
|
return m_controls.last();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -32,7 +32,8 @@ public:
|
|||||||
EchonestFactory();
|
EchonestFactory();
|
||||||
|
|
||||||
virtual GeneratorInterface* create();
|
virtual GeneratorInterface* create();
|
||||||
|
virtual dyncontrol_ptr createControl( const QString& controlType = QString() );
|
||||||
|
virtual QStringList typeSelectors() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EchonestGenerator : public GeneratorInterface
|
class EchonestGenerator : public GeneratorInterface
|
||||||
|
Reference in New Issue
Block a user