1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-15 10:33:59 +02:00

* Work in progress: New sidebar with "Super Collection".

* Click the track title in the AudioControls to jump to the current track in the playlist.
* Moved networky stuff to a separate subdir.
* Don't crash on jabber error.
* Try to reconnect to jabber server after an error occurred.
This commit is contained in:
Christian Muehlhaeuser
2010-11-11 05:22:58 +01:00
parent 3872477446
commit eed67d9b89
39 changed files with 328 additions and 192 deletions

View File

@@ -43,17 +43,18 @@ SET( tomahawkSources ${tomahawkSources}
infosystem/infoplugins/musixmatchplugin.cpp
bufferiodevice.cpp
connection.cpp
msgprocessor.cpp
controlconnection.cpp
collection.cpp
filetransferconnection.cpp
dbsyncconnection.cpp
musicscanner.cpp
remotecollection.cpp
servent.cpp
scriptresolver.cpp
network/connection.cpp
network/controlconnection.cpp
network/filetransferconnection.cpp
network/dbsyncconnection.cpp
network/remotecollection.cpp
network/servent.cpp
database/fuzzyindex.cpp
database/database.cpp
database/databaseworker.cpp
@@ -94,6 +95,8 @@ SET( tomahawkSourcesGui ${tomahawkSourcesGui}
utils/imagebutton.cpp
utils/progresstreeview.cpp
utils/proxystyle.cpp
utils/widgetdragfilter.cpp
audio/madtranscode.cpp
audio/audioengine.cpp
@@ -126,9 +129,6 @@ SET( tomahawkSourcesGui ${tomahawkSourcesGui}
tomahawkwindow.cpp
audiocontrols.cpp
settingsdialog.cpp
proxystyle.cpp
widgetdragfilter.cpp
)
SET( tomahawkHeaders ${tomahawkHeaders}
@@ -186,17 +186,18 @@ SET( tomahawkHeaders ${tomahawkHeaders}
infosystem/infoplugins/musixmatchplugin.h
bufferiodevice.h
connection.h
msgprocessor.h
controlconnection.h
filetransferconnection.h
dbsyncconnection.h
musicscanner.h
tomahawkzeroconf.h
remotecollection.h
servent.h
scriptresolver.h
tomahawksettings.h
tomahawkzeroconf.h
network/remotecollection.h
network/servent.h
network/connection.h
network/controlconnection.h
network/filetransferconnection.h
network/dbsyncconnection.h
xmppbot/xmppbot.h
@@ -209,6 +210,7 @@ SET( tomahawkHeadersGui ${tomahawkHeadersGui}
utils/animatedcounterlabel.h
utils/imagebutton.h
utils/progresstreeview.h
utils/widgetdragfilter.h
audio/transcodeinterface.h
audio/madtranscode.h
@@ -243,8 +245,6 @@ SET( tomahawkHeadersGui ${tomahawkHeadersGui}
tomahawkwindow.h
audiocontrols.h
settingsdialog.h
widgetdragfilter.h
)
SET( tomahawkUI ${tomahawkUI}
@@ -265,6 +265,7 @@ INCLUDE_DIRECTORIES(
audio
database
playlist
network
sourcetree
topbar
utils

View File

@@ -119,6 +119,8 @@ AudioControls::AudioControls( QWidget* parent )
connect( ui->repeatButton, SIGNAL( clicked() ), SLOT( onRepeatClicked() ) );
connect( ui->shuffleButton, SIGNAL( clicked() ), SLOT( onShuffleClicked() ) );
connect( ui->artistTrackLabel, SIGNAL( linkActivated( QString ) ), SLOT( onTrackClicked( QString ) ) );
// <From AudioEngine>
connect( (QObject*)TomahawkApp::instance()->audioEngine(), SIGNAL( loading( const Tomahawk::result_ptr& ) ), SLOT( onPlaybackLoading( const Tomahawk::result_ptr& ) ) );
connect( (QObject*)TomahawkApp::instance()->audioEngine(), SIGNAL( started( const Tomahawk::result_ptr& ) ), SLOT( onPlaybackStarted( const Tomahawk::result_ptr& ) ) );
@@ -221,7 +223,7 @@ AudioControls::onPlaybackLoading( const Tomahawk::result_ptr& result )
m_currentTrack = result;
ui->artistTrackLabel->setText( QString( "%1 - %2" ).arg( result->artist() ).arg( result->track() ) );
ui->artistTrackLabel->setText( "<a style='color:black; text-decoration:none;' href='#'>" + QString( "%1 - %2" ).arg( result->artist() ).arg( result->track() ) + "</a>" );
ui->albumLabel->setText( result->album() );
ui->ownerLabel->setText( result->collection()->source()->friendlyName() );
ui->coverImage->setPixmap( m_defaultCover );
@@ -402,3 +404,10 @@ AudioControls::onShuffleClicked()
{
APP->playlistManager()->setShuffled( m_shuffled ^ true );
}
void
AudioControls::onTrackClicked( const QString& /* link */ )
{
APP->playlistManager()->showCurrentTrack();
}

View File

@@ -38,6 +38,8 @@ private slots:
void onRepeatClicked();
void onShuffleClicked();
void onTrackClicked( const QString& link );
void onCoverArtDownloaded();
private:

View File

@@ -11,7 +11,6 @@ using namespace Tomahawk;
Collection::Collection( const source_ptr& source, const QString& name, QObject* parent )
: QObject( parent )
, m_name( name )
, m_loaded( false )
, m_lastmodified( 0 )
, m_source( source )
{
@@ -75,20 +74,37 @@ Collection::playlist( const QString& guid )
}
bool
Collection::trackSorter( const QVariant& left, const QVariant& right )
void
Collection::setPlaylists( const QList<Tomahawk::playlist_ptr>& plists )
{
int art = left.toMap().value( "artist" ).toString()
.localeAwareCompare( right.toMap().value( "artist" ).toString() );
qDebug() << Q_FUNC_INFO << plists.count();
if ( art == 0 )
{
int trk = left.toMap().value( "track" ).toString()
.localeAwareCompare( right.toMap().value( "track" ).toString() );
return trk < 0;
}
else
{
return art < 0;
}
m_playlists.append( plists );
emit playlistsAdded( plists );
}
void
Collection::setTracks( const QList<QVariant>& tracks, Tomahawk::collection_ptr collection )
{
qDebug() << Q_FUNC_INFO << tracks.count() << collection->name();
QList<query_ptr> qs;
foreach( const QVariant& v, tracks )
{
query_ptr query = query_ptr( new Query( v ) );
QVariantMap t = query->toVariant().toMap();
t["score"] = 1.0;
QList<result_ptr> results;
result_ptr result = result_ptr( new Result( t, collection ) );
results << result;
query->addResults( results );
qs << query;
}
m_tracks << qs;
emit tracksAdded( qs, collection );
}

View File

@@ -31,14 +31,14 @@ DatabaseCollection::loadPlaylists()
void
DatabaseCollection::loadAllTracks()
DatabaseCollection::loadTracks()
{
qDebug() << Q_FUNC_INFO << source()->userName();
DatabaseCommand_AllTracks* cmd = new DatabaseCommand_AllTracks( source()->collection() );
connect( cmd, SIGNAL( tracks( QList<QVariant>, Tomahawk::collection_ptr ) ),
SIGNAL( tracksAdded( QList<QVariant>, Tomahawk::collection_ptr ) ) );
connect( cmd, SIGNAL( done( Tomahawk::collection_ptr ) ),
SIGNAL( tracksFinished( Tomahawk::collection_ptr ) ) );
SLOT( setTracks( QList<QVariant>, Tomahawk::collection_ptr ) ) );
/* connect( cmd, SIGNAL( done( Tomahawk::collection_ptr ) ),
SIGNAL( tracksFinished( Tomahawk::collection_ptr ) ) );*/
TomahawkApp::instance()->database()->enqueue(
QSharedPointer<DatabaseCommand>( cmd )
@@ -66,3 +66,31 @@ DatabaseCollection::removeTracks( const QList<QVariant> &olditems )
// TODO RemoveTracks cmd, probably builds a temp table of all the URLs in
// olditems, then joins on that to batch-delete.
}
QList< Tomahawk::playlist_ptr >
DatabaseCollection::playlists()
{
qDebug() << Q_FUNC_INFO;
if ( Collection::playlists().isEmpty() )
{
loadPlaylists();
}
return Collection::playlists();
}
QList< Tomahawk::query_ptr >
DatabaseCollection::tracks()
{
qDebug() << Q_FUNC_INFO;
if ( Collection::tracks().isEmpty() )
{
loadTracks();
}
return Collection::tracks();
}

View File

@@ -15,9 +15,12 @@ public:
qDebug() << Q_FUNC_INFO;
}
virtual void loadAllTracks();
virtual void loadTracks();
virtual void loadPlaylists();
virtual QList< Tomahawk::playlist_ptr > playlists();
virtual QList< Tomahawk::query_ptr > tracks();
public slots:
virtual void addTracks( const QList<QVariant> &newitems );
virtual void removeTracks( const QList<QVariant> &olditems );

View File

@@ -40,7 +40,7 @@ DatabaseCommand_AddFiles::postCommitHook()
Collection* coll = source()->collection().data();
connect( this, SIGNAL( notify( const QList<QVariant>&, Tomahawk::collection_ptr ) ),
coll, SIGNAL( tracksAdded( const QList<QVariant>&, Tomahawk::collection_ptr ) ),
coll, SIGNAL( setTracks( const QList<QVariant>&, Tomahawk::collection_ptr ) ),
Qt::QueuedConnection );
// do it like this so it gets called in the right thread:
emit notify( m_files, source()->collection() );

View File

@@ -2,6 +2,7 @@
#include <QDebug>
#include <QTime>
#include <QTimer>
#include <QString>
#include <QRegExp>
@@ -56,7 +57,7 @@ Jabber_p::Jabber_p( const QString& jid, const QString& password, const QString&
Jabber_p::~Jabber_p()
{
// qDebug() << Q_FUNC_INFO;
if( m_client )
if ( !m_client.isNull() )
{
// m_client->disco()->removeDiscoHandler( this );
m_client->rosterManager()->removeRosterListener();
@@ -70,16 +71,16 @@ Jabber_p::setProxy( QNetworkProxy* proxy )
{
qDebug() << Q_FUNC_INFO;
if( !m_client || !proxy )
if( !m_client.isNull() || !proxy )
{
qDebug() << "No client or no proxy";
return;
}
QNetworkProxy appProx = QNetworkProxy::applicationProxy();
QNetworkProxy* prox = proxy->type() == QNetworkProxy::DefaultProxy ? &appProx : proxy;
QNetworkProxy* p = proxy->type() == QNetworkProxy::DefaultProxy ? &appProx : proxy;
if( prox->type() == QNetworkProxy::NoProxy )
if( p->type() == QNetworkProxy::NoProxy )
{
qDebug() << "Setting proxy to none";
m_client->setConnectionImpl( new gloox::ConnectionTCPClient( m_client.data(), m_client->logInstance(), m_client->server(), m_client->port() ) );
@@ -120,10 +121,10 @@ Jabber_p::go()
// Handle proxy
if( m_client->connect( false ) )
if ( m_client->connect( false ) )
{
emit connected();
m_timer.singleShot(0, this, SLOT(doJabberRecv()));
QTimer::singleShot( 0, this, SLOT( doJabberRecv() ) );
}
}
@@ -131,14 +132,17 @@ Jabber_p::go()
void
Jabber_p::doJabberRecv()
{
ConnectionError ce = m_client->recv(100);
if( ce != ConnNoError )
if ( m_client.isNull() )
return;
ConnectionError ce = m_client->recv( 100 );
if ( ce != ConnNoError )
{
qDebug() << "Jabber_p::Recv failed, disconnected";
}
else
{
m_timer.singleShot(100, this, SLOT(doJabberRecv()));
QTimer::singleShot( 100, this, SLOT( doJabberRecv() ) );
}
}
@@ -146,7 +150,7 @@ Jabber_p::doJabberRecv()
void
Jabber_p::disconnect()
{
if ( m_client )
if ( !m_client.isNull() )
{
m_client->disconnect();
}
@@ -156,7 +160,7 @@ Jabber_p::disconnect()
void
Jabber_p::sendMsg( const QString& to, const QString& msg )
{
if( QThread::currentThread() != thread() )
if ( QThread::currentThread() != thread() )
{
qDebug() << Q_FUNC_INFO << "invoking in correct thread, not"
<< QThread::currentThread();
@@ -169,8 +173,12 @@ Jabber_p::sendMsg( const QString& to, const QString& msg )
return;
}
if ( m_client.isNull() )
return;
qDebug() << Q_FUNC_INFO << to << msg;
Message m( Message::Chat, JID(to.toStdString()), msg.toStdString(), "" );
m_client->send( m ); // assuming this is threadsafe
}
@@ -178,7 +186,7 @@ Jabber_p::sendMsg( const QString& to, const QString& msg )
void
Jabber_p::broadcastMsg( const QString &msg )
{
if( QThread::currentThread() != thread() )
if ( QThread::currentThread() != thread() )
{
QMetaObject::invokeMethod( this, "broadcastMsg",
Qt::QueuedConnection,
@@ -186,6 +194,10 @@ Jabber_p::broadcastMsg( const QString &msg )
);
return;
}
if ( m_client.isNull() )
return;
std::string msg_s = msg.toStdString();
foreach( const QString& jidstr, m_peers.keys() )
{
@@ -202,7 +214,7 @@ Jabber_p::onConnect()
{
// update jid resource, servers like gtalk use resource binding and may
// have changed our requested /resource
if( m_client->resource() != m_jid.resource() )
if ( m_client->resource() != m_jid.resource() )
{
m_jid.setResource( m_client->resource() );
QString jidstr( m_jid.full().c_str() );
@@ -218,15 +230,18 @@ Jabber_p::onDisconnect( ConnectionError e )
{
qDebug() << "Jabber Disconnected";
QString error;
switch(e)
switch( e )
{
case AuthErrorUndefined:
error = " No error occurred, or error condition is unknown";
break;
case SaslAborted:
error = "The receiving entity acknowledges an &lt;abort/&gt; element sent "
"by the initiating entity; sent in reply to the &lt;abort/&gt; element.";
break;
case SaslIncorrectEncoding:
error = "The data provided by the initiating entity could not be processed "
"because the [BASE64] encoding is incorrect (e.g., because the encoding "
@@ -234,6 +249,7 @@ Jabber_p::onDisconnect( ConnectionError e )
"reply to a &lt;response/&gt; element or an &lt;auth/&gt; element with "
"initial response data.";
break;
case SaslInvalidAuthzid:
error = "The authzid provided by the initiating entity is invalid, either "
"because it is incorrectly formatted or because the initiating entity "
@@ -241,58 +257,70 @@ Jabber_p::onDisconnect( ConnectionError e )
"&lt;response/&gt; element or an &lt;auth/&gt; element with initial "
"response data.";
break;
case SaslInvalidMechanism:
error = "The initiating entity did not provide a mechanism or requested a "
"mechanism that is not supported by the receiving entity; sent in reply "
"to an &lt;auth/&gt; element.";
break;
case SaslMalformedRequest:
error = "The request is malformed (e.g., the &lt;auth/&gt; element includes "
"an initial response but the mechanism does not allow that); sent in "
"reply to an &lt;abort/&gt;, &lt;auth/&gt;, &lt;challenge/&gt;, or "
"&lt;response/&gt; element.";
break;
case SaslMechanismTooWeak:
error = "The mechanism requested by the initiating entity is weaker than "
"server policy permits for that initiating entity; sent in reply to a "
"&lt;response/&gt; element or an &lt;auth/&gt; element with initial "
"response data.";
break;
case SaslNotAuthorized:
error = "The authentication failed because the initiating entity did not "
"provide valid credentials (this includes but is not limited to the "
"case of an unknown username); sent in reply to a &lt;response/&gt; "
"element or an &lt;auth/&gt; element with initial response data. ";
break;
case SaslTemporaryAuthFailure:
error = "The authentication failed because of a temporary error condition "
"within the receiving entity; sent in reply to an &lt;auth/&gt; element "
"or &lt;response/&gt; element.";
break;
case NonSaslConflict:
error = "XEP-0078: Resource Conflict";
break;
case NonSaslNotAcceptable:
error = "XEP-0078: Required Information Not Provided";
break;
case NonSaslNotAuthorized:
error = "XEP-0078: Incorrect Credentials";
break;
case ConnAuthenticationFailed:
error = "Authentication failed";
break;
case ConnNoSupportedAuth:
error = "No supported auth mechanism";
break;
default :
error ="UNKNOWN ERROR";
}
qDebug() << "Connection error msg:" << error;
emit authError(e, error);
default :
error = "UNKNOWN ERROR";
}
qDebug() << "Connection error msg:" << error;
emit authError( e, error );
emit disconnected();
// Q_ASSERT(0); //this->exit(1);
// trigger reconnect
}
@@ -322,7 +350,8 @@ Jabber_p::handleMessage( const Message& m, MessageSession * /*session*/ )
QString from = QString::fromStdString( m.from().full() );
QString msg = QString::fromStdString( m.body() );
if( msg.length() == 0 ) return;
if ( !msg.length() )
return;
qDebug() << "Jabber_p::handleMessage" << from << msg;
@@ -340,9 +369,9 @@ void
Jabber_p::handleLog( LogLevel level, LogArea area, const std::string& message )
{
qDebug() << Q_FUNC_INFO
<< "level:" << level
<< "area:" << area
<< "msg:" << message.c_str();
<< "level:" << level
<< "area:" << area
<< "msg:" << message.c_str();
}
@@ -460,7 +489,7 @@ Jabber_p::handleRosterPresence( const RosterItem& item, const std::string& resou
// "going offline" event
if ( !presenceMeansOnline( presence ) &&
( !m_peers.contains( fulljid ) ||
presenceMeansOnline( m_peers.value(fulljid) )
presenceMeansOnline( m_peers.value( fulljid ) )
)
)
{
@@ -571,7 +600,8 @@ Jabber_p::handleDiscoError( const JID& j, const Error* e, int /*context*/ )
/// END DISCO STUFF
bool Jabber_p::presenceMeansOnline( Presence::PresenceType p )
bool
Jabber_p::presenceMeansOnline( Presence::PresenceType p )
{
switch(p)
{

View File

@@ -11,7 +11,6 @@
#include <QMap>
#include <QNetworkProxy>
#include <QThread>
#include <QTimer>
#include <string>
@@ -135,7 +134,6 @@ private:
QMap<gloox::Presence::PresenceType, QString> m_presences;
QMap<QString, gloox::Presence::PresenceType> m_peers;
QSharedPointer<gloox::VCardManager> m_vcardManager;
QTimer m_timer; // for recv()
};
#endif // JABBER_H

View File

@@ -52,8 +52,10 @@ CollectionFlatModel::addCollection( const collection_ptr& collection )
emit loadingStarts();
connect( collection.data(), SIGNAL( tracksAdded( QList<QVariant>, Tomahawk::collection_ptr ) ),
SLOT( onTracksAdded( QList<QVariant>, Tomahawk::collection_ptr ) ) );
onTracksAdded( collection->tracks(), collection );
connect( collection.data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr>, Tomahawk::collection_ptr ) ),
SLOT( onTracksAdded( QList<Tomahawk::query_ptr>, Tomahawk::collection_ptr ) ) );
connect( collection.data(), SIGNAL( tracksFinished( Tomahawk::collection_ptr ) ),
SLOT( onTracksAddingFinished( Tomahawk::collection_ptr ) ) );
}
@@ -62,8 +64,8 @@ CollectionFlatModel::addCollection( const collection_ptr& collection )
void
CollectionFlatModel::removeCollection( const collection_ptr& collection )
{
disconnect( collection.data(), SIGNAL( tracksAdded( QList<QVariant>, Tomahawk::collection_ptr ) ),
this, SLOT( onTracksAdded( QList<QVariant>, Tomahawk::collection_ptr ) ) );
disconnect( collection.data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr>, Tomahawk::collection_ptr ) ),
this, SLOT( onTracksAdded( QList<Tomahawk::query_ptr>, Tomahawk::collection_ptr ) ) );
disconnect( collection.data(), SIGNAL( tracksFinished( Tomahawk::collection_ptr ) ),
this, SLOT( onTracksAddingFinished( Tomahawk::collection_ptr ) ) );
@@ -126,7 +128,7 @@ CollectionFlatModel::removeCollection( const collection_ptr& collection )
void
CollectionFlatModel::onTracksAdded( const QList<QVariant>& tracks, const collection_ptr& collection )
CollectionFlatModel::onTracksAdded( const QList<Tomahawk::query_ptr>& tracks, const Tomahawk::collection_ptr& collection )
{
int c = rowCount( QModelIndex() );
QPair< int, int > crows;
@@ -136,25 +138,12 @@ CollectionFlatModel::onTracksAdded( const QList<QVariant>& tracks, const collect
emit beginInsertRows( QModelIndex(), crows.first, crows.second );
PlItem* plitem;
foreach( const QVariant& v, tracks )
foreach( const query_ptr& query, tracks )
{
Tomahawk::query_ptr query = query_ptr( new Query( v ) );
// FIXME: needs merging
// Manually add a result, since it's coming from the local collection
QVariantMap t = query->toVariant().toMap();
t["score"] = 1.0;
QList<result_ptr> results;
result_ptr result = result_ptr( new Result( t, collection ) );
results << result;
query->addResults( results );
plitem = new PlItem( query, m_rootItem );
plitem->index = createIndex( m_rootItem->children.count() - 1, 0, plitem );
connect( plitem, SIGNAL( dataChanged() ), SLOT( onDataChanged() ) );
// m_collectionIndex.insertMulti( collection, plitem );
}
m_collectionRows.insertMulti( collection, crows );
@@ -166,9 +155,10 @@ CollectionFlatModel::onTracksAdded( const QList<QVariant>& tracks, const collect
void
CollectionFlatModel::onTracksAddingFinished( const Tomahawk::collection_ptr& /* collection */ )
CollectionFlatModel::onTracksAddingFinished( const Tomahawk::collection_ptr& collection )
{
qDebug() << "Finished loading tracks";
qDebug() << "Finished loading tracks" << collection->source()->friendlyName();
emit loadingFinished();
}

View File

@@ -44,7 +44,7 @@ signals:
private slots:
void onDataChanged();
void onTracksAdded( const QList<QVariant>& tracks, const Tomahawk::collection_ptr& collection );
void onTracksAdded( const QList<Tomahawk::query_ptr>& tracks, const Tomahawk::collection_ptr& collection );
void onTracksAddingFinished( const Tomahawk::collection_ptr& collection );
void onSourceOffline( const Tomahawk::source_ptr& src );

View File

@@ -239,9 +239,15 @@ CollectionModel::onTracksAdded( const QList<QVariant>& tracks, const collection_
void
CollectionModel::onTracksAddingFinished( const Tomahawk::collection_ptr& /* collection */ )
CollectionModel::onTracksAddingFinished( const Tomahawk::collection_ptr& collection )
{
qDebug() << "Finished loading tracks";
qDebug() << "Finished loading tracks" << collection->source()->friendlyName();
disconnect( collection.data(), SIGNAL( tracksAdded( QList<QVariant>, Tomahawk::collection_ptr ) ),
this, SLOT( onTracksAdded( QList<QVariant>, Tomahawk::collection_ptr ) ) );
disconnect( collection.data(), SIGNAL( tracksFinished( Tomahawk::collection_ptr ) ),
this, SLOT( onTracksAddingFinished( Tomahawk::collection_ptr ) ) );
emit loadingFinished();
}

View File

@@ -53,7 +53,7 @@ PlaylistItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& opti
else
painter->setOpacity( 0.3 );
if ( item->isPlaying() )
if ( item->isPlaying() )
{
painter->save();
painter->setRenderHint( QPainter::Antialiasing );
@@ -67,7 +67,7 @@ PlaylistItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& opti
}
painter->setPen( option.palette.text().color() );
painter->drawText( r, index.data().toString() );
painter->drawText( r.adjusted( 0, 2, 0, 0 ), index.data().toString() );
}
if ( index.column() == index.model()->columnCount() - 1 )

View File

@@ -14,18 +14,20 @@
PlaylistManager::PlaylistManager( QObject* parent )
: QObject( parent )
, m_widget( new QStackedWidget() )
, m_superCollectionModel( new CollectionModel() )
, m_superCollectionFlatModel( new CollectionFlatModel() )
, m_currentProxyModel( 0 )
, m_currentModel( 0 )
, m_currentView( 0 )
, m_currentMode( 0 )
, m_superCollectionVisible( true )
{
m_widget->setMinimumWidth( 620 );
m_superCollectionViews << new CollectionView();
m_superCollectionViews.first()->setModel( m_superCollectionFlatModel );
m_widget->addWidget( m_superCollectionViews.first() );
m_superCollectionView = new CollectionView();
m_superCollectionFlatModel = new CollectionFlatModel( m_superCollectionView );
m_superCollectionView->setModel( m_superCollectionFlatModel );
m_widget->addWidget( m_superCollectionView );
m_currentView = m_superCollectionView;
connect( &m_filterTimer, SIGNAL( timeout() ), SLOT( applyFilter() ) );
}
@@ -61,6 +63,7 @@ PlaylistManager::show( const Tomahawk::playlist_ptr& playlist )
m_views.insert( playlist, views );
m_widget->addWidget( views.first() );
m_widget->setCurrentWidget( views.first() );
m_currentView = views.first();
}
else
{
@@ -68,13 +71,13 @@ PlaylistManager::show( const Tomahawk::playlist_ptr& playlist )
m_widget->setCurrentWidget( views.first() );
m_currentProxyModel = views.first()->proxyModel();
m_currentModel = views.first()->model();
m_currentView = views.first();
}
m_superCollectionVisible = false;
linkPlaylist();
emit numSourcesChanged( APP->sourcelist().count() );
return true;
}
@@ -82,42 +85,68 @@ PlaylistManager::show( const Tomahawk::playlist_ptr& playlist )
bool
PlaylistManager::show( const Tomahawk::collection_ptr& collection )
{
if ( m_superCollectionVisible )
{
if ( !m_superCollections.contains( collection ) )
{
m_superCollections.append( collection );
m_superCollectionFlatModel->addCollection( collection );
collection->loadAllTracks();
}
else
{
m_superCollectionFlatModel->removeCollection( collection );
m_superCollections.removeAll( collection );
}
}
unlinkPlaylist();
if ( m_currentMode == 0 )
if ( !m_collectionViews.contains( collection ) )
{
m_widget->setCurrentWidget( m_superCollectionViews.first() );
m_currentProxyModel = m_superCollectionViews.first()->proxyModel();
m_currentModel = m_superCollectionViews.first()->model();
QList<CollectionView*> views;
{
CollectionView* view = new CollectionView();
CollectionFlatModel* model = new CollectionFlatModel();
view->setModel( model );
views << view;
m_currentProxyModel = view->proxyModel();
m_currentModel = view->model();
model->addCollection( collection );
// collection->loadAllTracks();
}
m_collectionViews.insert( collection, views );
m_widget->addWidget( views.first() );
m_widget->setCurrentWidget( views.first() );
m_currentView = views.first();
}
else
{
m_widget->setCurrentWidget( m_superCollectionViews.at( 1 ) );
m_currentProxyModel = m_superCollectionViews.at( 1 )->proxyModel();
m_currentModel = m_superCollectionViews.at( 1 )->model();
QList<CollectionView*> views = m_collectionViews.value( collection );
m_widget->setCurrentWidget( views.first() );
m_currentProxyModel = views.first()->proxyModel();
m_currentModel = views.first()->model();
m_currentView = views.first();
}
m_superCollectionVisible = false;
linkPlaylist();
emit numSourcesChanged( 1 );
return true;
}
bool
PlaylistManager::showSuperCollection()
{
foreach( const Tomahawk::source_ptr& source, APP->sourcelist().sources() )
{
if ( !m_superCollections.contains( source->collection() ) )
{
m_superCollections.append( source->collection() );
m_superCollectionFlatModel->addCollection( source->collection() );
// source->collection()->loadAllTracks();
}
}
m_widget->setCurrentWidget( m_superCollectionView );
m_currentProxyModel = m_superCollectionView->proxyModel();
m_currentModel = m_superCollectionView->model();
m_currentView = m_superCollectionView;
m_superCollectionVisible = true;
linkPlaylist();
emit numSourcesChanged( m_superCollections.count() );
return true;
}
@@ -130,7 +159,7 @@ PlaylistManager::setTreeMode()
qDebug() << Q_FUNC_INFO;
m_currentMode = 1;
m_widget->setCurrentWidget( m_superCollectionViews.at( 1 ) );
m_widget->setCurrentWidget( m_superCollectionView );
}
@@ -140,7 +169,7 @@ PlaylistManager::setTableMode()
qDebug() << Q_FUNC_INFO;
m_currentMode = 0;
m_widget->setCurrentWidget( m_superCollectionViews.first() );
m_widget->setCurrentWidget( m_superCollectionView );
}
@@ -235,3 +264,11 @@ PlaylistManager::setShuffled( bool enabled )
if ( m_currentProxyModel )
m_currentProxyModel->setShuffled( enabled );
}
void
PlaylistManager::showCurrentTrack()
{
if ( m_currentView && m_currentProxyModel )
m_currentView->scrollTo( m_currentProxyModel->currentItem(), QAbstractItemView::PositionAtCenter );
}

View File

@@ -14,6 +14,7 @@ class CollectionView;
class PlaylistView;
class TrackProxyModel;
class TrackModel;
class TrackView;
class PlaylistManager : public QObject
{
@@ -26,12 +27,14 @@ public:
QWidget* widget() const { return m_widget; }
bool isSuperCollectionVisible() const { return true; }
QList< Tomahawk::collection_ptr > superCollections() const { return m_superCollections; }
QList<PlaylistView*> views( const Tomahawk::playlist_ptr& playlist ) { return m_views.value( playlist ); }
bool show( const Tomahawk::playlist_ptr& playlist );
bool show( const Tomahawk::collection_ptr& collection );
bool showSuperCollection();
void showCurrentTrack();
signals:
void numSourcesChanged( unsigned int sources );
@@ -61,14 +64,17 @@ private:
QStackedWidget* m_widget;
CollectionModel* m_superCollectionModel;
CollectionFlatModel* m_superCollectionFlatModel;
QList<CollectionView*> m_superCollectionViews;
CollectionView* m_superCollectionView;
QList< Tomahawk::collection_ptr > m_superCollections;
QHash< Tomahawk::collection_ptr, QList<CollectionView*> > m_collectionViews;
QHash< Tomahawk::playlist_ptr, QList<PlaylistView*> > m_views;
TrackProxyModel* m_currentProxyModel;
TrackModel* m_currentModel;
TrackView* m_currentView;
int m_currentMode;
bool m_superCollectionVisible;

View File

@@ -45,9 +45,12 @@ Source::~Source()
}
collection_ptr Source::collection() const
collection_ptr
Source::collection() const
{
if( m_collections.length() ) return m_collections.first();
if( m_collections.length() )
return m_collections.first();
collection_ptr tmp;
return tmp;
}

View File

@@ -38,8 +38,8 @@ SourceList::add( const Tomahawk::source_ptr& s )
m_local = s;
}
}
emit sourceAdded( s );
s->collection()->loadPlaylists();
}
@@ -65,6 +65,7 @@ SourceList::remove( Tomahawk::Source* s )
m_sources.remove( s->userName() );
qDebug() << "SourceList::remove(" << s->userName() << "), total sources now:" << m_sources.size();
}
emit sourceRemoved( src );
}

View File

@@ -24,9 +24,6 @@ SourcesModel::SourcesModel( QObject* parent )
connect( parent, SIGNAL( onOnline( QModelIndex ) ), SLOT( onItemOnline( QModelIndex ) ) );
connect( parent, SIGNAL( onOffline( QModelIndex ) ), SLOT( onItemOffline( QModelIndex ) ) );
// load sources after the view initialised completely
// QTimer::singleShot( 0, this, SLOT( loadSources() ) );
}

View File

@@ -16,15 +16,20 @@ SourceTreeItem::SourceTreeItem( const source_ptr& source, QObject* parent )
{
QStandardItem* item = new QStandardItem( "" );
item->setEditable( false );
item->setData( (qlonglong)this, Qt::UserRole + 2 );
item->setData( 0, Qt::UserRole + 1 );
item->setData( (qlonglong)this, Qt::UserRole + 2 );
m_columns << item;
connect( source.data()->collection().data(), SIGNAL( playlistsAdded( QList<Tomahawk::playlist_ptr> ) ),
SLOT( onPlaylistsAdded( QList<Tomahawk::playlist_ptr> ) ) );
if ( !source.isNull() )
{
onPlaylistsAdded( source->collection()->playlists() );
connect( source.data()->collection().data(), SIGNAL( playlistsDeleted( QList<Tomahawk::playlist_ptr> ) ),
SLOT( onPlaylistsDeleted( QList<Tomahawk::playlist_ptr> ) ) );
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> ) ) );
}
m_widget = new SourceTreeItemWidget( source, (QWidget*)parent->parent() );
connect( m_widget, SIGNAL( clicked() ), SLOT( onClicked() ) );
@@ -55,8 +60,6 @@ SourceTreeItem::onOffline()
void
SourceTreeItem::onPlaylistsAdded( const QList<playlist_ptr>& playlists )
{
// qDebug() << playlists;
// const-ness is important for getting the right pointer!
foreach( const playlist_ptr& p, playlists )
{

View File

@@ -16,23 +16,36 @@ SourceTreeItemWidget::SourceTreeItemWidget( const source_ptr& source, QWidget* p
ui( new Ui::SourceTreeItemWidget )
{
// qDebug() << Q_FUNC_INFO;
ui->setupUi( this );
ui->verticalLayout->setSpacing( 3 );
connect( source.data(), SIGNAL( loadingStateChanged( DBSyncConnection::State, DBSyncConnection::State, QString ) ),
SLOT( onLoadingStateChanged( DBSyncConnection::State, DBSyncConnection::State, QString ) ) );
QString displayname;
if ( source.isNull() )
{
ui->avatarImage->setPixmap( QPixmap( RESPATH "images/user-avatar.png" ) );
connect( source.data(), SIGNAL( stats( const QVariantMap& ) ), SLOT( gotStats( const QVariantMap& ) ) );
displayname = tr( "Super Collection" );
ui->infoLabel->setText( tr( "All available tracks" ) );
}
else
{
connect( source.data(), SIGNAL( loadingStateChanged( DBSyncConnection::State, DBSyncConnection::State, QString ) ),
SLOT( onLoadingStateChanged( DBSyncConnection::State, DBSyncConnection::State, QString ) ) );
ui->avatarImage->setPixmap( QPixmap( RESPATH "images/user-avatar.png" ) );
connect( source.data(), SIGNAL( stats( QVariantMap ) ), SLOT( gotStats( QVariantMap ) ) );
QString displayname = source->friendlyName();
if( displayname.isEmpty() )
displayname = source->userName();
ui->avatarImage->setPixmap( QPixmap( RESPATH "images/user-avatar.png" ) );
displayname = source->friendlyName();
if( displayname.isEmpty() )
displayname = source->userName();
ui->infoLabel->setText( "???" );
}
ui->nameLabel->setText( displayname );
ui->infoLabel->setForegroundRole( QPalette::Dark );
ui->infoLabel->setText( "???" );
connect( ui->onOffButton, SIGNAL( clicked() ), SIGNAL( clicked() ) );
@@ -106,12 +119,14 @@ SourceTreeItemWidget::onLoadingStateChanged( DBSyncConnection::State newstate, D
void
SourceTreeItemWidget::onOnline()
{
ui->onOffButton->setPixmap( RESPATH "images/source-on-rest.png" );
if ( !m_source.isNull() )
ui->onOffButton->setPixmap( RESPATH "images/source-on-rest.png" );
}
void
SourceTreeItemWidget::onOffline()
{
ui->onOffButton->setPixmap( RESPATH "images/source-off-rest.png" );
if ( !m_source.isNull() )
ui->onOffButton->setPixmap( RESPATH "images/source-off-rest.png" );
}

View File

@@ -53,6 +53,7 @@ SourceTreeView::SourceTreeView( QWidget* parent )
setAllColumnsShowFocus( true );
setUniformRowHeights( false );
setIndentation( 0 );
setAnimated( false );
setItemDelegate( new SourceDelegate( this ) );
@@ -70,6 +71,8 @@ SourceTreeView::SourceTreeView( QWidget* parent )
connect( selectionModel(), SIGNAL( selectionChanged( const QItemSelection&, const QItemSelection& ) ), SLOT( onSelectionChanged() ) );
connect( &APP->sourcelist(), SIGNAL( sourceRemoved( Tomahawk::source_ptr ) ), SLOT( onSourceOffline( Tomahawk::source_ptr ) ) );
m_model->appendItem( source_ptr() );
}
@@ -123,19 +126,23 @@ SourceTreeView::onItemActivated( const QModelIndex& index )
SourceTreeItem* item = SourcesModel::indexToTreeItem( index );
if ( item )
{
if ( APP->playlistManager()->isSuperCollectionVisible() )
if ( item->source().isNull() )
{
APP->playlistManager()->showSuperCollection();
}
else
{
qDebug() << "SourceTreeItem toggled:" << item->source()->userName();
APP->playlistManager()->show( item->source()->collection() );
if ( APP->playlistManager()->superCollections().contains( item->source()->collection() ) )
/*if ( APP->playlistManager()->superCollections().contains( item->source()->collection() ) )
{
emit onOnline( index );
}
else
{
emit onOffline( index );
}
}*/
}
}
}
@@ -155,14 +162,14 @@ SourceTreeView::onItemActivated( const QModelIndex& index )
void
SourceTreeView::onSelectionChanged()
{
QModelIndexList si = selectedIndexes();
/* QModelIndexList si = selectedIndexes();
foreach( const QModelIndex& idx, si )
{
int type = SourcesModel::indexType( idx );
if ( type == 0 )
selectionModel()->select( idx, QItemSelectionModel::Deselect );
}
}*/
}

View File

@@ -428,12 +428,11 @@ TomahawkApp::loadPlugins()
void
TomahawkApp::setupJabber() //const QString& jid, const QString& pass, const QString server
TomahawkApp::setupJabber()
{
qDebug() << Q_FUNC_INFO;
if( !m_jabber.isNull() )
if ( !m_jabber.isNull() )
return;
if ( !m_settings->value( "jabber/autoconnect", true ).toBool() )
return;
@@ -443,9 +442,7 @@ TomahawkApp::setupJabber() //const QString& jid, const QString& pass, const QStr
unsigned int port = m_settings->value( "jabber/port", 5222 ).toUInt();
// gtalk check
if( server.isEmpty() && (
jid.contains("@gmail.com") ||
jid.contains("@googlemail.com") ) )
if( server.isEmpty() && ( jid.contains("@gmail.com") || jid.contains("@googlemail.com") ) )
{
qDebug() << "Setting jabber server to talk.google.com";
server = "talk.google.com";
@@ -459,17 +456,13 @@ TomahawkApp::setupJabber() //const QString& jid, const QString& pass, const QStr
m_jabber = QSharedPointer<Jabber>( new Jabber( jid, password, server, port ) );
connect( m_jabber.data(), SIGNAL( peerOnline( const QString& ) ),
SLOT( jabberPeerOnline( const QString& ) ) );
connect( m_jabber.data(), SIGNAL( peerOffline( const QString& ) ),
SLOT( jabberPeerOffline( const QString& ) ) );
connect( m_jabber.data(), SIGNAL( msgReceived( const QString&, const QString& ) ),
SLOT( jabberMessage( const QString&, const QString& ) ) );
connect( m_jabber.data(), SIGNAL( peerOnline( QString ) ), SLOT( jabberPeerOnline( QString ) ) );
connect( m_jabber.data(), SIGNAL( peerOffline( QString ) ), SLOT( jabberPeerOffline( QString ) ) );
connect( m_jabber.data(), SIGNAL( msgReceived( QString, QString ) ), SLOT( jabberMessage( QString, QString ) ) );
connect( m_jabber.data(), SIGNAL( disconnected() ), SLOT( jabberDisconnected() ) );
//connect( m_jabber.data(), SIGNAL( finished() ), SLOT( jabberDisconnected() ) );
connect( m_jabber.data(), SIGNAL( connected() ), SLOT( jabberConnected() ) );
connect( m_jabber.data(), SIGNAL( authError(int, const QString&) ), SLOT( jabberAuthError(int,const QString&) ) );
connect( m_jabber.data(), SIGNAL( disconnected() ), SLOT( jabberDisconnected() ) );
connect( m_jabber.data(), SIGNAL( authError( int, QString ) ), SLOT( jabberAuthError( int, QString ) ) );
m_jabber->setProxy( m_proxy );
m_jabber->start();
@@ -502,6 +495,9 @@ TomahawkApp::jabberAuthError( int code, const QString& msg )
QMessageBox::Ok );
}
#endif
if ( code != gloox::ConnAuthenticationFailed )
QTimer::singleShot( 10000, this, SLOT( reconnectJabber() ) );
}
@@ -534,7 +530,6 @@ TomahawkApp::jabberDisconnected()
.arg( (servent().externalPort() > 0) ? QString( "YES:%1" ).arg(servent().externalPort()):"NO" ) );
}
#endif
m_jabber.clear();
}