mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-31 01:30:02 +02:00
Merge remote branch 'origin' into phonon
This commit is contained in:
@@ -53,6 +53,7 @@ ENDIF(LIBLASTFM_FOUND)
|
||||
|
||||
SET( tomahawkSourcesGui ${tomahawkSourcesGui}
|
||||
sourcetree/sourcesmodel.cpp
|
||||
sourcetree/sourcesproxymodel.cpp
|
||||
sourcetree/sourcetreeitem.cpp
|
||||
sourcetree/sourcetreeitemwidget.cpp
|
||||
sourcetree/sourcetreeview.cpp
|
||||
@@ -97,6 +98,7 @@ ENDIF(LIBLASTFM_FOUND)
|
||||
|
||||
SET( tomahawkHeadersGui ${tomahawkHeadersGui}
|
||||
sourcetree/sourcesmodel.h
|
||||
sourcetree/sourcesproxymodel.h
|
||||
sourcetree/sourcetreeitem.h
|
||||
sourcetree/sourcetreeitemwidget.h
|
||||
sourcetree/sourcetreeview.h
|
||||
@@ -155,7 +157,8 @@ ENDIF( UNIX )
|
||||
|
||||
|
||||
IF(GLOOX_FOUND)
|
||||
ADD_SUBDIRECTORY( xmppbot )
|
||||
SET( tomahawkHeaders ${tomahawkHeaders} xmppbot/xmppbot.h )
|
||||
SET( tomahawkSources ${tomahawkSources} xmppbot/xmppbot.cpp )
|
||||
ENDIF(GLOOX_FOUND)
|
||||
ADD_SUBDIRECTORY( sip )
|
||||
|
||||
@@ -191,12 +194,11 @@ MESSAGE( STATUS "OS_SPECIFIC_LINK_LIBRARIES: ${OS_SPECIFIC_LINK_LIBRARIES}" )
|
||||
|
||||
SET(LINK_LIBRARIES "")
|
||||
IF(LIBLASTFM_FOUND)
|
||||
SET(LINK_LIBRARIES
|
||||
${LINK_LIBRARIES}
|
||||
${LIBLASTFM_LIBRARY}
|
||||
)
|
||||
SET(LINK_LIBRARIES ${LINK_LIBRARIES} ${LIBLASTFM_LIBRARY} )
|
||||
ENDIF(LIBLASTFM_FOUND)
|
||||
|
||||
IF(GLOOX_FOUND)
|
||||
SET(LINK_LIBRARIES ${LINK_LIBRARIES} ${GLOOX_LIBRARIES} )
|
||||
ENDIF(GLOOX_FOUND)
|
||||
|
||||
TARGET_LINK_LIBRARIES( tomahawk
|
||||
${LINK_LIBRARIES}
|
||||
|
@@ -7,4 +7,7 @@
|
||||
#cmakedefine LEOPARD
|
||||
#cmakedefine HAVE_SPARKLE
|
||||
|
||||
#cmakedefine LIBLASTFM_FOUND
|
||||
#cmakedefine GLOOX_FOUND
|
||||
|
||||
#endif // CONFIG_H_IN
|
||||
|
@@ -57,6 +57,7 @@ set( libSources
|
||||
database/databasecommand_playbackhistory.cpp
|
||||
database/databasecommand_setplaylistrevision.cpp
|
||||
database/databasecommand_loadallplaylists.cpp
|
||||
database/databasecommand_loadallsources.cpp
|
||||
database/databasecommand_createplaylist.cpp
|
||||
database/databasecommand_deleteplaylist.cpp
|
||||
database/databasecommand_renameplaylist.cpp
|
||||
@@ -195,6 +196,7 @@ set( libHeaders
|
||||
database/databasecommand_playbackhistory.h
|
||||
database/databasecommand_setplaylistrevision.h
|
||||
database/databasecommand_loadallplaylists.h
|
||||
database/databasecommand_loadallsources.h
|
||||
database/databasecommand_createplaylist.h
|
||||
database/databasecommand_deleteplaylist.h
|
||||
database/databasecommand_renameplaylist.h
|
||||
@@ -296,7 +298,7 @@ set( libUI ${libUI}
|
||||
playlist/infobar/infobar.ui
|
||||
)
|
||||
|
||||
include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ..
|
||||
include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/.. ..
|
||||
${QT_INCLUDE_DIR}
|
||||
${LIBECHONEST_INCLUDE_DIR}
|
||||
${LIBECHONEST_INCLUDE_DIR}/..
|
||||
|
@@ -46,6 +46,7 @@ Database::enqueue( QSharedPointer<DatabaseCommand> lc )
|
||||
if( lc->doesMutates() )
|
||||
{
|
||||
//qDebug() << Q_FUNC_INFO << "RW" << lc->commandname();
|
||||
qDebug() << "Enqueueing command to rw thread:" << lc->commandname();
|
||||
m_workerRW->enqueue( lc );
|
||||
}
|
||||
else
|
||||
|
@@ -17,7 +17,8 @@ DatabaseCommand_CollectionStats::exec( DatabaseImpl* dbi )
|
||||
Q_ASSERT( source()->isLocal() || source()->id() >= 1 );
|
||||
TomahawkSqlQuery query = dbi->newquery();
|
||||
|
||||
if( source()->isLocal() )
|
||||
QVariantMap m;
|
||||
if ( source()->isLocal() )
|
||||
{
|
||||
query.exec( "SELECT count(*), max(mtime), (SELECT guid FROM oplog WHERE source IS NULL ORDER BY id DESC LIMIT 1) "
|
||||
"FROM file "
|
||||
@@ -30,16 +31,18 @@ DatabaseCommand_CollectionStats::exec( DatabaseImpl* dbi )
|
||||
"WHERE source = ?" );
|
||||
query.addBindValue( source()->id() );
|
||||
query.addBindValue( source()->id() );
|
||||
query.exec();
|
||||
}
|
||||
|
||||
query.exec();
|
||||
|
||||
QVariantMap m;
|
||||
if( query.next() )
|
||||
if ( query.next() )
|
||||
{
|
||||
m.insert( "numfiles", query.value( 0 ).toInt() );
|
||||
m.insert( "lastmodified", query.value( 1 ).toInt() );
|
||||
m.insert( "lastop", query.value( 2 ).toString() );
|
||||
|
||||
if ( !source()->isLocal() && !source()->lastOpGuid().isEmpty() )
|
||||
m.insert( "lastop", source()->lastOpGuid() );
|
||||
else
|
||||
m.insert( "lastop", query.value( 2 ).toString() );
|
||||
}
|
||||
|
||||
emit done( m );
|
||||
|
@@ -1,5 +1,5 @@
|
||||
#ifndef DATABASECOMMAND_IMPORTALLPLAYLIST_H
|
||||
#define DATABASECOMMAND_IMPORTALLPLAYLIST_H
|
||||
#ifndef DATABASECOMMAND_LOADALLPLAYLIST_H
|
||||
#define DATABASECOMMAND_LOADALLPLAYLIST_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariantMap>
|
||||
@@ -26,4 +26,4 @@ signals:
|
||||
void done( const QList<Tomahawk::playlist_ptr>& playlists );
|
||||
};
|
||||
|
||||
#endif // DATABASECOMMAND_ADDFILES_H
|
||||
#endif // DATABASECOMMAND_LOADALLPLAYLIST_H
|
||||
|
29
src/libtomahawk/database/databasecommand_loadallsources.cpp
Normal file
29
src/libtomahawk/database/databasecommand_loadallsources.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "databasecommand_loadallsources.h"
|
||||
|
||||
#include <QSqlQuery>
|
||||
|
||||
#include "network/servent.h"
|
||||
#include "source.h"
|
||||
#include "databaseimpl.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
void DatabaseCommand_LoadAllSources::exec( DatabaseImpl* dbi )
|
||||
{
|
||||
TomahawkSqlQuery query = dbi->newquery();
|
||||
|
||||
query.exec( QString( "SELECT id, name, friendlyname "
|
||||
"FROM source" ) );
|
||||
|
||||
QList<source_ptr> sources;
|
||||
while ( query.next() )
|
||||
{
|
||||
source_ptr src( new Source( query.value( 0 ).toUInt(), query.value( 1 ).toString() ) );
|
||||
src->setFriendlyName( query.value( 2 ).toString() );
|
||||
sources << src;
|
||||
}
|
||||
|
||||
emit done( sources );
|
||||
}
|
||||
|
29
src/libtomahawk/database/databasecommand_loadallsources.h
Normal file
29
src/libtomahawk/database/databasecommand_loadallsources.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef DATABASECOMMAND_LOADALLSOURCES_H
|
||||
#define DATABASECOMMAND_LOADALLSOURCES_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariantMap>
|
||||
|
||||
#include "databasecommand.h"
|
||||
#include "typedefs.h"
|
||||
|
||||
#include "dllmacro.h"
|
||||
|
||||
class DLLEXPORT DatabaseCommand_LoadAllSources : public DatabaseCommand
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DatabaseCommand_LoadAllSources( QObject* parent = 0 )
|
||||
: DatabaseCommand( parent )
|
||||
{}
|
||||
|
||||
virtual void exec( DatabaseImpl* );
|
||||
virtual bool doesMutates() const { return false; }
|
||||
virtual QString commandname() const { return "loadallsources"; }
|
||||
|
||||
signals:
|
||||
void done( const QList<Tomahawk::source_ptr>& sources );
|
||||
};
|
||||
|
||||
#endif // DATABASECOMMAND_LOADALLSOURCES_H
|
@@ -16,10 +16,7 @@ DatabaseCommand_loadOps::exec( DatabaseImpl* dbi )
|
||||
).arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) )
|
||||
);
|
||||
query.addBindValue( m_since );
|
||||
if( !query.exec() )
|
||||
{
|
||||
Q_ASSERT(0);
|
||||
}
|
||||
query.exec();
|
||||
|
||||
QString lastguid = m_since;
|
||||
while( query.next() )
|
||||
|
@@ -22,9 +22,9 @@ DatabaseCommand_LogPlayback::postCommitHook()
|
||||
}
|
||||
|
||||
connect( this, SIGNAL( trackPlaying( Tomahawk::query_ptr ) ),
|
||||
source().data(), SIGNAL( playbackStarted( Tomahawk::query_ptr ) ), Qt::QueuedConnection );
|
||||
source().data(), SLOT( onPlaybackStarted( Tomahawk::query_ptr ) ), Qt::QueuedConnection );
|
||||
connect( this, SIGNAL( trackPlayed( Tomahawk::query_ptr ) ),
|
||||
source().data(), SIGNAL( playbackFinished( Tomahawk::query_ptr ) ), Qt::QueuedConnection );
|
||||
source().data(), SLOT( onPlaybackFinished( Tomahawk::query_ptr ) ), Qt::QueuedConnection );
|
||||
|
||||
QVariantMap m;
|
||||
m.insert( "track", m_track );
|
||||
|
@@ -139,7 +139,7 @@ DatabaseCommand_Resolve::exec( DatabaseImpl* lib )
|
||||
s = SourceList::instance()->get( files_query.value( 13 ).toUInt() );
|
||||
if( s.isNull() )
|
||||
{
|
||||
//qDebug() << "Skipping result for offline sourceid:" << files_query.value( 13 ).toUInt();
|
||||
qDebug() << "Skipping result for offline sourceid:" << files_query.value( 13 ).toUInt();
|
||||
// will happen for valid sources which are offline (and thus not in the sourcelist)
|
||||
continue;
|
||||
}
|
||||
|
@@ -16,7 +16,8 @@
|
||||
*/
|
||||
#include "schema.sql.h"
|
||||
|
||||
#define CURRENT_SCHEMA_VERSION 19
|
||||
#define CURRENT_SCHEMA_VERSION 20
|
||||
|
||||
|
||||
DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent )
|
||||
: QObject( (QObject*) parent )
|
||||
@@ -36,6 +37,7 @@ DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent )
|
||||
|
||||
QSqlQuery qry = QSqlQuery( db );
|
||||
|
||||
bool schemaUpdated = false;
|
||||
qry.exec( "SELECT v FROM settings WHERE k='schema_version'" );
|
||||
if ( qry.next() )
|
||||
{
|
||||
@@ -60,18 +62,24 @@ DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent )
|
||||
{
|
||||
db = QSqlDatabase::addDatabase( "QSQLITE", "tomahawk" );
|
||||
db.setDatabaseName( dbname );
|
||||
if( !db.open() ) throw "db moving failed";
|
||||
updateSchema( v );
|
||||
if( !db.open() )
|
||||
throw "db moving failed";
|
||||
|
||||
TomahawkSqlQuery query = newquery();
|
||||
query.exec( "PRAGMA auto_vacuum = FULL" );
|
||||
schemaUpdated = updateSchema( v );
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_ASSERT(0);
|
||||
Q_ASSERT( false );
|
||||
QTimer::singleShot( 0, qApp, SLOT( quit() ) );
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
updateSchema( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
schemaUpdated = updateSchema( 0 );
|
||||
}
|
||||
|
||||
TomahawkSqlQuery query = newquery();
|
||||
@@ -95,15 +103,12 @@ DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent )
|
||||
// in case of unclean shutdown last time:
|
||||
query.exec( "UPDATE source SET isonline = 'false'" );
|
||||
|
||||
m_fuzzyIndex = new FuzzyIndex( *this );
|
||||
m_fuzzyIndex = new FuzzyIndex( *this, schemaUpdated );
|
||||
}
|
||||
|
||||
|
||||
DatabaseImpl::~DatabaseImpl()
|
||||
{
|
||||
m_indexThread.quit();
|
||||
m_indexThread.wait( 5000 );
|
||||
|
||||
delete m_fuzzyIndex;
|
||||
}
|
||||
|
||||
@@ -111,11 +116,8 @@ DatabaseImpl::~DatabaseImpl()
|
||||
void
|
||||
DatabaseImpl::loadIndex()
|
||||
{
|
||||
// load ngram index in the background
|
||||
m_fuzzyIndex->moveToThread( &m_indexThread );
|
||||
connect( &m_indexThread, SIGNAL( started() ), m_fuzzyIndex, SLOT( loadLuceneIndex() ) );
|
||||
connect( m_fuzzyIndex, SIGNAL( indexReady() ), this, SIGNAL( indexReady() ) );
|
||||
m_indexThread.start();
|
||||
connect( m_fuzzyIndex, SIGNAL( indexReady() ), SIGNAL( indexReady() ) );
|
||||
m_fuzzyIndex->loadLuceneIndex();
|
||||
}
|
||||
|
||||
|
||||
@@ -346,6 +348,7 @@ DatabaseImpl::searchTable( const QString& table, const QString& name, uint limit
|
||||
results << resultslist.at( k ).first;
|
||||
}
|
||||
|
||||
// qDebug() << "Returning" << results.count() << "results";
|
||||
return results;
|
||||
}
|
||||
|
||||
|
@@ -74,7 +74,6 @@ private:
|
||||
|
||||
QString m_dbid;
|
||||
|
||||
QThread m_indexThread;
|
||||
FuzzyIndex* m_fuzzyIndex;
|
||||
};
|
||||
|
||||
|
@@ -29,7 +29,7 @@ DatabaseResolver::resolve( const QVariant& v )
|
||||
void
|
||||
DatabaseResolver::gotResults( const Tomahawk::QID qid, QList< Tomahawk::result_ptr> results )
|
||||
{
|
||||
// qDebug() << Q_FUNC_INFO << qid << results.length();
|
||||
qDebug() << Q_FUNC_INFO << qid << results.length();
|
||||
|
||||
Tomahawk::Pipeline::instance()->reportResults( qid, results );
|
||||
}
|
||||
|
@@ -24,10 +24,11 @@ DatabaseWorker::~DatabaseWorker()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << m_outstanding;
|
||||
|
||||
qDebug () << m_commands;
|
||||
if ( m_commands.count() )
|
||||
qDebug() << m_commands;
|
||||
|
||||
quit();
|
||||
wait( 5000 );
|
||||
wait( 60000 );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -16,17 +16,21 @@ using namespace lucene::queryParser;
|
||||
using namespace lucene::search;
|
||||
|
||||
|
||||
FuzzyIndex::FuzzyIndex( DatabaseImpl& db )
|
||||
FuzzyIndex::FuzzyIndex( DatabaseImpl& db, bool wipeIndex )
|
||||
: QObject()
|
||||
, m_db( db )
|
||||
, m_luceneReader( 0 )
|
||||
, m_luceneSearcher( 0 )
|
||||
{
|
||||
QString lucenePath = TomahawkUtils::appDataDir().absoluteFilePath( "tomahawk.lucene" );
|
||||
bool create = !IndexReader::indexExists( lucenePath.toStdString().c_str() );
|
||||
m_luceneDir = FSDirectory::getDirectory( lucenePath.toStdString().c_str(), create );
|
||||
|
||||
QString m_lucenePath = TomahawkUtils::appDataDir().absoluteFilePath( "tomahawk.lucene" );
|
||||
m_luceneDir = FSDirectory::getDirectory( m_lucenePath.toStdString().c_str() );
|
||||
m_analyzer = _CLNEW SimpleAnalyzer();
|
||||
|
||||
if ( wipeIndex )
|
||||
{
|
||||
beginIndexing();
|
||||
endIndexing();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +56,6 @@ FuzzyIndex::beginIndexing()
|
||||
qDebug() << "Deleting old lucene stuff.";
|
||||
m_luceneSearcher->close();
|
||||
m_luceneReader->close();
|
||||
m_luceneReader->unlock( m_luceneDir );
|
||||
delete m_luceneSearcher;
|
||||
delete m_luceneReader;
|
||||
m_luceneSearcher = 0;
|
||||
@@ -83,6 +86,7 @@ FuzzyIndex::appendFields( const QString& table, const QMap< unsigned int, QStrin
|
||||
{
|
||||
try
|
||||
{
|
||||
qDebug() << "Appending to index:" << fields.count();
|
||||
bool create = !IndexReader::indexExists( TomahawkUtils::appDataDir().absoluteFilePath( "tomahawk.lucene" ).toStdString().c_str() );
|
||||
IndexWriter luceneWriter = IndexWriter( m_luceneDir, m_analyzer, create );
|
||||
Document doc;
|
||||
@@ -173,9 +177,12 @@ FuzzyIndex::search( const QString& table, const QString& name )
|
||||
if ( score > 0.05 )
|
||||
{
|
||||
resultsmap.insert( id, score );
|
||||
// qDebug() << "Hitres:" << result << id << score << table << name;
|
||||
// qDebug() << "Hitres:" << result << id << score << table << name;
|
||||
}
|
||||
}
|
||||
|
||||
delete hits;
|
||||
delete qry;
|
||||
}
|
||||
catch( CLuceneError& error )
|
||||
{
|
||||
|
@@ -35,7 +35,7 @@ class FuzzyIndex : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FuzzyIndex( DatabaseImpl& db );
|
||||
explicit FuzzyIndex( DatabaseImpl& db, bool wipeIndex = false );
|
||||
~FuzzyIndex();
|
||||
|
||||
void beginIndexing();
|
||||
@@ -53,6 +53,7 @@ public slots:
|
||||
private:
|
||||
DatabaseImpl& m_db;
|
||||
QMutex m_mutex;
|
||||
QString m_lucenePath;
|
||||
|
||||
lucene::analysis::SimpleAnalyzer* m_analyzer;
|
||||
lucene::store::Directory* m_luceneDir;
|
||||
|
@@ -250,4 +250,4 @@ CREATE TABLE IF NOT EXISTS settings (
|
||||
v TEXT NOT NULL DEFAULT ''
|
||||
);
|
||||
|
||||
INSERT INTO settings(k,v) VALUES('schema_version', '19');
|
||||
INSERT INTO settings(k,v) VALUES('schema_version', '20');
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
This file was automatically generated from schema.sql on Thu Feb 3 08:21:21 EST 2011.
|
||||
This file was automatically generated from ./schema.sql on Wed Feb 23 12:39:07 CET 2011.
|
||||
*/
|
||||
|
||||
static const char * tomahawk_schema_sql =
|
||||
@@ -165,7 +165,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', '19');"
|
||||
"INSERT INTO settings(k,v) VALUES('schema_version', '20');"
|
||||
;
|
||||
|
||||
const char * get_tomahawk_sql()
|
||||
|
@@ -8,7 +8,7 @@
|
||||
#define BLOCKSIZE 4096
|
||||
|
||||
|
||||
BufferIODevice::BufferIODevice( unsigned int size, QObject *parent )
|
||||
BufferIODevice::BufferIODevice( unsigned int size, QObject* parent )
|
||||
: QIODevice( parent )
|
||||
, m_size( size )
|
||||
, m_received( 0 )
|
||||
@@ -125,7 +125,8 @@ BufferIODevice::readData( char* data, qint64 maxSize )
|
||||
}
|
||||
|
||||
|
||||
qint64 BufferIODevice::writeData( const char* data, qint64 maxSize )
|
||||
qint64
|
||||
BufferIODevice::writeData( const char* data, qint64 maxSize )
|
||||
{
|
||||
// call addData instead
|
||||
Q_ASSERT( false );
|
||||
@@ -133,14 +134,16 @@ qint64 BufferIODevice::writeData( const char* data, qint64 maxSize )
|
||||
}
|
||||
|
||||
|
||||
qint64 BufferIODevice::size() const
|
||||
qint64
|
||||
BufferIODevice::size() const
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << m_size;
|
||||
return m_size;
|
||||
}
|
||||
|
||||
|
||||
bool BufferIODevice::atEnd() const
|
||||
bool
|
||||
BufferIODevice::atEnd() const
|
||||
{
|
||||
// qDebug() << Q_FUNC_INFO << ( m_size <= m_pos );
|
||||
return ( m_size <= m_pos );
|
||||
|
@@ -11,7 +11,7 @@ class BufferIODevice : public QIODevice
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit BufferIODevice( unsigned int size = 0, QObject *parent = 0 );
|
||||
explicit BufferIODevice( unsigned int size = 0, QObject* parent = 0 );
|
||||
|
||||
virtual bool open( OpenMode mode );
|
||||
virtual void close();
|
||||
|
@@ -1,6 +1,5 @@
|
||||
#include "controlconnection.h"
|
||||
|
||||
#include "remotecollection.h"
|
||||
#include "filetransferconnection.h"
|
||||
#include "database/database.h"
|
||||
#include "database/databasecommand_collectionstats.h"
|
||||
@@ -33,6 +32,9 @@ ControlConnection::~ControlConnection()
|
||||
{
|
||||
qDebug() << "DTOR controlconnection";
|
||||
|
||||
if ( !m_source.isNull() )
|
||||
m_source->setOffline();
|
||||
|
||||
delete m_pingtimer;
|
||||
m_servent->unregisterControlConnection(this);
|
||||
if( m_dbsyncconn ) m_dbsyncconn->deleteLater();
|
||||
@@ -53,29 +55,28 @@ void
|
||||
ControlConnection::setup()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << id() << name();
|
||||
// setup source and remote collection for this peer
|
||||
m_source = source_ptr( new Source( id(), this ) );
|
||||
|
||||
if( Servent::isIPWhitelisted( m_sock->peerAddress() ) )
|
||||
QString friendlyName;
|
||||
if ( Servent::isIPWhitelisted( m_sock->peerAddress() ) )
|
||||
{
|
||||
// FIXME TODO blocking DNS lookup if LAN, slow/fails on windows?
|
||||
QHostInfo i = QHostInfo::fromName( m_sock->peerAddress().toString() );
|
||||
if( i.hostName().length() )
|
||||
{
|
||||
m_source->setFriendlyName( i.hostName() );
|
||||
}
|
||||
friendlyName = i.hostName();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_source->setFriendlyName( QString( "%1" ).arg( name() ) );
|
||||
}
|
||||
friendlyName = name();
|
||||
|
||||
// setup source and remote collection for this peer
|
||||
m_source = SourceList::instance()->get( id(), friendlyName );
|
||||
m_source->setControlConnection( this );
|
||||
|
||||
// delay setting up collection/etc until source is synced.
|
||||
// we need it DB synced so it has an ID + exists in DB.
|
||||
connect( m_source.data(), SIGNAL( syncedWithDatabase() ),
|
||||
SLOT( registerSource() ), Qt::QueuedConnection );
|
||||
|
||||
m_source->doDBSync();
|
||||
m_source->setOnline();
|
||||
|
||||
m_pingtimer = new QTimer;
|
||||
m_pingtimer->setInterval( 5000 );
|
||||
@@ -94,10 +95,6 @@ ControlConnection::registerSource()
|
||||
Q_ASSERT( source == m_source.data() );
|
||||
// .. but we'll use the shared pointer we've already made:
|
||||
|
||||
collection_ptr coll( new RemoteCollection( m_source ) );
|
||||
m_source->addCollection( coll );
|
||||
SourceList::instance()->add( m_source );
|
||||
|
||||
m_registered = true;
|
||||
setupDbSyncConnection();
|
||||
m_servent->registerControlConnection( this );
|
||||
@@ -234,7 +231,7 @@ ControlConnection::onPingTimer()
|
||||
if ( m_pingtimer_mark.elapsed() >= TCP_TIMEOUT * 1000 )
|
||||
{
|
||||
qDebug() << "Timeout reached! Shutting down connection to" << m_source->friendlyName();
|
||||
shutdown( false );
|
||||
shutdown( true );
|
||||
}
|
||||
|
||||
sendMsg( Msg::factory( QByteArray(), Msg::PING ) );
|
||||
|
@@ -34,10 +34,9 @@ DBSyncConnection::DBSyncConnection( Servent* s, source_ptr src )
|
||||
, m_source( src )
|
||||
, m_state( UNKNOWN )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << thread();
|
||||
connect( this, SIGNAL( stateChanged( DBSyncConnection::State, DBSyncConnection::State, QString ) ),
|
||||
m_source.data(), SIGNAL( loadingStateChanged(DBSyncConnection::State, DBSyncConnection::State, QString ) )
|
||||
);
|
||||
qDebug() << Q_FUNC_INFO << src->id() << thread();
|
||||
connect( this, SIGNAL( stateChanged( DBSyncConnection::State, DBSyncConnection::State, QString ) ),
|
||||
m_source.data(), SLOT( onStateChanged( DBSyncConnection::State, DBSyncConnection::State, QString ) ) );
|
||||
|
||||
m_timer.setInterval( IDLE_TIMEOUT );
|
||||
connect( &m_timer, SIGNAL( timeout() ), SLOT( idleTimeout() ) );
|
||||
@@ -71,7 +70,7 @@ DBSyncConnection::changeState( State newstate )
|
||||
qDebug() << "DBSYNC State changed from" << s << "to" << newstate;
|
||||
emit stateChanged( newstate, s, "" );
|
||||
|
||||
if( newstate == SYNCED )
|
||||
if ( newstate == SYNCED )
|
||||
{
|
||||
qDebug() << "Synced :)";
|
||||
}
|
||||
@@ -82,7 +81,7 @@ void
|
||||
DBSyncConnection::setup()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
setId( QString("DBSyncConnection/%1").arg(socket()->peerAddress().toString()) );
|
||||
setId( QString( "DBSyncConnection/%1" ).arg( socket()->peerAddress().toString() ) );
|
||||
check();
|
||||
}
|
||||
|
||||
@@ -93,7 +92,8 @@ DBSyncConnection::trigger()
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
// if we're still setting up the connection, do nothing - we sync on first connect anyway:
|
||||
if( !this->isRunning() ) return;
|
||||
if ( !this->isRunning() )
|
||||
return;
|
||||
|
||||
QMetaObject::invokeMethod( this, "sendMsg", Qt::QueuedConnection,
|
||||
Q_ARG( msg_ptr,
|
||||
@@ -105,8 +105,8 @@ DBSyncConnection::trigger()
|
||||
void
|
||||
DBSyncConnection::check()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if( m_state != UNKNOWN && m_state != SYNCED )
|
||||
qDebug() << Q_FUNC_INFO << m_source->id();
|
||||
if ( m_state != UNKNOWN && m_state != SYNCED )
|
||||
{
|
||||
qDebug() << "Syncing in progress already.";
|
||||
return;
|
||||
@@ -115,20 +115,20 @@ DBSyncConnection::check()
|
||||
m_themcache.clear();
|
||||
m_us.clear();
|
||||
|
||||
changeState(CHECKING);
|
||||
changeState( CHECKING );
|
||||
|
||||
// load last-modified etc data for our collection and theirs from our DB:
|
||||
DatabaseCommand_CollectionStats * cmd_us =
|
||||
DatabaseCommand_CollectionStats* cmd_us =
|
||||
new DatabaseCommand_CollectionStats( SourceList::instance()->getLocal() );
|
||||
|
||||
DatabaseCommand_CollectionStats * cmd_them =
|
||||
DatabaseCommand_CollectionStats* cmd_them =
|
||||
new DatabaseCommand_CollectionStats( m_source );
|
||||
|
||||
connect( cmd_us, SIGNAL( done(const QVariantMap&) ),
|
||||
this, SLOT( gotUs(const QVariantMap&) ) );
|
||||
connect( cmd_us, SIGNAL( done( QVariantMap ) ),
|
||||
SLOT( gotUs( QVariantMap ) ) );
|
||||
|
||||
connect( cmd_them, SIGNAL( done(const QVariantMap&) ),
|
||||
this, SLOT( gotThemCache(const QVariantMap&) ) );
|
||||
connect( cmd_them, SIGNAL( done( QVariantMap ) ),
|
||||
SLOT( gotThemCache( QVariantMap ) ) );
|
||||
|
||||
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>(cmd_us) );
|
||||
@@ -145,7 +145,8 @@ void
|
||||
DBSyncConnection::gotUs( const QVariantMap& m )
|
||||
{
|
||||
m_us = m;
|
||||
if( !m_uscache.empty() ) sendOps();
|
||||
if ( !m_uscache.empty() )
|
||||
sendOps();
|
||||
}
|
||||
|
||||
|
||||
@@ -154,7 +155,7 @@ void
|
||||
DBSyncConnection::gotThemCache( const QVariantMap& m )
|
||||
{
|
||||
m_themcache = m;
|
||||
changeState(FETCHING);
|
||||
changeState( FETCHING );
|
||||
|
||||
qDebug() << "Sending a FETCHOPS cmd since:" << m_themcache.value( "lastop" ).toString();
|
||||
|
||||
@@ -170,20 +171,21 @@ DBSyncConnection::handleMsg( msg_ptr msg )
|
||||
{
|
||||
Q_ASSERT( !msg->is( Msg::COMPRESSED ) );
|
||||
|
||||
if( m_state == FETCHING ) changeState(PARSING);
|
||||
if ( m_state == FETCHING )
|
||||
changeState( PARSING );
|
||||
|
||||
// "everything is synced" indicated by non-json msg containing "ok":
|
||||
if( !msg->is( Msg::JSON ) &&
|
||||
msg->is( Msg::DBOP ) &&
|
||||
msg->payload() == "ok" )
|
||||
if ( !msg->is( Msg::JSON ) &&
|
||||
msg->is( Msg::DBOP ) &&
|
||||
msg->payload() == "ok" )
|
||||
{
|
||||
qDebug() << "No ops to apply, we are synced.";
|
||||
changeState( SYNCED );
|
||||
// calc the collection stats, to updates the "X tracks" in the sidebar etc
|
||||
// this is done automatically if you run a dbcmd to add files.
|
||||
DatabaseCommand_CollectionStats* cmd = new DatabaseCommand_CollectionStats( m_source );
|
||||
connect( cmd, SIGNAL( done( const QVariantMap & ) ),
|
||||
m_source.data(), SLOT( setStats( const QVariantMap& ) ), Qt::QueuedConnection );
|
||||
connect( cmd, SIGNAL( done( const QVariantMap & ) ),
|
||||
m_source.data(), SLOT( setStats( const QVariantMap& ) ), Qt::QueuedConnection );
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>(cmd) );
|
||||
return;
|
||||
}
|
||||
@@ -191,7 +193,7 @@ DBSyncConnection::handleMsg( msg_ptr msg )
|
||||
Q_ASSERT( msg->is( Msg::JSON ) );
|
||||
|
||||
QVariantMap m = msg->json().toMap();
|
||||
if( m.empty() )
|
||||
if ( m.empty() )
|
||||
{
|
||||
qDebug() << "Failed to parse msg in dbsync";
|
||||
Q_ASSERT( false );
|
||||
@@ -199,45 +201,49 @@ DBSyncConnection::handleMsg( msg_ptr msg )
|
||||
}
|
||||
|
||||
// a db sync op msg
|
||||
if( msg->is( Msg::DBOP ) )
|
||||
if ( msg->is( Msg::DBOP ) )
|
||||
{
|
||||
DatabaseCommand *cmd = DatabaseCommand::factory( m, m_source );
|
||||
DatabaseCommand* cmd = DatabaseCommand::factory( m, m_source );
|
||||
if ( !cmd )
|
||||
{
|
||||
qDebug() << "UNKNOWN DBOP CMD";
|
||||
|
||||
if( !msg->is( Msg::FRAGMENT ) ) // last msg in this batch
|
||||
if ( !msg->is( Msg::FRAGMENT ) ) // last msg in this batch
|
||||
lastOpApplied();
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "APPLYING CMD" << cmd->commandname() << cmd->guid();
|
||||
|
||||
if( !msg->is( Msg::FRAGMENT ) ) // last msg in this batch
|
||||
if ( !msg->is( Msg::FRAGMENT ) ) // last msg in this batch
|
||||
{
|
||||
changeState( SAVING ); // just DB work left to complete
|
||||
connect( cmd, SIGNAL( finished() ), this, SLOT( lastOpApplied() ) );
|
||||
connect( cmd, SIGNAL( finished() ), SLOT( lastOpApplied() ) );
|
||||
}
|
||||
|
||||
if ( !cmd->singletonCmd() )
|
||||
m_source->setLastOpGuid( cmd->guid() );
|
||||
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if( m.value( "method" ).toString() == "fetchops" )
|
||||
if ( m.value( "method" ).toString() == "fetchops" )
|
||||
{
|
||||
m_uscache = m;
|
||||
if( !m_us.empty() ) sendOps();
|
||||
if ( !m_us.empty() )
|
||||
sendOps();
|
||||
return;
|
||||
}
|
||||
|
||||
if( m.value( "method" ).toString() == "trigger" )
|
||||
if ( m.value( "method" ).toString() == "trigger" )
|
||||
{
|
||||
qDebug() << "Got trigger msg on dbsyncconnection, checking for new stuff.";
|
||||
check();
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << Q_FUNC_INFO << "Unhandled msg: " << msg->payload();
|
||||
qDebug() << Q_FUNC_INFO << "Unhandled msg:" << msg->payload();
|
||||
Q_ASSERT( false );
|
||||
}
|
||||
|
||||
@@ -246,8 +252,8 @@ void
|
||||
DBSyncConnection::lastOpApplied()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
changeState(SYNCED);
|
||||
// check again, until peer reponds we have no new ops to process
|
||||
changeState( SYNCED );
|
||||
// check again, until peer responds we have no new ops to process
|
||||
check();
|
||||
}
|
||||
|
||||
@@ -263,7 +269,7 @@ DBSyncConnection::sendOps()
|
||||
|
||||
DatabaseCommand_loadOps* cmd = new DatabaseCommand_loadOps( src, m_uscache.value( "lastop" ).toString() );
|
||||
connect( cmd, SIGNAL( done( QString, QString, QList< dbop_ptr > ) ),
|
||||
this, SLOT( sendOpsData( QString, QString, QList< dbop_ptr > ) ) );
|
||||
SLOT( sendOpsData( QString, QString, QList< dbop_ptr > ) ) );
|
||||
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||
}
|
||||
@@ -272,13 +278,12 @@ DBSyncConnection::sendOps()
|
||||
void
|
||||
DBSyncConnection::sendOpsData( QString sinceguid, QString lastguid, QList< dbop_ptr > ops )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << sinceguid << lastguid << "Num ops to send:" << ops.length();
|
||||
|
||||
if ( m_lastSentOp == lastguid )
|
||||
ops.clear();
|
||||
|
||||
qDebug() << Q_FUNC_INFO << sinceguid << lastguid << "Num ops to send:" << ops.length();
|
||||
m_lastSentOp = lastguid;
|
||||
if( ops.length() == 0 )
|
||||
if ( ops.length() == 0 )
|
||||
{
|
||||
sendMsg( Msg::factory( "ok", Msg::DBOP ) );
|
||||
return;
|
||||
@@ -289,12 +294,12 @@ DBSyncConnection::sendOpsData( QString sinceguid, QString lastguid, QList< dbop_
|
||||
{
|
||||
quint8 flags = Msg::JSON | Msg::DBOP;
|
||||
|
||||
if( ops.at(i)->compressed )
|
||||
if ( ops.at( i )->compressed )
|
||||
flags |= Msg::COMPRESSED;
|
||||
if( i != ops.length()-1 )
|
||||
if ( i != ops.length() - 1 )
|
||||
flags |= Msg::FRAGMENT;
|
||||
|
||||
sendMsg( Msg::factory( ops.at(i)->payload, flags ) );
|
||||
sendMsg( Msg::factory( ops.at( i )->payload, flags ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -711,7 +711,8 @@ Servent::triggerDBSync()
|
||||
if( src.isNull() || src->isLocal() )
|
||||
continue;
|
||||
|
||||
src->controlConnection()->dbSyncConnection()->trigger();
|
||||
if ( src->controlConnection() ) // source online?
|
||||
src->controlConnection()->dbSyncConnection()->trigger();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -139,14 +139,14 @@ Pipeline::reportResults( QID qid, const QList< result_ptr >& results )
|
||||
|
||||
if ( !m_qids.contains( qid ) )
|
||||
{
|
||||
qDebug() << "reportResults called for unknown QID";
|
||||
qDebug() << "reportResults called for unknown QID" << qid;
|
||||
Q_ASSERT( false );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !m_qidsState.contains( qid ) )
|
||||
{
|
||||
qDebug() << "reportResults called for unknown QID-state";
|
||||
qDebug() << "reportResults called for unknown QID-state" << qid;
|
||||
Q_ASSERT( false );
|
||||
return;
|
||||
}
|
||||
|
@@ -57,6 +57,9 @@ PlaylistItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& opti
|
||||
if ( item->query()->results().count() )
|
||||
painter->setOpacity( item->query()->results().at( 0 )->score() );
|
||||
else
|
||||
painter->setOpacity( 0.0 );
|
||||
|
||||
if ( painter->opacity() < 0.3 )
|
||||
painter->setOpacity( 0.3 );
|
||||
|
||||
if ( item->isPlaying() )
|
||||
|
@@ -104,28 +104,18 @@ PlItem::setupItem( const Tomahawk::query_ptr& query, PlItem* parent, int row )
|
||||
toberemoved = false;
|
||||
m_query = query;
|
||||
if ( query->numResults() )
|
||||
onResultsAdded( query->results() );
|
||||
{
|
||||
emit dataChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
connect( query.data(), SIGNAL( resultsAdded( QList<Tomahawk::result_ptr> ) ),
|
||||
SLOT( onResultsAdded( QList<Tomahawk::result_ptr> ) ), Qt::DirectConnection );
|
||||
SIGNAL( dataChanged() ) );
|
||||
|
||||
connect( query.data(), SIGNAL( resultsRemoved( Tomahawk::result_ptr ) ),
|
||||
SLOT( onResultsRemoved( Tomahawk::result_ptr ) ), Qt::DirectConnection );
|
||||
SIGNAL( dataChanged() ) );
|
||||
|
||||
connect( query.data(), SIGNAL( resultsChanged() ),
|
||||
SIGNAL( dataChanged() ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlItem::onResultsAdded( const QList<Tomahawk::result_ptr>& results )
|
||||
{
|
||||
// qDebug() << "Found results for playlist item:" << this;
|
||||
emit dataChanged();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlItem::onResultsRemoved( const Tomahawk::result_ptr& result )
|
||||
{
|
||||
emit dataChanged();
|
||||
}
|
||||
|
@@ -41,10 +41,6 @@ public:
|
||||
signals:
|
||||
void dataChanged();
|
||||
|
||||
private slots:
|
||||
void onResultsAdded( const QList<Tomahawk::result_ptr>& result );
|
||||
void onResultsRemoved( const Tomahawk::result_ptr& result );
|
||||
|
||||
private:
|
||||
void setupItem( const Tomahawk::query_ptr& query, PlItem* parent, int row = -1 );
|
||||
|
||||
|
@@ -28,14 +28,14 @@ PluginAPI::reportResults( const QString& qid, const QList<QVariantMap>& vresults
|
||||
void
|
||||
PluginAPI::addSource( source_ptr s )
|
||||
{
|
||||
SourceList::instance()->add( s );
|
||||
// SourceList::instance()->add( s );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PluginAPI::removeSource( source_ptr s )
|
||||
{
|
||||
SourceList::instance()->remove( s );
|
||||
// SourceList::instance()->remove( s );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -13,7 +13,7 @@ using namespace Tomahawk;
|
||||
query_ptr
|
||||
Query::get( const QVariant& v, bool autoResolve )
|
||||
{
|
||||
query_ptr q = query_ptr( new Query( v ) );
|
||||
query_ptr q = query_ptr( new Query( v, autoResolve ) );
|
||||
|
||||
if ( autoResolve )
|
||||
Pipeline::instance()->resolve( q );
|
||||
@@ -21,7 +21,7 @@ Query::get( const QVariant& v, bool autoResolve )
|
||||
}
|
||||
|
||||
|
||||
Query::Query( const QVariant& v )
|
||||
Query::Query( const QVariant& v, bool autoResolve )
|
||||
: m_v( v )
|
||||
, m_solved( false )
|
||||
{
|
||||
@@ -33,8 +33,8 @@ Query::Query( const QVariant& v )
|
||||
|
||||
m_qid = m.value( "qid" ).toString();
|
||||
|
||||
connect( SourceList::instance(), SIGNAL( sourceAdded( Tomahawk::source_ptr ) ), SLOT( refreshResults() ), Qt::QueuedConnection );
|
||||
connect( Database::instance(), SIGNAL( indexReady() ), SLOT( refreshResults() ), Qt::QueuedConnection );
|
||||
if ( autoResolve )
|
||||
connect( Database::instance(), SIGNAL( indexReady() ), SLOT( refreshResults() ), Qt::QueuedConnection );
|
||||
}
|
||||
|
||||
|
||||
@@ -50,17 +50,12 @@ Query::addResults( const QList< Tomahawk::result_ptr >& newresults )
|
||||
// hook up signals, and check solved status
|
||||
foreach( const result_ptr& rp, newresults )
|
||||
{
|
||||
connect( rp.data(), SIGNAL( becomingUnavailable() ), SLOT( resultUnavailable() ) );
|
||||
if( !m_solved && rp->score() > 0.99 )
|
||||
{
|
||||
m_solved = true;
|
||||
becameSolved = true;
|
||||
}
|
||||
connect( rp.data(), SIGNAL( statusChanged() ), SLOT( onResultStatusChanged() ) );
|
||||
}
|
||||
}
|
||||
|
||||
emit resultsAdded( newresults );
|
||||
if( becameSolved )
|
||||
emit solvedStateChanged( true );
|
||||
checkResults();
|
||||
}
|
||||
|
||||
|
||||
@@ -72,28 +67,12 @@ Query::refreshResults()
|
||||
|
||||
|
||||
void
|
||||
Query::resultUnavailable()
|
||||
Query::onResultStatusChanged()
|
||||
{
|
||||
Result* result = (Result*) sender();
|
||||
Q_ASSERT( result );
|
||||
qStableSort( m_results.begin(), m_results.end(), Query::resultSorter );
|
||||
checkResults();
|
||||
|
||||
for ( int i = 0; i < m_results.length(); ++i )
|
||||
{
|
||||
if ( m_results.value( i ).data() == result )
|
||||
{
|
||||
result_ptr r = m_results.value( i );
|
||||
m_results.removeAt( i );
|
||||
|
||||
emit resultsRemoved( r );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_results.isEmpty() ) // FIXME proper score checking
|
||||
{
|
||||
m_solved = false;
|
||||
emit solvedStateChanged( false );
|
||||
}
|
||||
emit resultsChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -104,10 +83,9 @@ Query::removeResult( const Tomahawk::result_ptr& result )
|
||||
QMutexLocker lock( &m_mut );
|
||||
m_results.removeAll( result );
|
||||
}
|
||||
emit resultsRemoved( result );
|
||||
|
||||
if ( m_results.isEmpty() ) // FIXME proper score checking
|
||||
emit solvedStateChanged( false );
|
||||
emit resultsRemoved( result );
|
||||
checkResults();
|
||||
}
|
||||
|
||||
|
||||
@@ -157,3 +135,43 @@ Query::resultSorter( const result_ptr& left, const result_ptr& right )
|
||||
return left->score() > right->score();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Query::clearResults()
|
||||
{
|
||||
foreach( const result_ptr& rp, m_results )
|
||||
{
|
||||
removeResult( rp );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Query::checkResults()
|
||||
{
|
||||
bool becameSolved = false;
|
||||
bool becameUnsolved = true;
|
||||
|
||||
// hook up signals, and check solved status
|
||||
foreach( const result_ptr& rp, m_results )
|
||||
{
|
||||
if ( !m_solved && rp->score() > 0.99 )
|
||||
{
|
||||
m_solved = true;
|
||||
becameSolved = true;
|
||||
}
|
||||
if ( rp->score() > 0.99 )
|
||||
{
|
||||
becameUnsolved = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_solved && becameUnsolved )
|
||||
{
|
||||
m_solved = false;
|
||||
emit solvedStateChanged( true );
|
||||
}
|
||||
|
||||
if( becameSolved )
|
||||
emit solvedStateChanged( true );
|
||||
}
|
||||
|
@@ -20,7 +20,7 @@ Q_OBJECT
|
||||
|
||||
public:
|
||||
static query_ptr get( const QVariant& v, bool autoResolve = true );
|
||||
explicit Query( const QVariant& v );
|
||||
explicit Query( const QVariant& v, bool autoResolve );
|
||||
|
||||
QVariant toVariant() const { return m_v; }
|
||||
|
||||
@@ -55,6 +55,7 @@ signals:
|
||||
void resultsAdded( const QList<Tomahawk::result_ptr>& );
|
||||
void resultsRemoved( const Tomahawk::result_ptr& );
|
||||
|
||||
void resultsChanged();
|
||||
void solvedStateChanged( bool state );
|
||||
void resolvingFinished( bool hasResults );
|
||||
|
||||
@@ -66,10 +67,13 @@ public slots:
|
||||
void onResolvingFinished();
|
||||
|
||||
private slots:
|
||||
void resultUnavailable();
|
||||
void onResultStatusChanged();
|
||||
void refreshResults();
|
||||
|
||||
private:
|
||||
void clearResults();
|
||||
void checkResults();
|
||||
|
||||
mutable QMutex m_mut;
|
||||
mutable QVariant m_v;
|
||||
QList< Tomahawk::result_ptr > m_results;
|
||||
|
@@ -25,15 +25,23 @@ Result::Result( const QVariant& v, const collection_ptr& collection )
|
||||
m_size = m.value( "size" ).toUInt();
|
||||
m_albumpos = m.value( "albumpos" ).toUInt();
|
||||
m_modtime = m.value( "mtime" ).toUInt();
|
||||
m_score = m.value( "score" ).toFloat();
|
||||
m_year = 0;
|
||||
|
||||
m_id = m.value( "id" ).toUInt();
|
||||
|
||||
if ( !m_collection.isNull() )
|
||||
connect( m_collection->source().data(), SIGNAL( offline() ), SIGNAL( becomingUnavailable() ), Qt::QueuedConnection );
|
||||
{
|
||||
connect( m_collection->source().data(), SIGNAL( online() ), SLOT( onOnline() ), Qt::QueuedConnection );
|
||||
connect( m_collection->source().data(), SIGNAL( offline() ), SLOT( onOffline() ), Qt::QueuedConnection );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Result::~Result()
|
||||
{
|
||||
}
|
||||
|
||||
Result::~Result() {}
|
||||
|
||||
artist_ptr
|
||||
Result::artist() const
|
||||
@@ -41,22 +49,30 @@ Result::artist() const
|
||||
return m_artist;
|
||||
}
|
||||
|
||||
|
||||
album_ptr
|
||||
Result::album() const
|
||||
{
|
||||
return m_album;
|
||||
}
|
||||
|
||||
|
||||
collection_ptr
|
||||
Result::collection() const
|
||||
{
|
||||
return m_collection;
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
Result::score() const
|
||||
{
|
||||
return m_v.toMap().value( "score", 0.0 ).toFloat();
|
||||
if ( collection()->source()->isOnline() )
|
||||
{
|
||||
return m_score;
|
||||
}
|
||||
else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +84,7 @@ Result::id() const
|
||||
m_rid = m_v.toMap().value( "sid" ).toString();
|
||||
}
|
||||
return m_rid;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
@@ -94,3 +110,19 @@ Result::updateAttributes()
|
||||
m_year = m_attributes.value( "releaseyear" ).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Result::onOnline()
|
||||
{
|
||||
// qDebug() << Q_FUNC_INFO << toString();
|
||||
emit statusChanged();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Result::onOffline()
|
||||
{
|
||||
// qDebug() << Q_FUNC_INFO << toString();
|
||||
emit statusChanged();
|
||||
}
|
||||
|
@@ -30,7 +30,7 @@ public:
|
||||
RID id() const;
|
||||
collection_ptr collection() const;
|
||||
Tomahawk::artist_ptr artist() const;
|
||||
Tomahawk::album_ptr album() const;
|
||||
Tomahawk::album_ptr album() const;
|
||||
QString track() const { return m_track; }
|
||||
QString url() const { return m_url; }
|
||||
QString mimetype() const { return m_mimetype; }
|
||||
@@ -48,8 +48,12 @@ public:
|
||||
unsigned int dbid() const { return m_id; }
|
||||
|
||||
signals:
|
||||
// emitted when the collection this result comes from is going offline:
|
||||
void becomingUnavailable();
|
||||
// emitted when the collection this result comes from is going offline/online:
|
||||
void statusChanged();
|
||||
|
||||
private slots:
|
||||
void onOffline();
|
||||
void onOnline();
|
||||
|
||||
private:
|
||||
void updateAttributes();
|
||||
@@ -70,6 +74,7 @@ private:
|
||||
unsigned int m_albumpos;
|
||||
unsigned int m_modtime;
|
||||
int m_year;
|
||||
float m_score;
|
||||
|
||||
QVariantMap m_attributes;
|
||||
|
||||
|
@@ -6,43 +6,42 @@
|
||||
#include "network/controlconnection.h"
|
||||
#include "database/databasecommand_addsource.h"
|
||||
#include "database/databasecommand_sourceoffline.h"
|
||||
#include "database/databasecommand_logplayback.h"
|
||||
#include "database/database.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
Source::Source( const QString &username, ControlConnection* cc )
|
||||
|
||||
Source::Source( int id, const QString &username )
|
||||
: QObject()
|
||||
, m_isLocal( false )
|
||||
, m_online( false )
|
||||
, m_username( username )
|
||||
, m_id( 0 )
|
||||
, m_cc( cc )
|
||||
, m_ftc( 0 )
|
||||
{
|
||||
// source for local machine doesn't have a controlconnection. this is normal.
|
||||
if ( cc )
|
||||
connect( cc, SIGNAL( finished() ), SLOT( remove() ), Qt::QueuedConnection );
|
||||
}
|
||||
|
||||
|
||||
Source::Source( const QString &username )
|
||||
: QObject()
|
||||
, m_isLocal( true )
|
||||
, m_online( false )
|
||||
, m_username( username )
|
||||
, m_id( 0 )
|
||||
, m_id( id )
|
||||
, m_cc( 0 )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
if ( id == 0 )
|
||||
{
|
||||
m_isLocal = true;
|
||||
m_online = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Source::~Source()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << friendlyName();
|
||||
}
|
||||
|
||||
/* DatabaseCommand_SourceOffline* cmd = new DatabaseCommand_SourceOffline( id() );
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>(cmd) );*/
|
||||
|
||||
void
|
||||
Source::setControlConnection( ControlConnection* cc )
|
||||
{
|
||||
m_cc = cc;
|
||||
if ( cc )
|
||||
connect( cc, SIGNAL( finished() ), SLOT( remove() ), Qt::QueuedConnection );
|
||||
}
|
||||
|
||||
|
||||
@@ -57,17 +56,6 @@ Source::collection() const
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Source::doDBSync()
|
||||
{
|
||||
// ensure username is in the database
|
||||
DatabaseCommand_addSource* cmd = new DatabaseCommand_addSource( m_username, m_friendlyname );
|
||||
connect( cmd, SIGNAL( done( unsigned int, QString ) ),
|
||||
SLOT( dbLoaded( unsigned int, const QString& ) ) );
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>(cmd) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Source::setStats( const QVariantMap& m )
|
||||
{
|
||||
@@ -81,10 +69,7 @@ Source::remove()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
m_cc = 0;
|
||||
emit offline();
|
||||
m_collections.clear();
|
||||
SourceList::instance()->remove( this );
|
||||
setOffline();
|
||||
}
|
||||
|
||||
|
||||
@@ -102,7 +87,7 @@ Source::friendlyName() const
|
||||
|
||||
|
||||
void
|
||||
Source::addCollection( collection_ptr c )
|
||||
Source::addCollection( const collection_ptr& c )
|
||||
{
|
||||
Q_ASSERT( m_collections.length() == 0 ); // only 1 source supported atm
|
||||
m_collections.append( c );
|
||||
@@ -111,7 +96,7 @@ Source::addCollection( collection_ptr c )
|
||||
|
||||
|
||||
void
|
||||
Source::removeCollection( collection_ptr c )
|
||||
Source::removeCollection( const collection_ptr& c )
|
||||
{
|
||||
Q_ASSERT( m_collections.length() == 1 && m_collections.first() == c ); // only 1 source supported atm
|
||||
m_collections.removeAll( c );
|
||||
@@ -127,6 +112,10 @@ Source::setOffline()
|
||||
|
||||
m_online = false;
|
||||
emit offline();
|
||||
|
||||
m_cc = 0;
|
||||
DatabaseCommand_SourceOffline* cmd = new DatabaseCommand_SourceOffline( id() );
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>(cmd) );
|
||||
}
|
||||
|
||||
|
||||
@@ -136,6 +125,12 @@ Source::setOnline()
|
||||
if ( m_online )
|
||||
return;
|
||||
|
||||
// ensure username is in the database
|
||||
DatabaseCommand_addSource* cmd = new DatabaseCommand_addSource( m_username, m_friendlyname );
|
||||
connect( cmd, SIGNAL( done( unsigned int, QString ) ),
|
||||
SLOT( dbLoaded( unsigned int, const QString& ) ) );
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>(cmd) );
|
||||
|
||||
m_online = true;
|
||||
emit online();
|
||||
}
|
||||
@@ -145,7 +140,76 @@ void
|
||||
Source::dbLoaded( unsigned int id, const QString& fname )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << id << fname;
|
||||
|
||||
m_id = id;
|
||||
m_friendlyname = fname;
|
||||
|
||||
emit syncedWithDatabase();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Source::scanningProgress( unsigned int files )
|
||||
{
|
||||
m_textStatus = tr( "Scanning (%L1 tracks)" ).arg( files );
|
||||
emit stateChanged();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Source::scanningFinished( unsigned int files )
|
||||
{
|
||||
m_textStatus = tr( "Online" );
|
||||
emit stateChanged();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Source::onStateChanged( DBSyncConnection::State newstate, DBSyncConnection::State oldstate, const QString& info )
|
||||
{
|
||||
QString msg;
|
||||
switch( newstate )
|
||||
{
|
||||
case DBSyncConnection::CHECKING:
|
||||
msg = tr( "Checking" );
|
||||
break;
|
||||
case DBSyncConnection::FETCHING:
|
||||
msg = tr( "Fetching" );
|
||||
break;
|
||||
case DBSyncConnection::PARSING:
|
||||
msg = tr( "Parsing" );
|
||||
break;
|
||||
case DBSyncConnection::SAVING:
|
||||
msg = tr( "Saving" );
|
||||
break;
|
||||
case DBSyncConnection::SYNCED:
|
||||
msg = tr( "Online" );
|
||||
break;
|
||||
case DBSyncConnection::SCANNING:
|
||||
msg = tr( "Scanning (%L1 tracks)" ).arg( info );
|
||||
break;
|
||||
|
||||
default:
|
||||
msg = "???";
|
||||
}
|
||||
|
||||
m_textStatus = msg;
|
||||
emit stateChanged();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Source::onPlaybackStarted( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << query->toString();
|
||||
m_currentTrack = query;
|
||||
emit playbackStarted( query );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Source::onPlaybackFinished( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << query->toString();
|
||||
emit playbackFinished( query );
|
||||
}
|
||||
|
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "dllmacro.h"
|
||||
|
||||
class DatabaseCommand_LogPlayback;
|
||||
class ControlConnection;
|
||||
class FileTransferConnection;
|
||||
|
||||
@@ -21,26 +22,40 @@ class DLLEXPORT Source : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class ::DatabaseCommand_LogPlayback;
|
||||
friend class ::DBSyncConnection;
|
||||
|
||||
public:
|
||||
explicit Source( const QString& username, ControlConnection* cc );
|
||||
explicit Source( const QString& username = QString() );
|
||||
explicit Source( int id, const QString& username = QString() );
|
||||
virtual ~Source();
|
||||
|
||||
bool isLocal() const { return m_isLocal; }
|
||||
bool isOnline() const { return m_online; }
|
||||
|
||||
QString lastOpGuid() const { return m_lastOpGuid; }
|
||||
|
||||
QString userName() const { return m_username; }
|
||||
QString friendlyName() const;
|
||||
void setFriendlyName( const QString& fname ) { m_friendlyname = fname; }
|
||||
|
||||
collection_ptr collection() const;
|
||||
void addCollection( QSharedPointer<Collection> c );
|
||||
void removeCollection( QSharedPointer<Collection> c );
|
||||
void addCollection( const Tomahawk::collection_ptr& c );
|
||||
void removeCollection( const Tomahawk::collection_ptr& c );
|
||||
|
||||
unsigned int id() const { return m_id; }
|
||||
ControlConnection* controlConnection() const { return m_cc; }
|
||||
void setControlConnection( ControlConnection* cc );
|
||||
|
||||
void scanningProgress( unsigned int files ) { emit loadingStateChanged( DBSyncConnection::SCANNING, DBSyncConnection::UNKNOWN, QString::number( files ) ); }
|
||||
void scanningProgress( unsigned int files );
|
||||
void scanningFinished( unsigned int files );
|
||||
|
||||
void setOffline();
|
||||
void setOnline();
|
||||
|
||||
unsigned int trackCount() const { return m_stats.value( "numfiles" ).toUInt(); }
|
||||
|
||||
Tomahawk::query_ptr currentTrack() const { return m_currentTrack; }
|
||||
QString textStatus() const { return m_textStatus; }
|
||||
|
||||
signals:
|
||||
void syncedWithDatabase();
|
||||
@@ -56,21 +71,21 @@ signals:
|
||||
void playbackStarted( const Tomahawk::query_ptr& query );
|
||||
void playbackFinished( const Tomahawk::query_ptr& query );
|
||||
|
||||
// this signal is emitted from DBSyncConnection:
|
||||
void loadingStateChanged( DBSyncConnection::State newstate, DBSyncConnection::State oldstate, const QString& info );
|
||||
void stateChanged();
|
||||
|
||||
public slots:
|
||||
void doDBSync();
|
||||
void setStats( const QVariantMap& m );
|
||||
|
||||
protected:
|
||||
void setOffline();
|
||||
void setOnline();
|
||||
|
||||
private slots:
|
||||
void setLastOpGuid( const QString& guid ) { m_lastOpGuid = guid; }
|
||||
|
||||
void dbLoaded( unsigned int id, const QString& fname );
|
||||
void remove();
|
||||
|
||||
void onStateChanged( DBSyncConnection::State newstate, DBSyncConnection::State oldstate, const QString& info );
|
||||
void onPlaybackStarted( const Tomahawk::query_ptr& query );
|
||||
void onPlaybackFinished( const Tomahawk::query_ptr& query );
|
||||
|
||||
private:
|
||||
bool m_isLocal;
|
||||
bool m_online;
|
||||
@@ -78,6 +93,10 @@ private:
|
||||
unsigned int m_id;
|
||||
QList< QSharedPointer<Collection> > m_collections;
|
||||
QVariantMap m_stats;
|
||||
QString m_lastOpGuid;
|
||||
|
||||
Tomahawk::query_ptr m_currentTrack;
|
||||
QString m_textStatus;
|
||||
|
||||
ControlConnection* m_cc;
|
||||
FileTransferConnection* m_ftc;
|
||||
|
@@ -2,6 +2,9 @@
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "database/database.h"
|
||||
#include "database/databasecommand_loadallsources.h"
|
||||
#include "network/remotecollection.h"
|
||||
#include "network/controlconnection.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
@@ -20,9 +23,11 @@ SourceList::instance()
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
|
||||
SourceList::SourceList( QObject* parent )
|
||||
: QObject( parent )
|
||||
{
|
||||
loadSources();
|
||||
}
|
||||
|
||||
|
||||
@@ -34,81 +39,95 @@ SourceList::getLocal()
|
||||
|
||||
|
||||
void
|
||||
SourceList::add( const Tomahawk::source_ptr& s )
|
||||
{
|
||||
{
|
||||
QMutexLocker lock( &m_mut );
|
||||
if ( m_sources.contains( s->userName() ) )
|
||||
return;
|
||||
|
||||
m_sources.insert( s->userName(), s );
|
||||
if( !s->isLocal() )
|
||||
{
|
||||
Q_ASSERT( s->id() );
|
||||
m_sources_id2name.insert( s->id(), s->userName() );
|
||||
}
|
||||
if( s->isLocal() )
|
||||
{
|
||||
Q_ASSERT( m_local.isNull() );
|
||||
m_local = s;
|
||||
}
|
||||
|
||||
qDebug() << "SourceList::add(" << s->userName() << "), total sources now:" << m_sources.size();
|
||||
}
|
||||
|
||||
emit sourceAdded( s );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceList::remove( Tomahawk::source_ptr& s )
|
||||
{
|
||||
if ( s.isNull() )
|
||||
return;
|
||||
|
||||
remove( s.data() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceList::remove( Tomahawk::Source* s )
|
||||
SourceList::loadSources()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
source_ptr src;
|
||||
DatabaseCommand_LoadAllSources* cmd = new DatabaseCommand_LoadAllSources();
|
||||
|
||||
connect( cmd, SIGNAL( done( const QList<Tomahawk::source_ptr>& ) ),
|
||||
SLOT( setSources( const QList<Tomahawk::source_ptr>& ) ) );
|
||||
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceList::setSources( const QList<Tomahawk::source_ptr>& sources )
|
||||
{
|
||||
QMutexLocker lock( &m_mut );
|
||||
|
||||
foreach( const source_ptr& src, sources )
|
||||
{
|
||||
QMutexLocker lock( &m_mut );
|
||||
if ( !m_sources.contains( s->userName() ) )
|
||||
return;
|
||||
|
||||
src = m_sources.value( s->userName() );
|
||||
m_sources_id2name.remove( src->id() );
|
||||
m_sources.remove( s->userName() );
|
||||
qDebug() << "SourceList::remove(" << s->userName() << "), total sources now:" << m_sources.size();
|
||||
|
||||
if ( src->controlConnection() )
|
||||
src->controlConnection()->shutdown( true );
|
||||
add( src );
|
||||
}
|
||||
|
||||
emit sourceRemoved( src );
|
||||
src.clear();
|
||||
qDebug() << Q_FUNC_INFO << "- Total sources now:" << m_sources.size();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceList::setLocal( const Tomahawk::source_ptr& localSrc )
|
||||
{
|
||||
Q_ASSERT( localSrc->isLocal() );
|
||||
Q_ASSERT( m_local.isNull() );
|
||||
|
||||
{
|
||||
QMutexLocker lock( &m_mut );
|
||||
m_sources.insert( localSrc->userName(), localSrc );
|
||||
m_local = localSrc;
|
||||
|
||||
qDebug() << Q_FUNC_INFO << localSrc->userName();
|
||||
}
|
||||
|
||||
emit sourceAdded( localSrc );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceList::add( const source_ptr& source )
|
||||
{
|
||||
Q_ASSERT( source->id() );
|
||||
|
||||
m_sources.insert( source->userName(), source );
|
||||
m_sources_id2name.insert( source->id(), source->userName() );
|
||||
connect( source.data(), SIGNAL( syncedWithDatabase() ), SLOT( sourceSynced() ) );
|
||||
|
||||
collection_ptr coll( new RemoteCollection( source ) );
|
||||
source->addCollection( coll );
|
||||
|
||||
emit sourceAdded( source );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceList::removeAllRemote()
|
||||
{
|
||||
foreach( source_ptr s, m_sources )
|
||||
{
|
||||
if( s != m_local )
|
||||
remove( s );
|
||||
{
|
||||
if ( s->controlConnection() )
|
||||
{
|
||||
s->controlConnection()->shutdown( true );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QList<source_ptr>
|
||||
SourceList::sources() const
|
||||
SourceList::sources( bool onlyOnline ) const
|
||||
{
|
||||
QMutexLocker lock( &m_mut );
|
||||
return m_sources.values();
|
||||
|
||||
QList< source_ptr > sources;
|
||||
foreach( const source_ptr& src, m_sources )
|
||||
{
|
||||
if ( !onlyOnline || src->controlConnection() )
|
||||
sources << src;
|
||||
}
|
||||
|
||||
return sources;
|
||||
}
|
||||
|
||||
|
||||
@@ -121,10 +140,32 @@ SourceList::get( unsigned int id ) const
|
||||
|
||||
|
||||
source_ptr
|
||||
SourceList::get( const QString& username ) const
|
||||
SourceList::get( const QString& username, const QString& friendlyName )
|
||||
{
|
||||
QMutexLocker lock( &m_mut );
|
||||
return m_sources.value( username );
|
||||
|
||||
source_ptr source;
|
||||
if ( !m_sources.contains( username ) )
|
||||
{
|
||||
source = source_ptr( new Source( -1, username ) );
|
||||
source->setFriendlyName( friendlyName );
|
||||
add( source );
|
||||
}
|
||||
else
|
||||
source = m_sources.value( username );
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceList::sourceSynced()
|
||||
{
|
||||
Source* src = qobject_cast< Source* >( sender() );
|
||||
|
||||
Q_ASSERT( m_sources_id2name.values().contains( src->userName() ) );
|
||||
m_sources_id2name.remove( m_sources_id2name.key( src->userName() ) );
|
||||
m_sources_id2name.insert( src->id(), src->userName() );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -20,24 +20,32 @@ public:
|
||||
explicit SourceList( QObject* parent = 0 );
|
||||
|
||||
const Tomahawk::source_ptr& getLocal();
|
||||
void add( const Tomahawk::source_ptr& s );
|
||||
void remove( Tomahawk::source_ptr& s );
|
||||
void remove( Tomahawk::Source* s );
|
||||
void setLocal( const Tomahawk::source_ptr& localSrc );
|
||||
|
||||
void removeAllRemote();
|
||||
|
||||
QList<Tomahawk::source_ptr> sources() const;
|
||||
QList<Tomahawk::source_ptr> sources( bool onlyOnline = false ) const;
|
||||
unsigned int count() const;
|
||||
|
||||
Tomahawk::source_ptr get( const QString& username ) const;
|
||||
Tomahawk::source_ptr get( const QString& username, const QString& friendlyName = QString() );
|
||||
Tomahawk::source_ptr get( unsigned int id ) const;
|
||||
|
||||
signals:
|
||||
void ready();
|
||||
|
||||
void sourceAdded( const Tomahawk::source_ptr& );
|
||||
void sourceRemoved( const Tomahawk::source_ptr& );
|
||||
|
||||
private slots:
|
||||
void setSources( const QList<Tomahawk::source_ptr>& sources );
|
||||
void sourceSynced();
|
||||
|
||||
private:
|
||||
QMap<QString, Tomahawk::source_ptr > m_sources;
|
||||
QMap<unsigned int, QString> m_sources_id2name;
|
||||
void loadSources();
|
||||
void add( const Tomahawk::source_ptr& source );
|
||||
|
||||
QMap< QString, Tomahawk::source_ptr > m_sources;
|
||||
QMap< unsigned int, QString > m_sources_id2name;
|
||||
|
||||
Tomahawk::source_ptr m_local;
|
||||
mutable QMutex m_mut; // mutable so const methods can use a lock
|
||||
|
@@ -6,10 +6,45 @@
|
||||
#include <QStyleOption>
|
||||
#include <QWidget>
|
||||
|
||||
#define ARROW_WIDTH 8
|
||||
#define ARROW_HEIGHT 8
|
||||
|
||||
|
||||
void
|
||||
ProxyStyle::drawPrimitive( PrimitiveElement pe, const QStyleOption* opt, QPainter* p, const QWidget* w ) const
|
||||
{
|
||||
if ( pe == PE_IndicatorBranch )
|
||||
{
|
||||
if ( opt->state & QStyle::State_Children )
|
||||
{
|
||||
QRect r = opt->rect;
|
||||
|
||||
int hd = ( opt->rect.height() - ARROW_HEIGHT ) / 2;
|
||||
int wd = ( opt->rect.width() - ARROW_WIDTH ) / 2;
|
||||
r.adjust( wd, hd, 0, 0 );
|
||||
|
||||
QPointF pointsOpened[3] = { QPointF( r.x(), r.y() ), QPointF( r.x() + ARROW_WIDTH, r.y() ), QPointF( r.x() + ARROW_WIDTH / 2, r.y() + ARROW_HEIGHT ) };
|
||||
QPointF pointsClosed[3] = { QPointF( r.x(), r.y() ), QPointF( r.x() + ARROW_WIDTH, r.y() + ARROW_HEIGHT / 2 ), QPointF( r.x(), r.y() + ARROW_HEIGHT ) };
|
||||
|
||||
p->save();
|
||||
p->setRenderHint( QPainter::Antialiasing );
|
||||
|
||||
p->setPen( opt->palette.dark().color() );
|
||||
p->setBrush( opt->palette.dark().color() );
|
||||
if ( !( opt->state & QStyle::State_Open ) )
|
||||
{
|
||||
p->drawPolygon( pointsClosed, 3 );
|
||||
}
|
||||
else
|
||||
{
|
||||
p->drawPolygon( pointsOpened, 3 );
|
||||
}
|
||||
|
||||
p->restore();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ( pe != PE_FrameStatusBar )
|
||||
QProxyStyle::drawPrimitive( pe, opt, p, w );
|
||||
}
|
||||
|
@@ -111,7 +111,7 @@ MusicScanner::listerFinished( const QMap<QString, unsigned int>& newmtimes )
|
||||
// any remaining stuff that wasnt emitted as a batch:
|
||||
if( m_scannedfiles.length() )
|
||||
{
|
||||
SourceList::instance()->getLocal()->scanningProgress( m_scanned );
|
||||
SourceList::instance()->getLocal()->scanningFinished( m_scanned );
|
||||
commitBatch( m_scannedfiles );
|
||||
}
|
||||
|
||||
|
@@ -1,3 +1,5 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <QCryptographicHash>
|
||||
#include <QDebug>
|
||||
#include <QDesktopServices>
|
||||
|
@@ -9,16 +9,19 @@
|
||||
#include "query.h"
|
||||
#include "sourcelist.h"
|
||||
#include "sourcetreeitem.h"
|
||||
#include "sourcetreeview.h"
|
||||
#include "utils/imagebutton.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
SourcesModel::SourcesModel( QObject* parent )
|
||||
SourcesModel::SourcesModel( SourceTreeView* parent )
|
||||
: QStandardItemModel( parent )
|
||||
, m_parent( parent )
|
||||
{
|
||||
setColumnCount( 1 );
|
||||
|
||||
onSourceAdded( SourceList::instance()->sources() );
|
||||
connect( SourceList::instance(), SIGNAL( sourceAdded( Tomahawk::source_ptr ) ), SLOT( onSourceAdded( Tomahawk::source_ptr ) ) );
|
||||
connect( SourceList::instance(), SIGNAL( sourceRemoved( Tomahawk::source_ptr ) ), SLOT( onSourceRemoved( Tomahawk::source_ptr ) ) );
|
||||
|
||||
@@ -91,6 +94,14 @@ SourcesModel::loadSources()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourcesModel::onSourceAdded( const QList<source_ptr>& sources )
|
||||
{
|
||||
foreach( const source_ptr& source, sources )
|
||||
appendItem( source );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourcesModel::onSourceAdded( const source_ptr& source )
|
||||
{
|
||||
@@ -113,8 +124,14 @@ SourcesModel::appendItem( const source_ptr& source )
|
||||
|
||||
// qDebug() << "Appending source item:" << item->source()->username();
|
||||
invisibleRootItem()->appendRow( item->columns() );
|
||||
// m_parent->setIndexWidget( m_parent->model()->index( rowCount() - 1, 0 ), item->widget() );
|
||||
|
||||
((QTreeView*)parent())->setIndexWidget( index( rowCount() - 1, 0 ), item->widget() );
|
||||
connect( source.data(), SIGNAL( offline() ), SLOT( onSourceChanged() ) );
|
||||
connect( source.data(), SIGNAL( online() ), SLOT( onSourceChanged() ) );
|
||||
connect( source.data(), SIGNAL( stats( QVariantMap ) ), SLOT( onSourceChanged() ) );
|
||||
connect( source.data(), SIGNAL( playbackStarted( Tomahawk::query_ptr ) ), SLOT( onSourceChanged() ) );
|
||||
connect( source.data(), SIGNAL( stateChanged() ), SLOT( onSourceChanged() ) );
|
||||
|
||||
return true; // FIXME
|
||||
}
|
||||
|
||||
@@ -201,7 +218,9 @@ SourcesModel::indexToPlaylist( const QModelIndex& index )
|
||||
return res;
|
||||
}
|
||||
|
||||
dynplaylist_ptr SourcesModel::indexToDynamicPlaylist(const QModelIndex& index)
|
||||
|
||||
dynplaylist_ptr
|
||||
SourcesModel::indexToDynamicPlaylist( const QModelIndex& index )
|
||||
{
|
||||
dynplaylist_ptr res;
|
||||
if ( !index.isValid() )
|
||||
@@ -252,7 +271,9 @@ SourcesModel::setData( const QModelIndex& index, const QVariant& value, int role
|
||||
if ( indexType( index ) == PlaylistSource )
|
||||
{
|
||||
playlist = indexToPlaylist( index );
|
||||
} else if ( indexType( index ) == DynamicPlaylistSource ) {
|
||||
}
|
||||
else if ( indexType( index ) == DynamicPlaylistSource )
|
||||
{
|
||||
playlist = indexToDynamicPlaylist( index ).staticCast< Playlist >();
|
||||
}
|
||||
|
||||
@@ -265,3 +286,27 @@ SourcesModel::setData( const QModelIndex& index, const QVariant& value, int role
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourcesModel::onSourceChanged()
|
||||
{
|
||||
Source* src = qobject_cast< Source* >( sender() );
|
||||
|
||||
for ( int i = 0; i < rowCount(); i++ )
|
||||
{
|
||||
QModelIndex idx = index( i, 0 );
|
||||
|
||||
if ( indexType( idx ) == CollectionSource )
|
||||
{
|
||||
SourceTreeItem* sti = indexToTreeItem( idx );
|
||||
if ( sti )
|
||||
{
|
||||
if ( sti->source().data() == src )
|
||||
{
|
||||
emit dataChanged( idx, idx );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@
|
||||
#include "typedefs.h"
|
||||
|
||||
class SourceTreeItem;
|
||||
class SourceTreeView;
|
||||
|
||||
class SourcesModel : public QStandardItemModel
|
||||
{
|
||||
@@ -21,7 +22,7 @@ public:
|
||||
DynamicPlaylistSource = 2
|
||||
};
|
||||
|
||||
explicit SourcesModel( QObject* parent = 0 );
|
||||
explicit SourcesModel( SourceTreeView* parent = 0 );
|
||||
|
||||
virtual QStringList mimeTypes() const;
|
||||
virtual Qt::DropActions supportedDropActions() const;
|
||||
@@ -43,14 +44,20 @@ protected:
|
||||
bool setData( const QModelIndex& index, const QVariant& value, int role = Qt::EditRole );
|
||||
|
||||
private slots:
|
||||
void onSourceAdded( const QList<Tomahawk::source_ptr>& sources );
|
||||
void onSourceAdded( const Tomahawk::source_ptr& source );
|
||||
void onSourceRemoved( const Tomahawk::source_ptr& source );
|
||||
|
||||
void onSourceChanged();
|
||||
|
||||
void onItemOnline( const QModelIndex& idx );
|
||||
void onItemOffline( const QModelIndex& idx );
|
||||
|
||||
public slots:
|
||||
void loadSources();
|
||||
|
||||
private:
|
||||
SourceTreeView* m_parent;
|
||||
};
|
||||
|
||||
#endif // SOURCESMODEL_H
|
||||
|
57
src/sourcetree/sourcesproxymodel.cpp
Normal file
57
src/sourcetree/sourcesproxymodel.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#include "sourcesproxymodel.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QTreeView>
|
||||
|
||||
#include "sourcesmodel.h"
|
||||
#include "sourcetreeitem.h"
|
||||
|
||||
|
||||
SourcesProxyModel::SourcesProxyModel( SourcesModel* model, QObject* parent )
|
||||
: QSortFilterProxyModel( parent )
|
||||
, m_model( model )
|
||||
, m_filtered( false )
|
||||
{
|
||||
setDynamicSortFilter( true );
|
||||
|
||||
setSourceModel( model );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourcesProxyModel::showOfflineSources()
|
||||
{
|
||||
m_filtered = false;
|
||||
invalidateFilter();
|
||||
|
||||
// Q_ASSERT( qobject_cast<QTreeView*>( parent() ) );
|
||||
// qobject_cast<QTreeView*>( parent() )->expandAll();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourcesProxyModel::hideOfflineSources()
|
||||
{
|
||||
m_filtered = true;
|
||||
invalidateFilter();
|
||||
|
||||
// Q_ASSERT( qobject_cast<QTreeView*>( parent() ) );
|
||||
// qobject_cast<QTreeView*>( parent() )->expandAll();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SourcesProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const
|
||||
{
|
||||
if ( !m_filtered )
|
||||
return true;
|
||||
|
||||
SourceTreeItem* sti = m_model->indexToTreeItem( sourceModel()->index( sourceRow, 0, sourceParent ) );
|
||||
if ( sti )
|
||||
{
|
||||
if ( sti->source().isNull() || sti->source()->isOnline() )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
28
src/sourcetree/sourcesproxymodel.h
Normal file
28
src/sourcetree/sourcesproxymodel.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef SOURCESPROXYMODEL_H
|
||||
#define SOURCESPROXYMODEL_H
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
class SourcesModel;
|
||||
|
||||
class SourcesProxyModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SourcesProxyModel( SourcesModel* model, QObject* parent = 0 );
|
||||
|
||||
public slots:
|
||||
void showOfflineSources();
|
||||
void hideOfflineSources();
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const;
|
||||
|
||||
private:
|
||||
SourcesModel* m_model;
|
||||
|
||||
bool m_filtered;
|
||||
};
|
||||
|
||||
#endif // SOURCESPROXYMODEL_H
|
@@ -10,6 +10,7 @@
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
static inline QList< playlist_ptr > dynListToPlaylists( const QList< Tomahawk::dynplaylist_ptr >& list )
|
||||
{
|
||||
QList< playlist_ptr > newptrs;
|
||||
@@ -19,11 +20,13 @@ static inline QList< playlist_ptr > dynListToPlaylists( const QList< Tomahawk::d
|
||||
return newptrs;
|
||||
}
|
||||
|
||||
|
||||
SourceTreeItem::SourceTreeItem( const source_ptr& source, QObject* parent )
|
||||
: QObject( parent )
|
||||
, m_source( source )
|
||||
{
|
||||
QStandardItem* item = new QStandardItem( "" );
|
||||
QStandardItem* item = new QStandardItem( source.isNull() ? "Super Collection" : source->friendlyName() );
|
||||
item->setIcon( QIcon( RESPATH "images/user-avatar.png" ) );
|
||||
item->setEditable( false );
|
||||
item->setData( SourcesModel::CollectionSource, Type );
|
||||
item->setData( (qlonglong)this, SourceItemPointer );
|
||||
@@ -36,7 +39,6 @@ SourceTreeItem::SourceTreeItem( const source_ptr& source, QObject* parent )
|
||||
|
||||
connect( source->collection().data(), SIGNAL( playlistsAdded( QList<Tomahawk::playlist_ptr> ) ),
|
||||
SLOT( onPlaylistsAdded( QList<Tomahawk::playlist_ptr> ) ) );
|
||||
|
||||
connect( source->collection().data(), SIGNAL( playlistsDeleted( QList<Tomahawk::playlist_ptr> ) ),
|
||||
SLOT( onPlaylistsDeleted( QList<Tomahawk::playlist_ptr> ) ) );
|
||||
|
||||
@@ -46,8 +48,8 @@ SourceTreeItem::SourceTreeItem( const source_ptr& source, QObject* parent )
|
||||
SLOT( onDynamicPlaylistsDeleted( QList<Tomahawk::dynplaylist_ptr> ) ) );
|
||||
}
|
||||
|
||||
m_widget = new SourceTreeItemWidget( source );
|
||||
connect( m_widget, SIGNAL( clicked() ), SLOT( onClicked() ) );
|
||||
/* m_widget = new SourceTreeItemWidget( source );
|
||||
connect( m_widget, SIGNAL( clicked() ), SLOT( onClicked() ) );*/
|
||||
}
|
||||
|
||||
|
||||
@@ -98,6 +100,7 @@ SourceTreeItem::onPlaylistsAdded( const QList<playlist_ptr>& playlists )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceTreeItem::onPlaylistsDeleted( const QList<playlist_ptr>& playlists )
|
||||
{
|
||||
@@ -125,6 +128,7 @@ SourceTreeItem::onPlaylistsDeleted( const QList<playlist_ptr>& playlists )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceTreeItem::onPlaylistLoaded( Tomahawk::PlaylistRevision revision )
|
||||
{
|
||||
@@ -149,7 +153,9 @@ SourceTreeItem::onPlaylistLoaded( Tomahawk::PlaylistRevision revision )
|
||||
}
|
||||
}
|
||||
|
||||
void SourceTreeItem::onDynamicPlaylistsAdded( const QList< dynplaylist_ptr >& playlists )
|
||||
|
||||
void
|
||||
SourceTreeItem::onDynamicPlaylistsAdded( const QList< dynplaylist_ptr >& playlists )
|
||||
{
|
||||
// const-ness is important for getting the right pointer!
|
||||
foreach( const dynplaylist_ptr& p, playlists )
|
||||
@@ -167,7 +173,9 @@ void SourceTreeItem::onDynamicPlaylistsAdded( const QList< dynplaylist_ptr >& pl
|
||||
}
|
||||
}
|
||||
|
||||
void SourceTreeItem::onDynamicPlaylistsDeleted( const QList< dynplaylist_ptr >& playlists )
|
||||
|
||||
void
|
||||
SourceTreeItem::onDynamicPlaylistsDeleted( const QList< dynplaylist_ptr >& playlists )
|
||||
{
|
||||
// const-ness is important for getting the right pointer!
|
||||
foreach( const dynplaylist_ptr& p, playlists )
|
||||
@@ -193,7 +201,9 @@ void SourceTreeItem::onDynamicPlaylistsDeleted( const QList< dynplaylist_ptr >&
|
||||
}
|
||||
}
|
||||
|
||||
void SourceTreeItem::onDynamicPlaylistLoaded( DynamicPlaylistRevision revision )
|
||||
|
||||
void
|
||||
SourceTreeItem::onDynamicPlaylistLoaded( DynamicPlaylistRevision revision )
|
||||
{
|
||||
qlonglong ptr = reinterpret_cast<qlonglong>( sender() );
|
||||
|
||||
|
@@ -19,8 +19,7 @@ public:
|
||||
PlaylistPointer = Qt::UserRole + 3, /// Value is the playlist_ptr.data()
|
||||
DynamicPlaylistPointer = Qt::UserRole + 4 /// Value is the dynplaylist_ptr.data()
|
||||
};
|
||||
|
||||
|
||||
|
||||
explicit SourceTreeItem( const Tomahawk::source_ptr& source, QObject* parent );
|
||||
virtual ~SourceTreeItem();
|
||||
|
||||
|
@@ -49,7 +49,8 @@ SourceTreeItemWidget::SourceTreeItemWidget( const source_ptr& source, QWidget* p
|
||||
connect( source.data(), SIGNAL( stats( QVariantMap ) ), SLOT( gotStats( QVariantMap ) ) );
|
||||
|
||||
connect( source.data(), SIGNAL( playbackStarted( Tomahawk::query_ptr ) ), SLOT( onPlaybackStarted( Tomahawk::query_ptr ) ) );
|
||||
|
||||
connect( source.data(), SIGNAL( offline() ), SLOT( onOffline() ) );
|
||||
|
||||
ui->avatarImage->setPixmap( QPixmap( RESPATH "images/user-avatar.png" ) );
|
||||
|
||||
displayname = source->friendlyName();
|
||||
@@ -62,8 +63,12 @@ SourceTreeItemWidget::SourceTreeItemWidget( const source_ptr& source, QWidget* p
|
||||
ui->infoButton->setPixmap( QPixmap( RESPATH "images/source-info.png" ) .scaledToHeight( 32, Qt::SmoothTransformation ) );
|
||||
}
|
||||
|
||||
if ( source.isNull() || source->isLocal() )
|
||||
ui->activityLabel->setText( tr( "Idle" ) );
|
||||
else
|
||||
onOffline();
|
||||
|
||||
ui->nameLabel->setText( displayname );
|
||||
ui->activityLabel->setText( tr( "Idle" ) );
|
||||
ui->infoLabel->setForegroundRole( QPalette::Dark );
|
||||
ui->activityLabel->setForegroundRole( QPalette::Dark );
|
||||
|
||||
@@ -73,8 +78,6 @@ SourceTreeItemWidget::SourceTreeItemWidget( const source_ptr& source, QWidget* p
|
||||
|
||||
connect( ui->onOffButton, SIGNAL( clicked() ), SIGNAL( clicked() ) );
|
||||
connect( ui->infoButton, SIGNAL( clicked() ), SLOT( onInfoButtonClicked() ) );
|
||||
|
||||
onOffline();
|
||||
}
|
||||
|
||||
|
||||
@@ -145,7 +148,6 @@ void
|
||||
SourceTreeItemWidget::onPlaybackStarted( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << query->toString();
|
||||
// ui->activityLabel->setText( tr( "Playing: %1 by %2" ).arg( query->track() ).arg( query->artist() ) );
|
||||
ui->activityLabel->setQuery( query );
|
||||
}
|
||||
|
||||
@@ -154,19 +156,14 @@ void
|
||||
SourceTreeItemWidget::onOnline()
|
||||
{
|
||||
return;
|
||||
|
||||
if ( !m_source.isNull() )
|
||||
ui->onOffButton->setPixmap( RESPATH "images/source-on-rest.png" );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceTreeItemWidget::onOffline()
|
||||
{
|
||||
ui->activityLabel->setText( tr( "Offline" ) );
|
||||
return;
|
||||
|
||||
if ( !m_source.isNull() )
|
||||
ui->onOffButton->setPixmap( RESPATH "images/source-off-rest.png" );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -5,6 +5,7 @@
|
||||
#include "playlist/playlistmanager.h"
|
||||
#include "sourcetreeitem.h"
|
||||
#include "sourcesmodel.h"
|
||||
#include "sourcesproxymodel.h"
|
||||
#include "sourcelist.h"
|
||||
#include "tomahawk/tomahawkapp.h"
|
||||
|
||||
@@ -14,6 +15,7 @@
|
||||
#include <QHeaderView>
|
||||
#include <QPainter>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QSize>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
@@ -24,11 +26,12 @@ public:
|
||||
SourceDelegate( QAbstractItemView* parent = 0 ) : QStyledItemDelegate( parent ), m_parent( parent ) {}
|
||||
|
||||
protected:
|
||||
void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
|
||||
void updateEditorGeometry( QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||
virtual QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const;
|
||||
virtual void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
|
||||
virtual void updateEditorGeometry( QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||
{
|
||||
if ( SourcesModel::indexType( index ) == SourcesModel::PlaylistSource || SourcesModel::indexType( index ) == SourcesModel::DynamicPlaylistSource )
|
||||
editor->setGeometry( option.rect.adjusted( 32, 0, 0, 0 ) );
|
||||
editor->setGeometry( option.rect.adjusted( 20, 0, 0, 0 ) );
|
||||
else
|
||||
QStyledItemDelegate::updateEditorGeometry( editor, option, index );
|
||||
}
|
||||
@@ -49,7 +52,7 @@ SourceTreeView::SourceTreeView( QWidget* parent )
|
||||
setMinimumWidth( 220 );
|
||||
|
||||
setHeaderHidden( true );
|
||||
setRootIsDecorated( false );
|
||||
setRootIsDecorated( true );
|
||||
setExpandsOnDoubleClick( false );
|
||||
|
||||
setSelectionBehavior( QAbstractItemView::SelectRows );
|
||||
@@ -58,8 +61,8 @@ SourceTreeView::SourceTreeView( QWidget* parent )
|
||||
setDropIndicatorShown( false );
|
||||
setAllColumnsShowFocus( true );
|
||||
setUniformRowHeights( false );
|
||||
setIndentation( 0 );
|
||||
setAnimated( false );
|
||||
setIndentation( 16 );
|
||||
setAnimated( true );
|
||||
|
||||
setItemDelegate( new SourceDelegate( this ) );
|
||||
|
||||
@@ -67,7 +70,8 @@ SourceTreeView::SourceTreeView( QWidget* parent )
|
||||
connect( this, SIGNAL( customContextMenuRequested( const QPoint& ) ), SLOT( onCustomContextMenu( const QPoint& ) ) );
|
||||
|
||||
m_model = new SourcesModel( this );
|
||||
setModel( m_model );
|
||||
m_proxyModel = new SourcesProxyModel( m_model, this );
|
||||
setModel( m_proxyModel );
|
||||
|
||||
header()->setStretchLastSection( false );
|
||||
header()->setResizeMode( 0, QHeaderView::Stretch );
|
||||
@@ -79,6 +83,8 @@ SourceTreeView::SourceTreeView( QWidget* parent )
|
||||
connect( SourceList::instance(), SIGNAL( sourceRemoved( Tomahawk::source_ptr ) ), SLOT( onSourceOffline( Tomahawk::source_ptr ) ) );
|
||||
|
||||
m_model->appendItem( source_ptr() );
|
||||
|
||||
hideOfflineSources();
|
||||
}
|
||||
|
||||
|
||||
@@ -107,11 +113,8 @@ SourceTreeView::setupMenus()
|
||||
}
|
||||
}
|
||||
|
||||
if ( readonly )
|
||||
{
|
||||
m_deletePlaylistAction->setEnabled( !readonly );
|
||||
m_renamePlaylistAction->setEnabled( !readonly );
|
||||
}
|
||||
m_deletePlaylistAction->setEnabled( !readonly );
|
||||
m_renamePlaylistAction->setEnabled( !readonly );
|
||||
|
||||
connect( m_loadPlaylistAction, SIGNAL( triggered() ), SLOT( loadPlaylist() ) );
|
||||
connect( m_renamePlaylistAction, SIGNAL( triggered() ), SLOT( renamePlaylist() ) );
|
||||
@@ -119,6 +122,20 @@ SourceTreeView::setupMenus()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceTreeView::showOfflineSources()
|
||||
{
|
||||
m_proxyModel->showOfflineSources();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceTreeView::hideOfflineSources()
|
||||
{
|
||||
m_proxyModel->hideOfflineSources();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceTreeView::onSourceOffline( Tomahawk::source_ptr src )
|
||||
{
|
||||
@@ -160,7 +177,7 @@ SourceTreeView::onItemActivated( const QModelIndex& index )
|
||||
PlaylistManager::instance()->show( playlist );
|
||||
}
|
||||
}
|
||||
else if ( type == SourcesModel::DynamicPlaylistSource )
|
||||
else if ( type == SourcesModel::DynamicPlaylistSource )
|
||||
{
|
||||
dynplaylist_ptr playlist = SourcesModel::indexToDynamicPlaylist( index );
|
||||
if ( !playlist.isNull() )
|
||||
@@ -211,7 +228,9 @@ SourceTreeView::deletePlaylist()
|
||||
}
|
||||
}
|
||||
|
||||
void SourceTreeView::renamePlaylist()
|
||||
|
||||
void
|
||||
SourceTreeView::renamePlaylist()
|
||||
{
|
||||
edit( m_contextMenuIndex );
|
||||
}
|
||||
@@ -384,23 +403,122 @@ SourceTreeView::drawRow( QPainter* painter, const QStyleOptionViewItem& option,
|
||||
}
|
||||
|
||||
|
||||
QSize
|
||||
SourceDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||
{
|
||||
if ( index.data( SourceTreeItem::Type ) == SourcesModel::CollectionSource )
|
||||
return QSize( option.rect.width(), 44 );
|
||||
else
|
||||
return QStyledItemDelegate::sizeHint( option, index );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||
{
|
||||
QStyleOptionViewItem o = option;
|
||||
o.rect.adjust( 12, 0, 0, 0 );
|
||||
QStyleOptionViewItem o2 = option;
|
||||
o2.rect.setX( 0 );
|
||||
o2.state = option.state;
|
||||
|
||||
if ( ( option.state & QStyle::State_Enabled ) == QStyle::State_Enabled )
|
||||
{
|
||||
o.state = QStyle::State_Enabled;
|
||||
|
||||
if ( ( SourcesModel::indexType( index ) == SourcesModel::PlaylistSource || SourcesModel::indexType( index ) == SourcesModel::DynamicPlaylistSource ) &&
|
||||
( option.state & QStyle::State_Selected ) == QStyle::State_Selected )
|
||||
if ( ( option.state & QStyle::State_Selected ) == QStyle::State_Selected )
|
||||
{
|
||||
o.palette.setColor( QPalette::Text, o.palette.color( QPalette::HighlightedText ) );
|
||||
}
|
||||
}
|
||||
|
||||
QStyledItemDelegate::paint( painter, option, index.model()->index( 0, 0 ) );
|
||||
QStyledItemDelegate::paint( painter, o, index );
|
||||
QStyledItemDelegate::paint( painter, o2, QModelIndex() );
|
||||
|
||||
if ( index.data( SourceTreeItem::Type ) == SourcesModel::CollectionSource )
|
||||
{
|
||||
painter->save();
|
||||
|
||||
QFont normal = painter->font();
|
||||
QFont bold = painter->font();
|
||||
bold.setBold( true );
|
||||
|
||||
SourceTreeItem* sti = SourcesModel::indexToTreeItem( index );
|
||||
bool status = !( !sti || sti->source().isNull() || !sti->source()->isOnline() );
|
||||
QString tracks;
|
||||
int figWidth = 0;
|
||||
|
||||
if ( status )
|
||||
{
|
||||
tracks = QString::number( sti->source()->trackCount() );
|
||||
figWidth = painter->fontMetrics().width( tracks );
|
||||
}
|
||||
|
||||
QRect iconRect = option.rect.adjusted( 4, 6, -option.rect.width() + option.rect.height() - 12 + 4, -6 );
|
||||
painter->drawPixmap( iconRect, QPixmap( RESPATH "images/user-avatar.png" ) );
|
||||
|
||||
if ( ( option.state & QStyle::State_Selected ) == QStyle::State_Selected )
|
||||
{
|
||||
painter->setPen( o.palette.color( QPalette::HighlightedText ) );
|
||||
}
|
||||
|
||||
QRect textRect = option.rect.adjusted( iconRect.width() + 8, 6, -figWidth - 24, 0 );
|
||||
if ( status || sti->source().isNull() )
|
||||
painter->setFont( bold );
|
||||
QString text = painter->fontMetrics().elidedText( index.data().toString(), Qt::ElideRight, textRect.width() );
|
||||
painter->drawText( textRect, text );
|
||||
|
||||
QString desc = status ? sti->source()->textStatus() : tr( "Offline" );
|
||||
if ( sti->source().isNull() )
|
||||
desc = tr( "All available tracks" );
|
||||
if ( status && !sti->source()->currentTrack().isNull() )
|
||||
desc = sti->source()->currentTrack()->artist() + " - " + sti->source()->currentTrack()->track();
|
||||
if ( desc.isEmpty() )
|
||||
desc = tr( "Online" );
|
||||
|
||||
textRect = option.rect.adjusted( iconRect.width() + 8, painter->fontMetrics().height() + 10, -figWidth - 24, 0 );
|
||||
painter->setFont( normal );
|
||||
text = painter->fontMetrics().elidedText( desc, Qt::ElideRight, textRect.width() );
|
||||
painter->drawText( textRect, text );
|
||||
|
||||
if ( !status )
|
||||
{
|
||||
painter->restore();
|
||||
return;
|
||||
}
|
||||
painter->setRenderHint( QPainter::Antialiasing );
|
||||
|
||||
QRect figRect = o.rect.adjusted( o.rect.width() - figWidth - 18, 0, -10, -o.rect.height() + 16 );
|
||||
int hd = ( option.rect.height() - figRect.height() ) / 2;
|
||||
figRect.adjust( 0, hd, 0, hd );
|
||||
|
||||
QColor figColor( 167, 183, 211 );
|
||||
painter->setPen( figColor );
|
||||
painter->setBrush( figColor );
|
||||
|
||||
QPen origpen = painter->pen();
|
||||
QPen pen = origpen;
|
||||
pen.setWidth( 1.0 );
|
||||
painter->setPen( pen );
|
||||
painter->drawRect( figRect );
|
||||
|
||||
QPainterPath ppath;
|
||||
ppath.moveTo( QPoint( figRect.x(), figRect.y() ) );
|
||||
ppath.quadTo( QPoint( figRect.x() - 8, figRect.y() + figRect.height() / 2 ), QPoint( figRect.x(), figRect.y() + figRect.height() ) );
|
||||
painter->drawPath( ppath );
|
||||
ppath.moveTo( QPoint( figRect.x() + figRect.width(), figRect.y() ) );
|
||||
ppath.quadTo( QPoint( figRect.x() + figRect.width() + 8, figRect.y() + figRect.height() / 2 ), QPoint( figRect.x() + figRect.width(), figRect.y() + figRect.height() ) );
|
||||
painter->drawPath( ppath );
|
||||
|
||||
painter->setPen( origpen );
|
||||
|
||||
QTextOption to( Qt::AlignCenter );
|
||||
painter->setFont( bold );
|
||||
painter->setPen( Qt::white );
|
||||
painter->drawText( figRect, tracks, to );
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
else
|
||||
{
|
||||
QStyledItemDelegate::paint( painter, o, index );
|
||||
}
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@
|
||||
class CollectionModel;
|
||||
class PlaylistModel;
|
||||
class SourcesModel;
|
||||
class SourcesProxyModel;
|
||||
|
||||
class SourceTreeView : public QTreeView
|
||||
{
|
||||
@@ -17,6 +18,10 @@ Q_OBJECT
|
||||
public:
|
||||
explicit SourceTreeView( QWidget* parent = 0 );
|
||||
|
||||
public slots:
|
||||
void showOfflineSources();
|
||||
void hideOfflineSources();
|
||||
|
||||
signals:
|
||||
void onOnline( const QModelIndex& index );
|
||||
void onOffline( const QModelIndex& index );
|
||||
@@ -33,7 +38,7 @@ private slots:
|
||||
void onSourceOffline( Tomahawk::source_ptr );
|
||||
|
||||
protected:
|
||||
void drawBranches( QPainter* painter, const QRect& rect, const QModelIndex& index ) const {}
|
||||
// void drawBranches( QPainter* painter, const QRect& rect, const QModelIndex& index ) const {}
|
||||
void drawRow( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
|
||||
|
||||
virtual void paintEvent( QPaintEvent* event );
|
||||
@@ -48,6 +53,7 @@ private:
|
||||
|
||||
CollectionModel* m_collectionModel;
|
||||
SourcesModel* m_model;
|
||||
SourcesProxyModel* m_proxyModel;
|
||||
QModelIndex m_contextMenuIndex;
|
||||
|
||||
QMenu m_playlistMenu;
|
||||
|
@@ -1,5 +1,7 @@
|
||||
#include "tomahawk/tomahawkapp.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <QPluginLoader>
|
||||
#include <QDir>
|
||||
#include <QMetaType>
|
||||
@@ -151,20 +153,21 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
|
||||
registerMetaTypes();
|
||||
setupLogfile();
|
||||
|
||||
Echonest::Config::instance()->setAPIKey("JRIHWEP6GPOER2QQ6");
|
||||
Echonest::Config::instance()->setAPIKey( "JRIHWEP6GPOER2QQ6" );
|
||||
|
||||
new TomahawkSettings( this );
|
||||
m_audioEngine = new AudioEngine;
|
||||
new ScanManager( this );
|
||||
|
||||
new Pipeline( this );
|
||||
new SourceList( this );
|
||||
|
||||
m_servent = new Servent( this );
|
||||
connect( m_servent, SIGNAL( ready() ), SLOT( setupSIP() ) );
|
||||
|
||||
qDebug() << "Init Database.";
|
||||
setupDatabase();
|
||||
|
||||
new SourceList( this );
|
||||
|
||||
qDebug() << "Init Echonest Factory.";
|
||||
GeneratorFactory::registerFactory( "echonest", new EchonestFactory );
|
||||
@@ -319,6 +322,7 @@ TomahawkApp::registerMetaTypes()
|
||||
qRegisterMetaType< GeneratorMode>("GeneratorMode");
|
||||
qRegisterMetaType<Tomahawk::GeneratorMode>("Tomahawk::GeneratorMode");
|
||||
// Extra definition for namespaced-versions of signals/slots required
|
||||
qRegisterMetaType< Tomahawk::source_ptr >("Tomahawk::source_ptr");
|
||||
qRegisterMetaType< Tomahawk::collection_ptr >("Tomahawk::collection_ptr");
|
||||
qRegisterMetaType< Tomahawk::result_ptr >("Tomahawk::result_ptr");
|
||||
qRegisterMetaType< Tomahawk::query_ptr >("Tomahawk::query_ptr");
|
||||
@@ -334,6 +338,7 @@ TomahawkApp::registerMetaTypes()
|
||||
qRegisterMetaType< QList<Tomahawk::result_ptr> >("QList<Tomahawk::result_ptr>");
|
||||
qRegisterMetaType< QList<Tomahawk::artist_ptr> >("QList<Tomahawk::artist_ptr>");
|
||||
qRegisterMetaType< QList<Tomahawk::album_ptr> >("QList<Tomahawk::album_ptr>");
|
||||
qRegisterMetaType< QList<Tomahawk::source_ptr> >("QList<Tomahawk::source_ptr>");
|
||||
qRegisterMetaType< QMap< QString, Tomahawk::plentry_ptr > >("QMap< QString, Tomahawk::plentry_ptr >");
|
||||
qRegisterMetaType< Tomahawk::PlaylistRevision >("Tomahawk::PlaylistRevision");
|
||||
qRegisterMetaType< Tomahawk::DynamicPlaylistRevision >("Tomahawk::DynamicPlaylistRevision");
|
||||
@@ -411,11 +416,11 @@ TomahawkApp::removeScriptResolver( const QString& path )
|
||||
void
|
||||
TomahawkApp::initLocalCollection()
|
||||
{
|
||||
source_ptr src( new Source( "My Collection" ) );
|
||||
source_ptr src( new Source( 0, "My Collection" ) );
|
||||
collection_ptr coll( new DatabaseCollection( src ) );
|
||||
|
||||
src->addCollection( coll );
|
||||
SourceList::instance()->add( src );
|
||||
SourceList::instance()->setLocal( src );
|
||||
|
||||
// to make the stats signal be emitted by our local source
|
||||
// this will update the sidebar, etc.
|
||||
@@ -480,16 +485,17 @@ TomahawkApp::setupSIP()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
#ifdef GLOOX_FOUND
|
||||
//FIXME: jabber autoconnect is really more, now that there is sip -- should be renamed and/or split out of jabber-specific settings
|
||||
if( !arguments().contains( "--nosip" ) && TomahawkSettings::instance()->jabberAutoConnect() )
|
||||
{
|
||||
#ifdef GLOOX_FOUND
|
||||
m_xmppBot = new XMPPBot( this );
|
||||
#endif
|
||||
|
||||
qDebug() << "Connecting SIP classes";
|
||||
m_sipHandler->connectPlugins( true );
|
||||
// m_sipHandler->setProxy( *TomahawkUtils::proxy() );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@@ -83,6 +83,9 @@ TomahawkWindow::TomahawkWindow( QWidget* parent )
|
||||
SourceTreeView* stv = new SourceTreeView();
|
||||
TransferView* transferView = new TransferView();
|
||||
|
||||
connect( ui->actionHideOfflineSources, SIGNAL( triggered() ), stv, SLOT( hideOfflineSources() ) );
|
||||
connect( ui->actionShowOfflineSources, SIGNAL( triggered() ), stv, SLOT( showOfflineSources() ) );
|
||||
|
||||
sidebar->addWidget( stv );
|
||||
sidebar->addWidget( transferView );
|
||||
sidebar->hide( 1, false );
|
||||
@@ -122,11 +125,11 @@ TomahawkWindow::TomahawkWindow( QWidget* parent )
|
||||
statusBar()->addPermanentWidget( m_audioControls, 1 );
|
||||
|
||||
// propagate sip menu
|
||||
foreach(SipPlugin *plugin, APP->sipHandler()->plugins())
|
||||
foreach( SipPlugin *plugin, APP->sipHandler()->plugins() )
|
||||
{
|
||||
if(plugin->menu())
|
||||
if ( plugin->menu() )
|
||||
{
|
||||
ui->menuNetwork->addMenu(plugin->menu());
|
||||
ui->menuNetwork->addMenu( plugin->menu() );
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -50,6 +50,9 @@
|
||||
</property>
|
||||
<addaction name="actionRescanCollection"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionShowOfflineSources"/>
|
||||
<addaction name="actionHideOfflineSources"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionExit"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuPlaylist">
|
||||
@@ -150,6 +153,16 @@
|
||||
<string>Create New &Station</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionShowOfflineSources">
|
||||
<property name="text">
|
||||
<string>Show Offline Sources</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionHideOfflineSources">
|
||||
<property name="text">
|
||||
<string>Hide Offline Sources</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
|
@@ -1,7 +0,0 @@
|
||||
SET( tomahawkHeaders ${tomahawkHeaders}
|
||||
xmppbot.h
|
||||
)
|
||||
|
||||
SET( tomahawkSources ${tomahawkSources}
|
||||
xmppbot.cpp
|
||||
)
|
Reference in New Issue
Block a user