mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-04-13 04:21:51 +02:00
Fix merge and compile, fix schema issue
This commit is contained in:
parent
c28a7b8aa4
commit
2172f68a66
@ -0,0 +1,56 @@
|
||||
/****************************************************************************************
|
||||
* 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 "databasecommand_deletedynamicplaylist.h"
|
||||
|
||||
#include <QSqlQuery>
|
||||
#include "network/servent.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
DatabaseCommand_DeleteDynamicPlaylist::DatabaseCommand_DeleteDynamicPlaylist( const source_ptr& source, const QString& playlistguid )
|
||||
: DatabaseCommand_DeletePlaylist( source, playlistguid )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DatabaseCommand_DeleteDynamicPlaylist::exec( DatabaseImpl* lib )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
DatabaseCommand_DeletePlaylist::exec( lib );
|
||||
TomahawkSqlQuery cre = lib->newquery();
|
||||
|
||||
cre.prepare( "DELETE FROM dynamic_playlist WHERE guid = :id" );
|
||||
cre.bindValue( ":id", m_playlistguid );
|
||||
|
||||
cre.exec();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DatabaseCommand_DeleteDynamicPlaylist::postCommitHook()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "..reporting..";
|
||||
|
||||
dynplaylist_ptr playlist = source()->collection()->dynamicPlaylist( m_playlistguid );
|
||||
Q_ASSERT( !playlist.isNull() );
|
||||
|
||||
playlist->reportDeleted( playlist );
|
||||
|
||||
if( source()->isLocal() )
|
||||
Servent::instance()->triggerDBSync();
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/****************************************************************************************
|
||||
* 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/>. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef DATABASECOMMAND_DELETEDYNAMICPLAYLIST_H
|
||||
#define DATABASECOMMAND_DELETEDYNAMICPLAYLIST_H
|
||||
|
||||
#include "databaseimpl.h"
|
||||
#include "databasecommand_deleteplaylist.h"
|
||||
#include "source.h"
|
||||
#include "typedefs.h"
|
||||
|
||||
class DatabaseCommand_DeleteDynamicPlaylist : public DatabaseCommand_DeletePlaylist
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DatabaseCommand_DeleteDynamicPlaylist( QObject* parent = 0 )
|
||||
: DatabaseCommand_DeletePlaylist( parent )
|
||||
{}
|
||||
|
||||
explicit DatabaseCommand_DeleteDynamicPlaylist( const Tomahawk::source_ptr& source, const QString& playlistguid );
|
||||
|
||||
QString commandname() const { return "deletedynamicplaylist"; }
|
||||
|
||||
virtual void exec( DatabaseImpl* lib );
|
||||
virtual void postCommitHook();
|
||||
virtual bool doesMutates() const { return true; }
|
||||
|
||||
private:
|
||||
QString m_playlistguid;
|
||||
};
|
||||
|
||||
#endif // DATABASECOMMAND_DELETEDYNAMICPLAYLIST_H
|
@ -0,0 +1,56 @@
|
||||
/****************************************************************************************
|
||||
* 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 "databasecommand_loadalldynamicplaylists.h"
|
||||
|
||||
#include <QSqlQuery>
|
||||
|
||||
#include "dynamic/DynamicPlaylist.h"
|
||||
#include "databaseimpl.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
void DatabaseCommand_LoadAllDynamicPlaylists::exec( DatabaseImpl* dbi )
|
||||
{
|
||||
TomahawkSqlQuery query = dbi->newquery();
|
||||
|
||||
query.exec( QString( "SELECT playlist.guid as guid, title, info, creator, lastmodified, shared, currentrevision, dynamic_playlist.pltype, dynamic_playlist.plmode "
|
||||
"FROM playlist, dynamic_playlist WHERE source %1 AND dynplaylist AND playlist.guid = dynamic_playlist.guid" )
|
||||
.arg( source()->isLocal() ? "IS NULL" :
|
||||
QString( "=%1" ).arg( source()->id() )
|
||||
) );
|
||||
|
||||
QList<dynplaylist_ptr> plists;
|
||||
while ( query.next() )
|
||||
{
|
||||
dynplaylist_ptr p( new DynamicPlaylist( source(), //src
|
||||
query.value(6).toString(), //current rev
|
||||
query.value(1).toString(), //title
|
||||
query.value(2).toString(), //info
|
||||
query.value(3).toString(), //creator
|
||||
query.value(7).toString(), // dynamic type
|
||||
static_cast<GeneratorMode>(query.value(8).toInt()), // dynamic mode
|
||||
query.value(5).toBool(), //shared
|
||||
query.value(4).toInt(), //lastmod
|
||||
query.value(0).toString() //GUID
|
||||
|
||||
) );
|
||||
plists.append( p );
|
||||
}
|
||||
|
||||
emit done( plists );
|
||||
}
|
||||
|
@ -0,0 +1,42 @@
|
||||
/****************************************************************************************
|
||||
* 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/>. *
|
||||
****************************************************************************************/
|
||||
#ifndef DATABASECOMMAND_LOADALLDYNAMICPLAYLISTS_H
|
||||
#define DATABASECOMMAND_LOADALLDYNAMICPLAYLISTS_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariantMap>
|
||||
|
||||
#include "databasecommand.h"
|
||||
#include "typedefs.h"
|
||||
|
||||
class DatabaseCommand_LoadAllDynamicPlaylists : public DatabaseCommand
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DatabaseCommand_LoadAllDynamicPlaylists( const Tomahawk::source_ptr& s, QObject* parent = 0 )
|
||||
: DatabaseCommand( s, parent )
|
||||
{}
|
||||
|
||||
virtual void exec( DatabaseImpl* );
|
||||
virtual bool doesMutates() const { return false; }
|
||||
virtual QString commandname() const { return "loadalldynamicplaylists"; }
|
||||
|
||||
signals:
|
||||
void done( const QList<Tomahawk::dynplaylist_ptr>& playlists );
|
||||
};
|
||||
|
||||
#endif // DATABASECOMMAND_ADDFILES_H
|
@ -0,0 +1,74 @@
|
||||
#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 playlist_revision.playlist, controls, plmode, pltype "
|
||||
"FROM dynamic_playlist_revision, playlist_revision "
|
||||
"WHERE dynamic_playlist_revision.guid = ? AND playlist_revision.guid = dynamic_playlist_revision.guid");
|
||||
controlsQuery.addBindValue( revisionGuid() );
|
||||
controlsQuery.exec();
|
||||
|
||||
QList< dyncontrol_ptr > controls;
|
||||
QString playlist_guid;
|
||||
if( controlsQuery.next() )
|
||||
{
|
||||
playlist_guid = controlsQuery.value( 0 ).toString();
|
||||
QStringList controlIds = controlsQuery.value( 1 ).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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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<GeneratorMode>( info.value( 1 ).toInt() );
|
||||
if( mode == OnDemand ) {
|
||||
Q_ASSERT( m_entrymap.isEmpty() ); // ondemand should have no entry
|
||||
|
||||
emit done( revisionGuid(), m_islatest, type, controls, true );
|
||||
} else {
|
||||
emit done( revisionGuid(), m_guids, m_oldentries, type, controls, m_islatest, m_entrymap, true );
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
#ifndef DATABASECOMMAND_LOADDYNAMICPLAYLIST_H
|
||||
#define DATABASECOMMAND_LOADDYNAMICPLAYLIST_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariantMap>
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "databasecommand.h"
|
||||
#include "databasecommand_loadplaylistentries.h"
|
||||
#include "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 )
|
||||
{ qDebug() << "loaded with:" << revision_guid << guid(); }
|
||||
|
||||
|
||||
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,
|
||||
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,
|
||||
QMap< QString, Tomahawk::plentry_ptr >,
|
||||
bool );
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // DATABASECOMMAND_LOADDYNAMICPLAYLIST_H
|
@ -0,0 +1,152 @@
|
||||
#include "databasecommand_setdynamicplaylistrevision.h"
|
||||
|
||||
#include <QSqlQuery>
|
||||
|
||||
#include "tomahawksqlquery.h"
|
||||
#include "dynamic/DynamicPlaylist.h"
|
||||
#include "dynamic/DynamicControl.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() )
|
||||
Servent::instance()->triggerDBSync();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DatabaseCommand_SetDynamicPlaylistRevision::exec( DatabaseImpl* lib )
|
||||
{
|
||||
DatabaseCommand_SetPlaylistRevision::exec( lib );
|
||||
|
||||
QVariantList newcontrols;
|
||||
foreach( const dyncontrol_ptr& control, m_controls ) {
|
||||
newcontrols << control->id();
|
||||
}
|
||||
QJson::Serializer ser;
|
||||
const QByteArray newcontrols_data = ser.serialize( newcontrols );
|
||||
|
||||
TomahawkSqlQuery query = lib->newquery();
|
||||
QString sql = "INSERT INTO dynamic_playlist_revision (guid, controls, plmode, pltype) "
|
||||
"VALUES(?, ?, ?, ?)";
|
||||
|
||||
query.prepare( sql );
|
||||
query.addBindValue( m_newrev );
|
||||
query.addBindValue( newcontrols_data );
|
||||
query.addBindValue( QString::number( (int) m_mode ) );
|
||||
query.addBindValue( m_type );
|
||||
query.exec();
|
||||
|
||||
// delete all the old controls, replace with new onws
|
||||
qDebug() << "Deleting controls with playlist id" << m_currentRevision;
|
||||
TomahawkSqlQuery delQuery = lib->newquery();
|
||||
delQuery.prepare( "DELETE FROM dynamic_playlist_controls WHERE playlist = ?" );
|
||||
delQuery.addBindValue( m_currentRevision );
|
||||
if( !delQuery.exec() )
|
||||
qWarning() << "Failed to delete controls from dynamic playlist controls table";
|
||||
|
||||
TomahawkSqlQuery controlsQuery = lib->newquery();
|
||||
controlsQuery.prepare( "INSERT INTO dynamic_playlist_controls( id, playlist, selectedType, match, input ) "
|
||||
"VALUES( ?, ?, ?, ?, ? )" );
|
||||
foreach( const dyncontrol_ptr& control, m_controls )
|
||||
{
|
||||
controlsQuery.addBindValue( control->id() );
|
||||
controlsQuery.addBindValue( m_playlistguid );
|
||||
controlsQuery.addBindValue( control->selectedType() );
|
||||
controlsQuery.addBindValue( control->match() );
|
||||
controlsQuery.addBindValue( control->input() );
|
||||
|
||||
controlsQuery.exec();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
#ifndef DATABASECOMMAND_SETDYNAMICPLAYLISTREVISION_H
|
||||
#define DATABASECOMMAND_SETDYNAMICPLAYLISTREVISION_H
|
||||
|
||||
#include "databasecommand_setplaylistrevision.h"
|
||||
#include "databaseimpl.h"
|
||||
#include "collection.h"
|
||||
#include "playlist.h"
|
||||
#include "dynamic/GeneratorInterface.h"
|
||||
#include "network/servent.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
class DatabaseCommand_SetDynamicPlaylistRevision : public DatabaseCommand_SetPlaylistRevision
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY( QString type READ type WRITE setType )
|
||||
Q_PROPERTY( int 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; }
|
||||
int mode() const { return (int)m_mode; }
|
||||
|
||||
void setType( const QString& type ) { m_type = type; }
|
||||
// void setMode( GeneratorMode mode ) { m_mode = mode; }
|
||||
void setMode( int mode ) { m_mode = (GeneratorMode)mode; }
|
||||
|
||||
private:
|
||||
QString m_type;
|
||||
GeneratorMode m_mode;
|
||||
QList< dyncontrol_ptr > m_controls;
|
||||
QList< QVariant > m_controlsV;
|
||||
};
|
||||
|
||||
#endif // DATABASECOMMAND_SETDYNAMICPLAYLISTREVISION_H
|
@ -15,7 +15,7 @@
|
||||
*/
|
||||
#include "schema.sql.h"
|
||||
|
||||
#define CURRENT_SCHEMA_VERSION 14
|
||||
#define CURRENT_SCHEMA_VERSION 15
|
||||
|
||||
|
||||
DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent )
|
||||
|
@ -160,10 +160,6 @@ DatabaseWorker::logOp( DatabaseCommandLoggable* command )
|
||||
"VALUES(?, ?, ?, ?, ?) ");
|
||||
|
||||
QVariantMap variant = QJson::QObjectHelper::qobject2qvariant( command );
|
||||
qDebug() << "trying to serialize:" << variant.keys();
|
||||
foreach( const QString& key, variant.keys() ) {
|
||||
qDebug() << key << ":" << variant.value( key );
|
||||
}
|
||||
QByteArray ba = m_serializer.serialize( variant );
|
||||
|
||||
// qDebug() << "OP JSON:" << ba.isNull() << ba << "from:" << variant; // debug
|
||||
|
@ -133,8 +133,8 @@ INSERT INTO dynamic_playlist_controls(id, playlist, selectedType, match, input)
|
||||
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
|
||||
plmode INTEGER,
|
||||
pltype TEXT
|
||||
);
|
||||
|
||||
INSERT INTO dynamic_playlist_revision(guid, controls, plmode, pltype)
|
||||
@ -257,4 +257,4 @@ CREATE TABLE IF NOT EXISTS settings (
|
||||
k TEXT NOT NULL PRIMARY KEY,
|
||||
v TEXT NOT NULL DEFAULT ''
|
||||
);
|
||||
INSERT INTO settings(k,v) VALUES('schema_version', '14');
|
||||
INSERT INTO settings(k,v) VALUES('schema_version', '15');
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
This file was automatically generated from schema.sql on Sun Dec 12 21:41:41 EST 2010.
|
||||
This file was automatically generated from schema.sql on Mon Jan 3 23:24:18 CST 2011.
|
||||
*/
|
||||
|
||||
static const char * tomahawk_schema_sql =
|
||||
@ -103,8 +103,8 @@ static const char * tomahawk_schema_sql =
|
||||
"CREATE TABLE IF NOT EXISTS dynamic_playlist_revision ("
|
||||
" guid TEXT PRIMARY KEY,"
|
||||
" controls TEXT, "
|
||||
" 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"
|
||||
" plmode INTEGER,"
|
||||
" pltype TEXT"
|
||||
");"
|
||||
"INSERT INTO dynamic_playlist_revision(guid, controls, plmode, pltype)"
|
||||
" VALUES('revisionguid-1', '[\"controlid-1\"]', 0, \"echonest\");"
|
||||
@ -190,7 +190,7 @@ static const char * tomahawk_schema_sql =
|
||||
" k TEXT NOT NULL PRIMARY KEY,"
|
||||
" v TEXT NOT NULL DEFAULT ''"
|
||||
");"
|
||||
"INSERT INTO settings(k,v) VALUES('schema_version', '14');"
|
||||
"INSERT INTO settings(k,v) VALUES('schema_version', '15');"
|
||||
;
|
||||
|
||||
const char * get_tomahawk_sql()
|
||||
|
36
src/libtomahawk/dynamic/DynamicControl.cpp
Normal file
36
src/libtomahawk/dynamic/DynamicControl.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
/****************************************************************************************
|
||||
* 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( const QStringList& typeSelectors )
|
||||
: m_typeSelectors( typeSelectors )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Tomahawk::DynamicControl::~DynamicControl()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Tomahawk::DynamicControl::DynamicControl(const QString& selectedType, const QStringList& typeSelectors, QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_selectedType( selectedType )
|
||||
, m_typeSelectors( typeSelectors )
|
||||
{
|
||||
|
||||
}
|
108
src/libtomahawk/dynamic/DynamicControl.h
Normal file
108
src/libtomahawk/dynamic/DynamicControl.h
Normal file
@ -0,0 +1,108 @@
|
||||
/****************************************************************************************
|
||||
* 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/>. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef DYNAMIC_PLAYLIST_CONTROL
|
||||
#define DYNAMIC_PLAYLIST_CONTROL
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QStringList>
|
||||
#include <QtGui/QWidget>
|
||||
#include "typedefs.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
/**
|
||||
* A Dynamic Control is a single constraint that limits a dynamic playlist. Each generator creates controls specific to that generator.
|
||||
* Each control has 3 pieces:
|
||||
* - Type (string selector for what this control is matching)
|
||||
* - Match selector (how to match the type to the input)
|
||||
* - Input field (the user input field).
|
||||
*
|
||||
* Each control also has a list of TypeSelectors that comes from the generator, and only one is selected at once.
|
||||
*
|
||||
*/
|
||||
class DynamicControl : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY( QString id READ id WRITE setId )
|
||||
Q_PROPERTY( QString selectedType READ selectedType WRITE setSelectedType )
|
||||
Q_PROPERTY( QString match READ match WRITE setMatch )
|
||||
Q_PROPERTY( QString input READ input WRITE setInput )
|
||||
|
||||
public:
|
||||
DynamicControl( const QStringList& typeSelectors = QStringList() );
|
||||
virtual ~DynamicControl();
|
||||
|
||||
|
||||
/// The current type of this control
|
||||
QString selectedType() const { return m_selectedType; }
|
||||
/**
|
||||
* The match selector widget based on this control's type
|
||||
*
|
||||
* The control manages the lifetime of the widget.
|
||||
*/
|
||||
virtual QWidget* matchSelector() { Q_ASSERT( false ); return 0; }
|
||||
/**
|
||||
* The input field widget that is associated with this type
|
||||
*
|
||||
* The control manages the lifetime of the widget.
|
||||
*/
|
||||
virtual QWidget* inputField() { Q_ASSERT( false ); return 0; }
|
||||
|
||||
/// the serializable value of the match
|
||||
QString match() const { return m_match; }
|
||||
/// the serializable value of the input
|
||||
QString input() const { return m_input; }
|
||||
|
||||
// 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
|
||||
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:
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
virtual void setSelectedType( const QString& selectedType ) { m_selectedType = selectedType; }
|
||||
|
||||
protected:
|
||||
// Private constructor, you can't make one. Get it from your Generator.
|
||||
explicit DynamicControl( const QString& selectedType, const QStringList& typeSelectors, QObject* parent = 0 );
|
||||
|
||||
QString m_match;
|
||||
QString m_input;
|
||||
|
||||
private:
|
||||
QString m_selectedType;
|
||||
QStringList m_typeSelectors;
|
||||
QString m_id;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
349
src/libtomahawk/dynamic/DynamicPlaylist.cpp
Normal file
349
src/libtomahawk/dynamic/DynamicPlaylist.cpp
Normal file
@ -0,0 +1,349 @@
|
||||
/****************************************************************************************
|
||||
* 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 "DynamicPlaylist.h"
|
||||
|
||||
#include "sourcelist.h"
|
||||
#include "GeneratorFactory.h"
|
||||
#include "database/database.h"
|
||||
#include "database/databasecommand.h"
|
||||
#include "database/databasecommand_createdynamicplaylist.h"
|
||||
#include "database/databasecommand_setdynamicplaylistrevision.h"
|
||||
#include "database/databasecommand_loaddynamicplaylist.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
DynamicPlaylist::DynamicPlaylist(const Tomahawk::source_ptr& author)
|
||||
: Playlist(author)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "JSON";
|
||||
}
|
||||
|
||||
|
||||
DynamicPlaylist::~DynamicPlaylist()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Called by loadAllPlaylists command
|
||||
DynamicPlaylist::DynamicPlaylist ( const Tomahawk::source_ptr& src,
|
||||
const QString& currentrevision,
|
||||
const QString& title,
|
||||
const QString& info,
|
||||
const QString& creator,
|
||||
const QString& type,
|
||||
GeneratorMode mode,
|
||||
bool shared,
|
||||
int lastmod,
|
||||
const QString& guid )
|
||||
: Playlist( src, currentrevision, title, info, creator, shared, lastmod, guid )
|
||||
{
|
||||
qDebug() << "Creating Dynamic Playlist 1";
|
||||
// TODO instantiate generator
|
||||
m_generator = geninterface_ptr( GeneratorFactory::create( type ) );
|
||||
m_generator->setMode( mode );
|
||||
}
|
||||
|
||||
|
||||
// called when a new playlist is created (no currentrevision, new guid)
|
||||
DynamicPlaylist::DynamicPlaylist ( const Tomahawk::source_ptr& author,
|
||||
const QString& guid,
|
||||
const QString& title,
|
||||
const QString& info,
|
||||
const QString& creator,
|
||||
const QString& type,
|
||||
bool shared )
|
||||
: Playlist ( author, guid, title, info, creator, shared )
|
||||
{
|
||||
qDebug() << "Creating Dynamic Playlist 2";
|
||||
m_generator = geninterface_ptr( GeneratorFactory::create( type ) );
|
||||
}
|
||||
|
||||
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,
|
||||
const QString& guid,
|
||||
const QString& title,
|
||||
const QString& info,
|
||||
const QString& creator,
|
||||
bool shared )
|
||||
{
|
||||
// default generator
|
||||
QString type = "";
|
||||
dynplaylist_ptr dynplaylist = dynplaylist_ptr( new DynamicPlaylist( author, guid, title, info, creator, type, shared ) );
|
||||
|
||||
DatabaseCommand_CreateDynamicPlaylist* cmd = new DatabaseCommand_CreateDynamicPlaylist( author, dynplaylist );
|
||||
connect( cmd, SIGNAL(finished()), dynplaylist.data(), SIGNAL(created()) );
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>(cmd) );
|
||||
dynplaylist->reportCreated( dynplaylist );
|
||||
return dynplaylist;
|
||||
|
||||
}
|
||||
|
||||
// create a new revision that will be a static playlist, as it has entries
|
||||
void
|
||||
DynamicPlaylist::createNewRevision( const QString& newrev,
|
||||
const QString& oldrev,
|
||||
const QString& type,
|
||||
const QList< dyncontrol_ptr>& controls,
|
||||
const QList< plentry_ptr >& entries )
|
||||
{
|
||||
// get the newly added tracks
|
||||
QList< plentry_ptr > added = newEntries( entries );
|
||||
|
||||
QStringList orderedguids;
|
||||
for( int i = 0; i < entries.size(); ++i )
|
||||
orderedguids << entries.at(i)->guid();
|
||||
|
||||
// no conflict resolution or partial updating for controls. all or nothing baby
|
||||
|
||||
// source making the change (local user in this case)
|
||||
source_ptr author = SourceList::instance()->getLocal();
|
||||
// command writes new rev to DB and calls setRevision, which emits our signal
|
||||
DatabaseCommand_SetDynamicPlaylistRevision* cmd =
|
||||
new DatabaseCommand_SetDynamicPlaylistRevision( author,
|
||||
guid(),
|
||||
newrev,
|
||||
oldrev,
|
||||
orderedguids,
|
||||
added,
|
||||
type,
|
||||
Static,
|
||||
controls );
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||
}
|
||||
|
||||
// create a new revision that will be an ondemand playlist, as it has no entries
|
||||
void
|
||||
DynamicPlaylist::createNewRevision( const QString& newrev,
|
||||
const QString& oldrev,
|
||||
const QString& type,
|
||||
const QList< dyncontrol_ptr>& controls )
|
||||
{
|
||||
// can skip the entry stuff. just overwrite with new info
|
||||
source_ptr author = SourceList::instance()->getLocal();
|
||||
// command writes new rev to DB and calls setRevision, which emits our signal
|
||||
DatabaseCommand_SetDynamicPlaylistRevision* cmd =
|
||||
new DatabaseCommand_SetDynamicPlaylistRevision( author,
|
||||
guid(),
|
||||
newrev,
|
||||
oldrev,
|
||||
type,
|
||||
OnDemand,
|
||||
controls );
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||
}
|
||||
|
||||
void
|
||||
DynamicPlaylist::loadRevision( const QString& rev )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "Loading with:" << ( rev.isEmpty() ? currentrevision() : rev );
|
||||
|
||||
DatabaseCommand_LoadDynamicPlaylist* cmd = new DatabaseCommand_LoadDynamicPlaylist( rev.isEmpty() ? currentrevision() : rev );
|
||||
|
||||
if( m_generator->mode() == OnDemand ) {
|
||||
connect( cmd, SIGNAL( done( QString,
|
||||
bool,
|
||||
QString,
|
||||
QList< Tomahawk::dyncontrol_ptr>,
|
||||
bool ) ),
|
||||
SLOT( setRevision( QString,
|
||||
bool,
|
||||
QString,
|
||||
QList< Tomahawk::dyncontrol_ptr>,
|
||||
bool) ) );
|
||||
} else if( m_generator->mode() == Static ) {
|
||||
connect( cmd, SIGNAL( done( QString,
|
||||
QList< QString >,
|
||||
QList< QString >,
|
||||
QString,
|
||||
QList< Tomahawk::dyncontrol_ptr>,
|
||||
bool,
|
||||
QMap< QString, Tomahawk::plentry_ptr >,
|
||||
bool ) ),
|
||||
SLOT( setRevision( QString,
|
||||
QList< QString >,
|
||||
QList< QString >,
|
||||
QString,
|
||||
QList< Tomahawk::dyncontrol_ptr>,
|
||||
bool,
|
||||
QMap< QString, Tomahawk::plentry_ptr >,
|
||||
bool ) ) );
|
||||
|
||||
}
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||
}
|
||||
|
||||
bool
|
||||
DynamicPlaylist::remove( const Tomahawk::dynplaylist_ptr& playlist )
|
||||
{
|
||||
// TODO
|
||||
// DatabaseCommand_DeletePlaylist* cmd = new DatabaseCommand_DeletePlaylist( playlist->author(), playlist->guid() );
|
||||
// APP->database()->enqueue( QSharedPointer<DatabaseCommand>(cmd) );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
DynamicPlaylist::reportCreated( const Tomahawk::dynplaylist_ptr& self )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
Q_ASSERT( self.data() == this );
|
||||
// will emit Collection::playlistCreated(...)
|
||||
author()->collection()->addDynamicPlaylist( self );
|
||||
}
|
||||
|
||||
void
|
||||
DynamicPlaylist::reportDeleted( const Tomahawk::dynplaylist_ptr& self )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
Q_ASSERT( self.data() == this );
|
||||
// will emit Collection::playlistCreated(...)
|
||||
author()->collection()->deleteDynamicPlaylist( self );
|
||||
}
|
||||
|
||||
void DynamicPlaylist::addEntries(const QList< query_ptr >& queries, const QString& oldrev)
|
||||
{
|
||||
Q_ASSERT( m_generator->mode() == Static );
|
||||
|
||||
QList<plentry_ptr> el = addEntriesInternal( queries );
|
||||
|
||||
QString newrev = uuid();
|
||||
createNewRevision( newrev, oldrev, m_generator->type(), m_generator->controls(), el );
|
||||
}
|
||||
|
||||
void DynamicPlaylist::addEntry(const Tomahawk::query_ptr& query, const QString& oldrev)
|
||||
{
|
||||
QList<query_ptr> queries;
|
||||
queries << query;
|
||||
|
||||
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 )
|
||||
{
|
||||
// we're probably being called by a database worker thread
|
||||
if( QThread::currentThread() != thread() )
|
||||
{
|
||||
QMetaObject::invokeMethod( this,
|
||||
"setRevision",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_ARG( QString, rev ),
|
||||
Q_ARG( QList<QString> , neworderedguids ),
|
||||
Q_ARG( QList<QString> , oldorderedguids ),
|
||||
Q_ARG( QString , type ),
|
||||
QGenericArgument( "QList< Tomahawk::dyncontrol_ptr > " , (const void*)&controls ),
|
||||
Q_ARG( bool, is_newest_rev ),
|
||||
QGenericArgument( "QMap< QString,Tomahawk::plentry_ptr > " , (const void*)&addedmap ),
|
||||
Q_ARG( bool, applied ) );
|
||||
return;
|
||||
}
|
||||
if( m_generator->type() != type ) { // new generator needed
|
||||
m_generator = GeneratorFactory::create( type );
|
||||
}
|
||||
|
||||
m_generator->setControls( controls );
|
||||
m_generator->setMode( Static );
|
||||
|
||||
DynamicPlaylistRevision pr = setNewRevision( rev, neworderedguids, oldorderedguids, is_newest_rev, addedmap );
|
||||
pr.controls = controls;
|
||||
pr.type = type;
|
||||
pr.mode = Static;
|
||||
|
||||
if( applied )
|
||||
setCurrentrevision( rev );
|
||||
pr.applied = applied;
|
||||
|
||||
emit revisionLoaded( pr );
|
||||
}
|
||||
|
||||
// ondemand version
|
||||
void
|
||||
DynamicPlaylist::setRevision( const QString& rev,
|
||||
bool is_newest_rev,
|
||||
const QString& type,
|
||||
const QList< Tomahawk::dyncontrol_ptr>& controls,
|
||||
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< Tomahawk::dyncontrol_ptr >" , (const void*)&controls ),
|
||||
Q_ARG( bool, applied ) );
|
||||
return;
|
||||
}
|
||||
if( m_generator->type() != type ) { // new generator needed
|
||||
m_generator = geninterface_ptr( GeneratorFactory::create( type ) );
|
||||
}
|
||||
|
||||
m_generator->setControls( controls );
|
||||
m_generator->setMode( OnDemand );
|
||||
|
||||
DynamicPlaylistRevision pr;
|
||||
pr.oldrevisionguid = currentrevision();
|
||||
pr.revisionguid = rev;
|
||||
pr.controls = controls;
|
||||
pr.type = type;
|
||||
pr.mode = OnDemand;
|
||||
|
||||
emit revisionLoaded( pr );
|
||||
}
|
||||
|
161
src/libtomahawk/dynamic/DynamicPlaylist.h
Normal file
161
src/libtomahawk/dynamic/DynamicPlaylist.h
Normal file
@ -0,0 +1,161 @@
|
||||
/****************************************************************************************
|
||||
* 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/>. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef DYNAMIC_PLAYLIST_H
|
||||
#define DYNAMIC_PLAYLIST_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QList>
|
||||
#include <QSharedPointer>
|
||||
|
||||
#include "playlist.h"
|
||||
#include "typedefs.h"
|
||||
#include "dynamic/DynamicControl.h"
|
||||
|
||||
class DatabaseCommand_LoadAllDynamicPlaylists;
|
||||
class DatabaseCommand_SetDynamicPlaylistRevision;
|
||||
class DatabaseCommand_CreateDynamicPlaylist;
|
||||
|
||||
namespace Tomahawk {
|
||||
|
||||
/**
|
||||
* Subclass of playlist that adds the information needed to store a dynamic playlist.
|
||||
* It uses normal PlaylistEntries but also has a mode, a generator, and a list of controls
|
||||
*/
|
||||
|
||||
struct DynamicPlaylistRevision : PlaylistRevision
|
||||
{
|
||||
QList< dyncontrol_ptr > controls;
|
||||
Tomahawk::GeneratorMode mode;
|
||||
QString type;
|
||||
|
||||
DynamicPlaylistRevision( const PlaylistRevision& other )
|
||||
{
|
||||
revisionguid = other.revisionguid;
|
||||
oldrevisionguid = other.oldrevisionguid;
|
||||
newlist = other.newlist;
|
||||
added = other.added;
|
||||
removed = other.removed;
|
||||
applied = other.applied;
|
||||
}
|
||||
|
||||
DynamicPlaylistRevision() {}
|
||||
};
|
||||
|
||||
class DynamicPlaylist : public Playlist
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY( GeneratorMode mode WRITE setMode READ mode )
|
||||
Q_PROPERTY( QString type WRITE setType READ type )
|
||||
|
||||
friend class ::DatabaseCommand_LoadAllDynamicPlaylists;
|
||||
friend class ::DatabaseCommand_SetDynamicPlaylistRevision;
|
||||
friend class ::DatabaseCommand_CreateDynamicPlaylist;
|
||||
|
||||
public:
|
||||
virtual ~DynamicPlaylist();
|
||||
|
||||
/// Generate an empty dynamic playlist with default generator
|
||||
static Tomahawk::dynplaylist_ptr create( const source_ptr& author,
|
||||
const QString& guid,
|
||||
const QString& title,
|
||||
const QString& info,
|
||||
const QString& creator,
|
||||
bool shared
|
||||
);
|
||||
static bool remove( const dynplaylist_ptr& playlist );
|
||||
|
||||
virtual void loadRevision( const QString& rev = "" );
|
||||
|
||||
GeneratorMode mode() const;
|
||||
QString type() const;
|
||||
geninterface_ptr generator() const;
|
||||
|
||||
virtual void addEntries( const QList< query_ptr >& queries, const QString& oldrev );
|
||||
virtual void addEntry( const Tomahawk::query_ptr& query, const QString& oldrev );
|
||||
|
||||
// <IGNORE hack="true">
|
||||
// these need to exist and be public for the json serialization stuff
|
||||
// you SHOULD NOT call them. They are used for an alternate CTOR method from json.
|
||||
// maybe friend QObjectHelper and make them private?
|
||||
explicit DynamicPlaylist( const source_ptr& author );
|
||||
void setMode( GeneratorMode mode );
|
||||
void setType( const QString& type ) { /** TODO */; }
|
||||
void setGenerator( const geninterface_ptr& gen_ptr );
|
||||
// </IGNORE>
|
||||
|
||||
signals:
|
||||
/// emitted when the playlist revision changes (whenever the playlist changes)
|
||||
void revisionLoaded( Tomahawk::DynamicPlaylistRevision );
|
||||
|
||||
public slots:
|
||||
// want to update the playlist from the model?
|
||||
// generate a newrev using uuid() and call this:
|
||||
// if this is a static playlist, pass it a new list of entries. implicitly sets mode to static
|
||||
void createNewRevision( const QString& newrev, const QString& oldrev, const QString& type, const QList< dyncontrol_ptr>& controls, const QList< plentry_ptr >& entries );
|
||||
// if it is ondemand, no entries are needed implicitly sets mode to ondemand
|
||||
void createNewRevision( const QString& newrev, const QString& oldrev, const QString& type, const QList< dyncontrol_ptr>& controls );
|
||||
|
||||
void reportCreated( const Tomahawk::dynplaylist_ptr& self );
|
||||
void reportDeleted( const Tomahawk::dynplaylist_ptr& self );
|
||||
|
||||
// called from setdynamicplaylistrevision db cmd
|
||||
// static version
|
||||
void setRevision( const QString& rev,
|
||||
const QList<QString>& neworderedguids,
|
||||
const QList<QString>& oldorderedguids,
|
||||
const QString& type,
|
||||
const QList< Tomahawk::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,
|
||||
bool applied );
|
||||
private:
|
||||
// called from loadAllPlaylists DB cmd:
|
||||
explicit DynamicPlaylist( const source_ptr& src,
|
||||
const QString& currentrevision,
|
||||
const QString& title,
|
||||
const QString& info,
|
||||
const QString& creator,
|
||||
const QString& type,
|
||||
GeneratorMode mode,
|
||||
bool shared,
|
||||
int lastmod,
|
||||
const QString& guid = "" ); // populate db
|
||||
|
||||
// called when creating new playlist
|
||||
explicit DynamicPlaylist( const source_ptr& author,
|
||||
const QString& guid,
|
||||
const QString& title,
|
||||
const QString& info,
|
||||
const QString& creator,
|
||||
const QString& type,
|
||||
bool shared );
|
||||
|
||||
private:
|
||||
geninterface_ptr m_generator;
|
||||
};
|
||||
|
||||
}; // namespace
|
||||
|
||||
#endif
|
27
src/libtomahawk/dynamic/GeneratorFactory.cpp
Normal file
27
src/libtomahawk/dynamic/GeneratorFactory.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include "dynamic/GeneratorFactory.h"
|
||||
#include "dynamic/GeneratorInterface.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
QHash< QString, GeneratorFactoryInterface* > GeneratorFactory::s_factories = QHash< QString, GeneratorFactoryInterface* >();
|
||||
|
||||
geninterface_ptr GeneratorFactory::create ( const QString& type )
|
||||
{
|
||||
if( type.isEmpty() && !s_factories.isEmpty() ) // default, return first
|
||||
return geninterface_ptr( s_factories.begin().value()->create() );
|
||||
|
||||
if( !s_factories.contains( type ) )
|
||||
return geninterface_ptr();
|
||||
|
||||
return geninterface_ptr( s_factories.value( type )->create() );
|
||||
}
|
||||
|
||||
void GeneratorFactory::registerFactory ( const QString& type, GeneratorFactoryInterface* interface )
|
||||
{
|
||||
s_factories.insert( type, interface );
|
||||
}
|
||||
|
||||
QStringList GeneratorFactory::types()
|
||||
{
|
||||
return s_factories.keys();
|
||||
}
|
40
src/libtomahawk/dynamic/GeneratorFactory.h
Normal file
40
src/libtomahawk/dynamic/GeneratorFactory.h
Normal file
@ -0,0 +1,40 @@
|
||||
#ifndef GENERATOR_FACTORY_H
|
||||
#define GENERATOR_FACTORY_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QString>
|
||||
|
||||
#include "dynamic/GeneratorInterface.h"
|
||||
|
||||
namespace Tomahawk {
|
||||
|
||||
/**
|
||||
* Generators should subclass this and have it create the custom Generator
|
||||
*/
|
||||
class GeneratorFactoryInterface
|
||||
{
|
||||
public:
|
||||
GeneratorFactoryInterface() {}
|
||||
|
||||
virtual GeneratorInterface* create() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Simple factory that generates Generators from string type descriptors
|
||||
*/
|
||||
class GeneratorFactory
|
||||
{
|
||||
public:
|
||||
static geninterface_ptr create( const QString& type );
|
||||
static void registerFactory( const QString& type, GeneratorFactoryInterface* interface );
|
||||
static QStringList types();
|
||||
|
||||
private:
|
||||
static QHash<QString, GeneratorFactoryInterface*> s_factories;
|
||||
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
67
src/libtomahawk/dynamic/GeneratorInterface.cpp
Normal file
67
src/libtomahawk/dynamic/GeneratorInterface.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
/****************************************************************************************
|
||||
* 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()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QList< Tomahawk::dyncontrol_ptr >
|
||||
Tomahawk::GeneratorInterface::controls()
|
||||
{
|
||||
if( m_controls.isEmpty() ) { // return a default control (so the user can add more)
|
||||
return QList< Tomahawk::dyncontrol_ptr >() << createControl();
|
||||
}
|
||||
|
||||
return m_controls;
|
||||
}
|
||||
|
||||
void
|
||||
Tomahawk::GeneratorInterface::addControl( const Tomahawk::dyncontrol_ptr& control )
|
||||
{
|
||||
m_controls << control;
|
||||
}
|
||||
|
||||
void
|
||||
Tomahawk::GeneratorInterface::clearControls()
|
||||
{
|
||||
m_controls.clear();
|
||||
}
|
||||
|
||||
void
|
||||
Tomahawk::GeneratorInterface::setControls( const QList< Tomahawk::dyncontrol_ptr >& controls )
|
||||
{
|
||||
m_controls = controls;
|
||||
}
|
||||
|
||||
Tomahawk::dyncontrol_ptr Tomahawk::GeneratorInterface::createControl(const QString& type)
|
||||
{
|
||||
return dyncontrol_ptr();
|
||||
}
|
||||
|
95
src/libtomahawk/dynamic/GeneratorInterface.h
Normal file
95
src/libtomahawk/dynamic/GeneratorInterface.h
Normal file
@ -0,0 +1,95 @@
|
||||
/****************************************************************************************
|
||||
* 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/>. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef GENERATOR_INTERFACE_H
|
||||
#define GENERATOR_INTERFACE_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QStringList>
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "query.h"
|
||||
#include "dynamic/DynamicControl.h"
|
||||
|
||||
namespace Tomahawk {
|
||||
|
||||
/**
|
||||
* The abstract interface for Dynamic Playlist Generators. Generators have the following features:
|
||||
* - They create new DynamicControls that are appropriate for the generator
|
||||
* - They expose a list of controls that this generator currently is operating on
|
||||
* - They have a mode of OnDemand or Static
|
||||
*
|
||||
* And they generate tracks
|
||||
*/
|
||||
class GeneratorInterface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY( QString type READ type )
|
||||
Q_PROPERTY( GeneratorMode mode READ mode WRITE setMode )
|
||||
Q_ENUMS( GeneratorMode )
|
||||
|
||||
public:
|
||||
// can't inline constructors/destructors for forward declared shared pointer types
|
||||
GeneratorInterface();
|
||||
explicit GeneratorInterface( QObject* parent = 0 );
|
||||
virtual ~GeneratorInterface();
|
||||
|
||||
// Can't make it pure otherwise we can't shove it in QVariants :-/
|
||||
// empty QString means use default
|
||||
/// The generator will keep track of all the controls it creates. No need to tell it about controls
|
||||
/// you ask it to create
|
||||
virtual dyncontrol_ptr createControl( const QString& type = QString() );
|
||||
|
||||
/**
|
||||
* Generate tracks from the controls in this playlist. If the current mode is
|
||||
* OnDemand, then \p number is not taken into account. If this generator is in static
|
||||
* mode, then it will return the desired number of tracks
|
||||
*
|
||||
* Connect to the generated() signal for the results.
|
||||
*
|
||||
*/
|
||||
virtual void generate( int number = -1 ) {}
|
||||
|
||||
/// The type of this generator
|
||||
QString type() const { return m_type; }
|
||||
|
||||
GeneratorMode mode() const { return m_mode; }
|
||||
void setMode( GeneratorMode mode ) { m_mode = mode; }
|
||||
|
||||
// control functions
|
||||
QList< dyncontrol_ptr > controls();
|
||||
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 );
|
||||
|
||||
protected:
|
||||
QString m_type;
|
||||
GeneratorMode m_mode;
|
||||
QList< dyncontrol_ptr > m_controls;
|
||||
QStringList m_typeSelectors;
|
||||
};
|
||||
|
||||
typedef QSharedPointer<GeneratorInterface> geninterface_ptr;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
109
src/libtomahawk/dynamic/echonest/EchonestControl.cpp
Normal file
109
src/libtomahawk/dynamic/echonest/EchonestControl.cpp
Normal file
@ -0,0 +1,109 @@
|
||||
/****************************************************************************************
|
||||
* 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/echonest/EchonestControl.h"
|
||||
|
||||
#include <echonest/Playlist.h>
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QLineEdit>
|
||||
|
||||
|
||||
Tomahawk::EchonestControl::EchonestControl( const QString& type, const QStringList& typeSelectors, QObject* parent )
|
||||
: DynamicControl ( type.isEmpty() ? "Artist" : type, typeSelectors, parent )
|
||||
{
|
||||
updateWidgets();
|
||||
}
|
||||
|
||||
QWidget*
|
||||
Tomahawk::EchonestControl::inputField()
|
||||
{
|
||||
return m_input.data();
|
||||
}
|
||||
|
||||
QWidget*
|
||||
Tomahawk::EchonestControl::matchSelector()
|
||||
{
|
||||
return m_match.data();
|
||||
}
|
||||
|
||||
void
|
||||
Tomahawk::EchonestControl::setSelectedType ( const QString& type )
|
||||
{
|
||||
if( !m_input.isNull() )
|
||||
delete m_input.data();
|
||||
if( !m_match.isNull() )
|
||||
delete m_match.data();
|
||||
|
||||
Tomahawk::DynamicControl::setSelectedType ( type );
|
||||
updateWidgets();
|
||||
}
|
||||
|
||||
Echonest::DynamicPlaylist::PlaylistParamData
|
||||
Tomahawk::EchonestControl::toENParam() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
void
|
||||
Tomahawk::EchonestControl::updateWidgets()
|
||||
{
|
||||
if( !m_input.isNull() )
|
||||
delete m_input.data();
|
||||
if( !m_match.isNull() )
|
||||
delete m_match.data();
|
||||
|
||||
// make sure the widgets are the proper kind for the selected type, and hook up to their slots
|
||||
if( selectedType() == "Artist" ) {
|
||||
m_currentType = Echonest::DynamicPlaylist::Artist;
|
||||
|
||||
QComboBox* match = new QComboBox();
|
||||
QLineEdit* input = new QLineEdit();
|
||||
|
||||
match->addItem( "Limit To", Echonest::DynamicPlaylist::ArtistType );
|
||||
match->addItem( "Similar To", Echonest::DynamicPlaylist::ArtistRadioType );
|
||||
|
||||
input->setPlaceholderText( "Artist name" );
|
||||
input->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Fixed );
|
||||
|
||||
connect( match, SIGNAL( currentIndexChanged(int) ), this, SLOT( updateData() ) );
|
||||
connect( input, SIGNAL( textChanged(QString) ), this, SLOT( updateData() ) );
|
||||
|
||||
match->hide();
|
||||
input->hide();
|
||||
m_match = QWeakPointer< QWidget >( match );
|
||||
m_input = QWeakPointer< QWidget >( input );
|
||||
} else {
|
||||
m_match = QWeakPointer<QWidget>( new QWidget );
|
||||
m_input = QWeakPointer<QWidget>( new QWidget );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Tomahawk::EchonestControl::updateData()
|
||||
{
|
||||
qDebug() << "Sender:" << sender() << qobject_cast<QLineEdit*>(sender()) << m_input << qobject_cast<QLineEdit*>(m_input.data());
|
||||
if( selectedType() == "Artist" ) {
|
||||
QComboBox* combo = qobject_cast<QComboBox*>( m_match.data() );
|
||||
if( combo ) {
|
||||
}
|
||||
QLineEdit* edit = qobject_cast<QLineEdit*>( m_input.data() );
|
||||
if( edit && !edit->text().isEmpty() ) {
|
||||
m_data.first = m_currentType;
|
||||
m_data.second = edit->text();
|
||||
}
|
||||
}
|
||||
}
|
63
src/libtomahawk/dynamic/echonest/EchonestControl.h
Normal file
63
src/libtomahawk/dynamic/echonest/EchonestControl.h
Normal file
@ -0,0 +1,63 @@
|
||||
/****************************************************************************************
|
||||
* 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/>. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef ECHONEST_CONTROL_H
|
||||
#define ECHONEST_CONTROL_H
|
||||
|
||||
#include <echonest/Playlist.h>
|
||||
|
||||
#include "dynamic/DynamicControl.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class EchonestControl : public DynamicControl
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
virtual QWidget* inputField();
|
||||
virtual QWidget* matchSelector();
|
||||
|
||||
/// Converts this to an echonest suitable parameter
|
||||
Echonest::DynamicPlaylist::PlaylistParamData toENParam() const;
|
||||
|
||||
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();
|
||||
|
||||
Echonest::DynamicPlaylist::PlaylistParam m_currentType;
|
||||
|
||||
QWeakPointer< QWidget > m_input;
|
||||
QWeakPointer< QWidget > m_match;
|
||||
|
||||
Echonest::DynamicPlaylist::PlaylistParamData m_data;
|
||||
|
||||
friend class EchonestGenerator;
|
||||
};
|
||||
|
||||
typedef QSharedPointer<EchonestControl> encontrol_ptr;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
112
src/libtomahawk/dynamic/echonest/EchonestGenerator.cpp
Normal file
112
src/libtomahawk/dynamic/echonest/EchonestGenerator.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
/****************************************************************************************
|
||||
* 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/echonest/EchonestGenerator.h"
|
||||
#include "dynamic/echonest/EchonestControl.h"
|
||||
#include "query.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
EchonestFactory::EchonestFactory()
|
||||
{}
|
||||
|
||||
GeneratorInterface*
|
||||
EchonestFactory::create()
|
||||
{
|
||||
return new EchonestGenerator();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
EchonestGenerator::~EchonestGenerator()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
dyncontrol_ptr
|
||||
EchonestGenerator::createControl( const QString& type )
|
||||
{
|
||||
m_controls << dyncontrol_ptr( new EchonestControl( type, m_typeSelectors ) );
|
||||
return m_controls.last();
|
||||
}
|
||||
|
||||
void
|
||||
EchonestGenerator::generate ( int number )
|
||||
{
|
||||
// convert to an echonest query, and fire it off
|
||||
if( number < 0 ) { // dynamic
|
||||
|
||||
} else { // static
|
||||
Echonest::DynamicPlaylist::PlaylistParams params;
|
||||
foreach( const dyncontrol_ptr& control, m_controls ) {
|
||||
params.append( control.dynamicCast<EchonestControl>()->toENParam() );
|
||||
}
|
||||
params.append( Echonest::DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Type, determineRadioType() ) );
|
||||
params.append( Echonest::DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Results, number ) );
|
||||
QNetworkReply* reply = Echonest::DynamicPlaylist::staticPlaylist( params );
|
||||
qDebug() << "Generating a static playlist from echonest!" << reply->url().toString();
|
||||
connect( reply, SIGNAL( finished() ), this, SLOT( staticFinished() ) );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
EchonestGenerator::staticFinished()
|
||||
{
|
||||
Q_ASSERT( sender() );
|
||||
Q_ASSERT( qobject_cast< QNetworkReply* >( sender() ) );
|
||||
|
||||
QNetworkReply* reply = qobject_cast< QNetworkReply* >( sender() );
|
||||
|
||||
Echonest::SongList songs;
|
||||
try {
|
||||
songs = Echonest::DynamicPlaylist::parseStaticPlaylist( reply );
|
||||
} catch( const Echonest::ParseError& e ) {
|
||||
qWarning() << "libechonest threw an error trying to parse the static playlist!" << e.errorType() << e.what();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
QList< query_ptr > queries;
|
||||
foreach( const Echonest::Song& song, songs ) {
|
||||
qDebug() << "EchonestGenerator got song:" << song;
|
||||
QVariantMap track;
|
||||
track[ "artist" ] = song.artistName();
|
||||
// track[ "album" ] = song.release(); // TODO should we include it? can be quite specific
|
||||
track[ "track" ] = song.title();
|
||||
queries << query_ptr( new Query( track ) );
|
||||
}
|
||||
|
||||
emit generated( queries );
|
||||
}
|
||||
|
||||
|
||||
// tries to heuristically determine what sort of radio this is based on the controls
|
||||
Echonest::DynamicPlaylist::ArtistTypeEnum EchonestGenerator::determineRadioType() const
|
||||
{
|
||||
// TODO
|
||||
return Echonest::DynamicPlaylist::ArtistRadioType;
|
||||
}
|
||||
|
58
src/libtomahawk/dynamic/echonest/EchonestGenerator.h
Normal file
58
src/libtomahawk/dynamic/echonest/EchonestGenerator.h
Normal file
@ -0,0 +1,58 @@
|
||||
/****************************************************************************************
|
||||
* 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/>. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef ECHONEST_GENERATOR_H
|
||||
#define ECHONEST_GENERATOR_H
|
||||
|
||||
#include <echonest/Playlist.h>
|
||||
|
||||
#include "dynamic/GeneratorInterface.h"
|
||||
#include "dynamic/GeneratorFactory.h"
|
||||
#include "dynamic/DynamicControl.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class EchonestFactory : public GeneratorFactoryInterface
|
||||
{
|
||||
public:
|
||||
EchonestFactory();
|
||||
|
||||
virtual GeneratorInterface* create();
|
||||
|
||||
};
|
||||
|
||||
class EchonestGenerator : public GeneratorInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit EchonestGenerator( QObject* parent = 0 );
|
||||
virtual ~EchonestGenerator();
|
||||
|
||||
virtual dyncontrol_ptr createControl( const QString& type = QString() );
|
||||
|
||||
virtual void generate ( int number = -1 );
|
||||
|
||||
private slots:
|
||||
void staticFinished();
|
||||
|
||||
private:
|
||||
Echonest::DynamicPlaylist::ArtistTypeEnum determineRadioType() const;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -286,11 +286,11 @@ Playlist::setNewRevision( const QString& rev,
|
||||
//qDebug() << "counters:" << neworderedguids.count() << entriesmap.count() << addedmap.count();
|
||||
foreach( const QString& id, neworderedguids )
|
||||
{
|
||||
qDebug() << "id:" << id;
|
||||
qDebug() << "newordered:" << neworderedguids.count() << neworderedguids;
|
||||
qDebug() << "entriesmap:" << entriesmap.count() << entriesmap;
|
||||
qDebug() << "addedmap:" << addedmap.count() << addedmap;
|
||||
qDebug() << "m_entries" << m_entries;
|
||||
//qDebug() << "id:" << id;
|
||||
//qDebug() << "newordered:" << neworderedguids.count() << neworderedguids;
|
||||
//qDebug() << "entriesmap:" << entriesmap.count() << entriesmap;
|
||||
//qDebug() << "addedmap:" << addedmap.count() << addedmap;
|
||||
//qDebug() << "m_entries" << m_entries;
|
||||
|
||||
if( entriesmap.contains( id ) )
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user