1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-14 01:54:07 +02:00

Add dynamic interface, and fix up some more dynamic playlist code

This commit is contained in:
Leo Franchi
2010-12-04 16:51:33 -05:00
parent 5b23b6ad81
commit c30f62e834
11 changed files with 220 additions and 55 deletions

View File

@@ -7,6 +7,7 @@
#include "tomahawk/query.h" #include "tomahawk/query.h"
#include "tomahawk/typedefs.h" #include "tomahawk/typedefs.h"
#include "typedefs.h"
class DatabaseCommand_LoadAllPlaylists; class DatabaseCommand_LoadAllPlaylists;
class DatabaseCommand_SetPlaylistRevision; class DatabaseCommand_SetPlaylistRevision;
@@ -174,7 +175,7 @@ protected:
const QString& creator, const QString& creator,
bool shared ); bool shared );
QList<plentry_ptr> newEntries( const QList< plentry_ptr >& entries ); QList< plentry_ptr > newEntries( const QList< plentry_ptr >& entries );
PlaylistRevision setNewRevision( const QString& rev, PlaylistRevision setNewRevision( const QString& rev,
const QList<QString>& neworderedguids, const QList<QString>& neworderedguids,
const QList<QString>& oldorderedguids, const QList<QString>& oldorderedguids,

View File

@@ -92,8 +92,9 @@ SET( tomahawkSources ${tomahawkSources}
database/databasecollection.cpp database/databasecollection.cpp
dynamic/dynamicplaylist.cpp dynamic/dynamicplaylist.cpp
dynamic/dynamiccontrol.cpp
dynamic/generatorfactory.cpp dynamic/generatorfactory.cpp
dynamic/echonest/echonestgenerator.cpp
dynamic/echonest/echonestcontrol.cpp
scrobbler.cpp scrobbler.cpp
xmppbot/xmppbot.cpp xmppbot/xmppbot.cpp
@@ -230,6 +231,8 @@ SET( tomahawkHeaders ${tomahawkHeaders}
dynamic/dynamiccontrol.h dynamic/dynamiccontrol.h
dynamic/generatorfactory.h dynamic/generatorfactory.h
dynamic/generatorinterface.h dynamic/generatorinterface.h
dynamic/echonest/echonestgenerator.h
dynamic/echonest/echonestcontrol.h
musicscanner.h musicscanner.h
scriptresolver.h scriptresolver.h

View File

@@ -1,6 +1,77 @@
/****************************************************************************************
* 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 #ifndef DYNAMIC_PLAYLIST_CONTROL
#define DYNAMIC_PLAYLIST_CONTROL #define DYNAMIC_PLAYLIST_CONTROL
#include <QtCore/QObject>
#include <QtCore/QSharedPointer>
#include <QStringList>
#include <QtGui/QWidget>
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 selectedType READ selectedType WRITE setSelectedType )
Q_PROPERTY( QStringList typeSelectors READ typeSelectors )
public:
virtual ~DynamicControl();
/// The current type of this control
QString selectedType() const { return m_selectedType; }
/// The match selector widget based on this control's type
virtual QWidget* matchSelector() { return 0; }
/// The input field widget that is associated with this type
virtual QWidget* inputField() { return 0; }
/// All the potential type selectors for this control
QStringList typeSelectors() const { return m_typeSelectors; }
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& type ) { m_selectedType = type; }
protected:
// Private constructor, you can't make one. Get it from your Generator.
explicit DynamicControl( const QString& type, const QStringList& typeSelectors, QObject* parent = 0 ) : QObject( parent ), m_selectedType( type ), m_typeSelectors( typeSelectors ) {}
private:
QString m_selectedType;
QStringList m_typeSelectors;
};
typedef QSharedPointer<DynamicControl> dyncontrol_ptr;
};
#endif #endif

View File

@@ -1,6 +1,25 @@
/****************************************************************************************
* 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 "dynamicplaylist.h"
#include "tomahawk/tomahawkapp.h" #include "tomahawk/tomahawkapp.h"
#include "generatorfactory.h"
#include "database.h"
#include "databasecommand.h"
using namespace Tomahawk; using namespace Tomahawk;
@@ -44,7 +63,7 @@ dynplaylist_ptr DynamicPlaylist::create( const Tomahawk::source_ptr& author,
{ {
// TODO default generator? // TODO default generator?
QString type = "default_generator"; QString type = "default_generator";
dynplaylist_ptr dynplaylist = new dynplaylist_ptr( new DynamicPlaylist( author, guid, title, info, creator, type, shared ) ); dynplaylist_ptr dynplaylist = dynplaylist_ptr( new DynamicPlaylist( author, guid, title, info, creator, type, shared ) );
DatabaseCommand_CreateDynamicPlaylist* cmd = new DatabaseCommand_CreateDynamicPlaylist( author, dynplaylist ); DatabaseCommand_CreateDynamicPlaylist* cmd = new DatabaseCommand_CreateDynamicPlaylist( author, dynplaylist );
connect( cmd, SIGNAL(finished()), dynplaylist.data(), SIGNAL(created()) ); connect( cmd, SIGNAL(finished()), dynplaylist.data(), SIGNAL(created()) );
@@ -65,12 +84,12 @@ void DynamicPlaylist::createNewRevision( const QString& newrev,
QList< plentry_ptr > added = newEntries( entries ); QList< plentry_ptr > added = newEntries( entries );
QStringList orderedguids; QStringList orderedguids;
foreach( plentry_ptr p, entries ) for( int i = 0; i < entries.size(); ++i )
orderedguids << p->guid(); orderedguids << entries.at(i)->guid();
// no conflict resolution or partial updating for controls. all or nothing baby // no conflict resolution or partial updating for controls. all or nothing baby
// source making the change (localy user in this case) // source making the change (local user in this case)
source_ptr author = APP->sourcelist().getLocal(); source_ptr author = APP->sourcelist().getLocal();
// command writes new rev to DB and calls setRevision, which emits our signal // command writes new rev to DB and calls setRevision, which emits our signal
DatabaseCommand_SetDynamicPlaylistRevision* cmd = DatabaseCommand_SetDynamicPlaylistRevision* cmd =
@@ -81,7 +100,7 @@ void DynamicPlaylist::createNewRevision( const QString& newrev,
orderedguids, orderedguids,
added, added,
type, type,
STATIC, OnDemand,
controls ); controls );
APP->database()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) ); APP->database()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
} }
@@ -101,7 +120,7 @@ void DynamicPlaylist::createNewRevision( const QString& newrev,
newrev, newrev,
oldrev, oldrev,
type, type,
STATIC, Static,
controls ); controls );
APP->database()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) ); APP->database()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
} }
@@ -113,7 +132,7 @@ void DynamicPlaylist::loadRevision( const QString& rev )
DatabaseCommand_LoadDynamicPlaylist* cmd = DatabaseCommand_LoadDynamicPlaylist* cmd =
new DatabaseCommand_LoadDynamicPlaylist( rev.isEmpty() ? currentrevision() : rev, m_generator->mode() ); new DatabaseCommand_LoadDynamicPlaylist( rev.isEmpty() ? currentrevision() : rev, m_generator->mode() );
if( m_generator->mode() == ONDEMAND ) { if( m_generator->mode() == OnDemand ) {
connect( cmd, SIGNAL( done( QString, connect( cmd, SIGNAL( done( QString,
bool, bool,
const QString, const QString,
@@ -124,7 +143,7 @@ void DynamicPlaylist::loadRevision( const QString& rev )
const QString, const QString,
QList< dyncontrol_ptr>, QList< dyncontrol_ptr>,
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 >,
@@ -148,7 +167,7 @@ void DynamicPlaylist::loadRevision( const QString& rev )
bool DynamicPlaylist::remove( const Tomahawk::dynplaylist_ptr& playlist ) bool DynamicPlaylist::remove( const Tomahawk::dynplaylist_ptr& playlist )
{ {
return remove( playlist.staticCast<Tomahawk::playlist_ptr>() ); return Playlist::remove( playlist.staticCast<Tomahawk::Playlist>() );
} }
void DynamicPlaylist::reportCreated( const Tomahawk::dynplaylist_ptr& self ) void DynamicPlaylist::reportCreated( const Tomahawk::dynplaylist_ptr& self )
@@ -156,7 +175,7 @@ void DynamicPlaylist::reportCreated( const Tomahawk::dynplaylist_ptr& self )
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
Q_ASSERT( self.data() == this ); Q_ASSERT( self.data() == this );
// will emit Collection::playlistCreated(...) // will emit Collection::playlistCreated(...)
m_source->collection()->addPlaylist( self.staticCast<Tomahawk::playlist_ptr>() ); author()->collection()->addPlaylist( self.staticCast<Tomahawk::Playlist>() );
} }
void DynamicPlaylist::reportDeleted( const Tomahawk::dynplaylist_ptr& self ) void DynamicPlaylist::reportDeleted( const Tomahawk::dynplaylist_ptr& self )
@@ -164,7 +183,7 @@ void DynamicPlaylist::reportDeleted( const Tomahawk::dynplaylist_ptr& self )
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
Q_ASSERT( self.data() == this ); Q_ASSERT( self.data() == this );
// will emit Collection::playlistCreated(...) // will emit Collection::playlistCreated(...)
m_source->collection()->deletePlaylist( self.staticCast<Tomahawk::playlist_ptr>() ); author()->collection()->deletePlaylist( self.staticCast<Tomahawk::Playlist>() );
} }
// static version // static version
@@ -194,19 +213,19 @@ void DynamicPlaylist::setRevision( const QString& rev,
return; return;
} }
if( m_generator->type() != type ) { // new generator needed if( m_generator->type() != type ) { // new generator needed
m_generator = generatorinterface_ptr( GeneratorFactory::create( type ) ); m_generator = GeneratorFactory::create( type );
} }
m_generator->setControls( controls ); m_generator->setControls( controls );
m_generator->setMode( ONDEMAND ) m_generator->setMode( Static );
DynamicPlaylistRevision pr = DynamicPlaylistRevision( setNewRevision( rev, neworderedguids, oldorderedguids, is_newest_rev, addedmap ) ); DynamicPlaylistRevision pr = setNewRevision( rev, neworderedguids, oldorderedguids, is_newest_rev, addedmap );
pr.controls = controls; pr.controls = controls;
pr.type = type; pr.type = type;
pr.mode = STATIC; pr.mode = Static;
if( applied ) if( applied )
setCurrentRevision( rev ); setCurrentrevision( rev );
pr.applied = applied; pr.applied = applied;
emit revisionLoaded( pr ); emit revisionLoaded( pr );
@@ -220,18 +239,18 @@ void DynamicPlaylist::setRevision( const QString& rev,
bool applied ) bool applied )
{ {
if( m_generator->type() != type ) { // new generator needed if( m_generator->type() != type ) { // new generator needed
m_generator = generatorinterface_ptr( GeneratorFactory::create( type ) ); m_generator = geninterface_ptr( GeneratorFactory::create( type ) );
} }
m_generator->setControls( controls ); m_generator->setControls( controls );
m_generator->setMode( ONDEMAND ) m_generator->setMode( OnDemand );
DynamicPlaylistRevision pr; DynamicPlaylistRevision pr;
pr.oldrevisionguid = m_currentrevision; pr.oldrevisionguid = currentrevision();
pr.revisionguid = rev; pr.revisionguid = rev;
pr.controls = controls; pr.controls = controls;
pr.type = type; pr.type = type;
pr.mode = ONDEMAND; pr.mode = OnDemand;
emit revisionLoaded( pr ); emit revisionLoaded( pr );
} }

View File

@@ -1,3 +1,19 @@
/****************************************************************************************
* 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 #ifndef DYNAMIC_PLAYLIST_H
#define DYNAMIC_PLAYLIST_H #define DYNAMIC_PLAYLIST_H
@@ -15,6 +31,23 @@ namespace Tomahawk {
* It uses normal PlaylistEntries but also has a mode, a generator, and a list of controls * 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;
applied = other.applied;
}
DynamicPlaylistRevision() {}
};
class DynamicPlaylist : public Playlist class DynamicPlaylist : public Playlist
{ {
Q_OBJECT Q_OBJECT
@@ -22,12 +55,7 @@ class DynamicPlaylist : public Playlist
Q_PROPERTY( GeneratorMode mode WRITE setMode READ mode ) Q_PROPERTY( GeneratorMode mode WRITE setMode READ mode )
Q_PROPERTY( QString type WRITE setType READ type ) Q_PROPERTY( QString type WRITE setType READ type )
public: public:
enum DynamicPlaylistMode {
OnDemand = 0,
StaticPlaylist
};
/// Generate an empty dynamic playlist with default generator /// Generate an empty dynamic playlist with default generator
static Tomahawk::dynplaylist_ptr create( const source_ptr& author, static Tomahawk::dynplaylist_ptr create( const source_ptr& author,
const QString& guid, const QString& guid,
@@ -42,7 +70,7 @@ public:
GeneratorMode mode() const { return m_generator->mode(); } GeneratorMode mode() const { return m_generator->mode(); }
QString type() const { return m_generator->type(); } QString type() const { return m_generator->type(); }
generatorinterface_ptr generator() const { return m_generator; } geninterface_ptr generator() const { return m_generator; }
// <IGNORE hack="true"> // <IGNORE hack="true">
// these need to exist and be public for the json serialization stuff // these need to exist and be public for the json serialization stuff
@@ -55,7 +83,7 @@ public:
} }
void setMode( GeneratorMode mode ) { m_generator->setMode( mode ); } void setMode( GeneratorMode mode ) { m_generator->setMode( mode ); }
void setType( const QString& type ) { /** TODO */; } void setType( const QString& type ) { /** TODO */; }
void setGenerator( const generatorinterface_ptr& gen_ptr ) { m_generator = gen_ptr; } void setGenerator( const geninterface_ptr& gen_ptr ) { m_generator = gen_ptr; }
// </IGNORE> // </IGNORE>
signals: signals:
@@ -112,7 +140,7 @@ private:
bool shared ); bool shared );
private: private:
generatorinterface_ptr m_generator; geninterface_ptr m_generator;
}; };
}; // namespace }; // namespace

View File

@@ -1,4 +1,5 @@
#include "generatorfactory.h" #include "dynamic/generatorfactory.h"
#include "dynamic/generatorinterface.h"
Tomahawk::GeneratorFactory::GeneratorFactory() Tomahawk::GeneratorFactory::GeneratorFactory()
{ {
@@ -12,9 +13,9 @@ Tomahawk::GeneratorFactory::~GeneratorFactory()
generatorinterface_ptr Tomahawk::GeneratorFactory::create ( const QString& type ) generatorinterface_ptr Tomahawk::GeneratorFactory::create ( const QString& type )
{ {
if( !m_factories.contains( type ) ) if( !m_factories.contains( type ) )
return generatorinterface_ptr(); return geninterface_ptr();
return generatorinterface_ptr( m_factories.value( type )->create() ); return geninterface_ptr( m_factories.value( type )->create() );
} }
void Tomahawk::GeneratorFactory::registerFactory ( const QString& type, Tomahawk::GeneratorFactoryInterface* interface ) void Tomahawk::GeneratorFactory::registerFactory ( const QString& type, Tomahawk::GeneratorFactoryInterface* interface )

View File

@@ -4,6 +4,8 @@
#include <QHash> #include <QHash>
#include <QString> #include <QString>
#include "dynamic/generatorinterface.h"
namespace Tomahawk { namespace Tomahawk {
/** /**
@@ -12,7 +14,9 @@ namespace Tomahawk {
class GeneratorFactoryInterface class GeneratorFactoryInterface
{ {
public: public:
GeneratorInterface* create() = 0; GeneratorFactoryInterface() {}
virtual GeneratorInterface* create() = 0;
}; };
/** /**
@@ -21,15 +25,11 @@ public:
class GeneratorFactory class GeneratorFactory
{ {
public: public:
GeneratorFactory(); static geninterface_ptr create( const QString& type );
~GeneratorFactory(); static void registerFactory( const QString& type, GeneratorFactoryInterface* interface );
generatorinterface_ptr create( const QString& type );
void registerFactory( const QString& type, GeneratorFactoryInterface* interface );
private: private:
QHash<QString, GeneratorFactoryInterface*> m_factories; static QHash<QString, GeneratorFactoryInterface*> m_factories;
}; };

View File

@@ -1,7 +1,27 @@
/****************************************************************************************
* 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 #ifndef GENERATOR_INTERFACE_H
#define GENERATOR_INTERFACE_H #define GENERATOR_INTERFACE_H
#include <QtCore/QObject> #include <QtCore/QObject>
#include <QtCore/QSharedPointer>
#include "dynamic/dynamiccontrol.h"
#include <tomahawk/typedefs.h>
namespace Tomahawk { namespace Tomahawk {
@@ -14,7 +34,9 @@ enum GeneratorMode {
* The abstract interface for Dynamic Playlist Generators. Generators have the following features: * The abstract interface for Dynamic Playlist Generators. Generators have the following features:
* - They create new DynamicControls that are appropriate for the generator * - They create new DynamicControls that are appropriate for the generator
* - They expose a list of controls that this generator currently is operating on * - They expose a list of controls that this generator currently is operating on
* - They have a state of OnDemand or Static * - They have a mode of OnDemand or Static
*
* And they generate tracks
*/ */
class GeneratorInterface : public QObject class GeneratorInterface : public QObject
{ {
@@ -24,29 +46,49 @@ class GeneratorInterface : public QObject
Q_ENUMS( GeneratorMode ) Q_ENUMS( GeneratorMode )
public: public:
explicit GeneratorInterface() {} explicit GeneratorInterface( QObject* parent = 0 ) : QObject( parent ) {}
virtual ~GeneratorInterface() {} virtual ~GeneratorInterface() {}
// Can't make it pure otherwise we can't shove it in QVariants :-/ // Can't make it pure otherwise we can't shove it in QVariants :-/
virtual dyncontrol_ptr createControl() const {} // empty QString means use default
virtual dyncontrol_ptr createControl( const QString& type = QString() ) const { return dyncontrol_ptr(); }
/**
* 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 /// The type of this generator
virtual QString type() const { return m_type; } QString type() const { return m_type; }
virtual GeneratorMode mode() const { return m_mode; } GeneratorMode mode() const { return m_mode; }
virtual void setMode( GeneratorMode mode ) { m_mode = mode; } void setMode( GeneratorMode mode ) { m_mode = mode; }
// control functions // control functions
virtual QList< dyncontrol_ptr > controls() const { return m_controls; } QList< dyncontrol_ptr > controls() const { return m_controls; }
virtual void addControl( const dyncontrol_ptr& control ) { m_controls << control; } void addControl( const dyncontrol_ptr& control ) { m_controls << control; }
virtual void clearControls() { m_controls.clear(); } void clearControls() { m_controls.clear(); }
virtual void setControls( const QList< dyncontrol_ptr>& controls ) { m_controls = controls; } void setControls( const QList< dyncontrol_ptr>& controls ) { m_controls = controls; }
private:
QStringList typeSelectors() const { return m_typeSelectors; }
signals:
void generated( const QList< query_ptr>& queries );
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;
}; };
#endif #endif

View File

@@ -312,6 +312,7 @@ Playlist::setNewRevision( const QString& rev,
// << "total entries" << m_entries.size(); // << "total entries" << m_entries.size();
pr.newlist = entries; pr.newlist = entries;
return pr;
} }
void Playlist::resolve() void Playlist::resolve()
@@ -363,7 +364,7 @@ Playlist::addEntries( const QList<query_ptr>& queries, const QString& oldrev )
} }
QList< plentry_ptr > QList< plentry_ptr >
Playlist::newEntries( const QList< plentry_ptr > entries ) Playlist::newEntries( const QList< plentry_ptr >& entries )
{ {
QSet<QString> currentguids; QSet<QString> currentguids;
foreach( plentry_ptr p, m_entries ) foreach( plentry_ptr p, m_entries )

View File

@@ -8,7 +8,6 @@ Query::Query( const QVariant& v )
: m_v( v ) : m_v( v )
, m_solved( false ) , m_solved( false )
{ {
// ensure a QID is present:
QVariantMap m = m_v.toMap(); QVariantMap m = m_v.toMap();
m_artist = m.value( "artist" ).toString(); m_artist = m.value( "artist" ).toString();