mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-09-06 20:20:41 +02:00
Compare commits
37 Commits
hugolm84-t
...
0.2.2
Author | SHA1 | Date | |
---|---|---|---|
|
13ab10adea | ||
|
20d2a5ff59 | ||
|
6b9eec00fd | ||
|
d7416ddd57 | ||
|
2e9aa7f3b3 | ||
|
208393deb0 | ||
|
b923d4f994 | ||
|
edbee5a922 | ||
|
e0bdc4b8bc | ||
|
4b53d20663 | ||
|
74c4f4ddc2 | ||
|
ec03ece35c | ||
|
d217e7fae0 | ||
|
bc3bcc708f | ||
|
7a90ba11bb | ||
|
ed219a56cd | ||
|
1537d5b08a | ||
|
263340a270 | ||
|
bf54ebf7fe | ||
|
bfbac296b0 | ||
|
7971e7aadc | ||
|
4cc1690dea | ||
|
2090d76955 | ||
|
d09397a8ab | ||
|
a734cad4e1 | ||
|
9b433379ee | ||
|
2e11376d01 | ||
|
9ba11290ae | ||
|
97e0bbaf38 | ||
|
eb4242622d | ||
|
469bea43ba | ||
|
f9f3a45a31 | ||
|
0579d63013 | ||
|
1bb115ec6f | ||
|
5f320028b8 | ||
|
b0d445c262 | ||
|
479a0c469f |
@@ -16,7 +16,7 @@ SET( TOMAHAWK_DESCRIPTION_SUMMARY "The social media player" )
|
||||
|
||||
SET( TOMAHAWK_VERSION_MAJOR 0 )
|
||||
SET( TOMAHAWK_VERSION_MINOR 2 )
|
||||
SET( TOMAHAWK_VERSION_PATCH 1 )
|
||||
SET( TOMAHAWK_VERSION_PATCH 2 )
|
||||
|
||||
#SET( TOMAHAWK_VERSION_RC 0 )
|
||||
|
||||
|
@@ -203,7 +203,7 @@ Function PageReinstall
|
||||
IntCmp $R0 ${VER_MINOR} build_check new_version older_version
|
||||
build_check:
|
||||
ReadRegDWORD $R0 HKLM "Software\Tomahawk" "VersionBuild"
|
||||
IntCmp $R0 ${VER_BUILD} new_version older_version
|
||||
IntCmp $R0 ${VER_BUILD} same_version new_version older_version
|
||||
|
||||
new_version:
|
||||
!insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 1" "Text" "An older version of Tomahawk is installed on your system. It is recommended that you uninstall the current version before installing. Select the operation you want to perform and click Next to continue."
|
||||
|
@@ -1,3 +1,12 @@
|
||||
Version 0.2.2:
|
||||
* Fixed crash when pressing previous and next when playing a song from the Queue.
|
||||
* Fixed issue where wrench for newly added resolvers would not show up immediately.
|
||||
* Fixed sidebar statistics not updating after collection scan finished.
|
||||
* Fixed omitting a few tracks in the Collection tree-view.
|
||||
* Fixed sidebar & track sorting issues.
|
||||
* Seek- & volume sliders now directly jump to the position you clicked on.
|
||||
* Added ability to drag artists and albums within Tomahawk (to playlists, queue, etc.).
|
||||
|
||||
Version 0.2.1:
|
||||
* Fixed crashing trying to play an unavailable track.
|
||||
* Fixed a crash caused by using Javascript resolvers.
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 19 KiB |
@@ -237,7 +237,6 @@ TARGET_LINK_LIBRARIES( tomahawk
|
||||
${QXTWEB_LIBRARIES}
|
||||
${QJSON_LIBRARIES}
|
||||
${TAGLIB_LIBRARIES}
|
||||
${CLUCENE_LIBRARIES}
|
||||
)
|
||||
|
||||
|
||||
|
@@ -35,6 +35,7 @@
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "utils/logger.h"
|
||||
#include <globalactionmanager.h>
|
||||
#include "dropjob.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
@@ -90,56 +91,9 @@ AudioControls::AudioControls( QWidget* parent )
|
||||
ui->ownerLabel->setForegroundRole( QPalette::Dark );
|
||||
ui->metaDataArea->setStyleSheet( "QWidget#metaDataArea {\nborder-width: 4px;\nborder-image: url(" RESPATH "images/now-playing-panel.png) 4 4 4 4 stretch stretch; }" );
|
||||
|
||||
ui->seekSlider->setFixedHeight( 20 );
|
||||
ui->seekSlider->setEnabled( true );
|
||||
ui->seekSlider->setStyleSheet( "QSlider::groove::horizontal {"
|
||||
"margin: 5px; border-width: 3px;"
|
||||
"border-image: url(" RESPATH "images/seek-slider-bkg.png) 3 3 3 3 stretch stretch;"
|
||||
"}"
|
||||
|
||||
"QSlider::sub-page:horizontal {"
|
||||
"margin: 5px; border-width: 3px;"
|
||||
"border-image: url(" RESPATH "images/seek-slider-level.png) 3 3 3 3 stretch stretch;"
|
||||
"}"
|
||||
|
||||
"QSlider::handle::horizontal {"
|
||||
"margin-bottom: -7px; margin-top: -7px;"
|
||||
"margin-left: -4px; margin-right: -4px;"
|
||||
"height: 17px; width: 16px;"
|
||||
"background-image: url(" RESPATH "images/seek-and-volume-knob-rest.png);"
|
||||
"background-repeat: no-repeat;"
|
||||
"}" );
|
||||
|
||||
ui->volumeSlider->setFixedHeight( 20 );
|
||||
ui->volumeSlider->setRange( 0, 100 );
|
||||
ui->volumeSlider->setValue( AudioEngine::instance()->volume() );
|
||||
ui->volumeSlider->setStyleSheet( "QSlider::groove::horizontal {"
|
||||
"margin: 5px; border-width: 3px;"
|
||||
"border-image: url(" RESPATH "images/volume-slider-bkg.png) 3 3 3 3 stretch stretch;"
|
||||
"}"
|
||||
|
||||
"QSlider::sub-page:horizontal {"
|
||||
"margin: 5px; border-width: 3px;"
|
||||
"border-image: url(" RESPATH "images/seek-slider-level.png) 3 3 3 3 stretch stretch;"
|
||||
"}"
|
||||
|
||||
"QSlider::handle::horizontal {"
|
||||
"margin-bottom: -7px; margin-top: -7px;"
|
||||
"margin-left: -4px; margin-right: -4px;"
|
||||
"height: 17px; width: 16px;"
|
||||
"background-image: url(" RESPATH "images/seek-and-volume-knob-rest.png);"
|
||||
"background-repeat: no-repeat;"
|
||||
"}" );
|
||||
|
||||
/* m_playAction = new QAction( this );
|
||||
m_pauseAction = new QAction( this );
|
||||
m_prevAction = new QAction( this );
|
||||
m_nextAction = new QAction( this );
|
||||
|
||||
connect( m_playAction, SIGNAL( triggered() ), (QObject*)APP->audioEngine(), SLOT( play() ) );
|
||||
connect( m_pauseAction, SIGNAL( triggered() ), (QObject*)APP->audioEngine(), SLOT( pause() ) );
|
||||
connect( m_prevAction, SIGNAL( triggered() ), (QObject*)APP->audioEngine(), SLOT( previous() ) );
|
||||
connect( m_nextAction, SIGNAL( triggered() ), (QObject*)APP->audioEngine(), SLOT( next() ) ); */
|
||||
|
||||
connect( ui->seekSlider, SIGNAL( valueChanged( int ) ), AudioEngine::instance(), SLOT( seek( int ) ) );
|
||||
connect( ui->volumeSlider, SIGNAL( valueChanged( int ) ), AudioEngine::instance(), SLOT( setVolume( int ) ) );
|
||||
@@ -179,7 +133,6 @@ AudioControls::AudioControls( QWidget* parent )
|
||||
|
||||
connect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ), SLOT( infoSystemFinished( QString ) ) );
|
||||
|
||||
|
||||
ui->buttonAreaLayout->setSpacing( 0 );
|
||||
ui->stackedLayout->setSpacing( 0 );
|
||||
ui->stackedLayout->setContentsMargins( 0, 0, 0, 0 );
|
||||
@@ -305,9 +258,6 @@ AudioControls::onPlaybackLoading( const Tomahawk::result_ptr& result )
|
||||
ui->seekSlider->setValue( 0 );
|
||||
ui->seekSlider->setVisible( true );
|
||||
|
||||
/* m_playAction->setEnabled( false );
|
||||
m_pauseAction->setEnabled( true ); */
|
||||
|
||||
ui->stackedLayout->setCurrentWidget( ui->pauseButton );
|
||||
|
||||
ui->loveButton->setEnabled( true );
|
||||
@@ -343,18 +293,12 @@ AudioControls::socialActionsLoaded()
|
||||
void
|
||||
AudioControls::onPlaybackPaused()
|
||||
{
|
||||
/* m_pauseAction->setEnabled( false );
|
||||
m_playAction->setEnabled( true ); */
|
||||
|
||||
ui->stackedLayout->setCurrentWidget( ui->playPauseButton );
|
||||
}
|
||||
|
||||
void
|
||||
AudioControls::onPlaybackResumed()
|
||||
{
|
||||
/* m_playAction->setEnabled( false );
|
||||
m_pauseAction->setEnabled( true ); */
|
||||
|
||||
ui->stackedLayout->setCurrentWidget( ui->pauseButton );
|
||||
ui->loveButton->setVisible( true );
|
||||
}
|
||||
@@ -376,9 +320,6 @@ AudioControls::onPlaybackStopped()
|
||||
ui->stackedLayout->setCurrentWidget( ui->playPauseButton );
|
||||
ui->loveButton->setEnabled( false );
|
||||
ui->loveButton->setVisible( false );
|
||||
|
||||
/* m_pauseAction->setEnabled( false );
|
||||
m_playAction->setEnabled( true ); */
|
||||
}
|
||||
|
||||
|
||||
@@ -521,7 +462,7 @@ AudioControls::onTrackClicked()
|
||||
void
|
||||
AudioControls::dragEnterEvent( QDragEnterEvent* e )
|
||||
{
|
||||
if ( GlobalActionManager::instance()->acceptsMimeData( e->mimeData() ) )
|
||||
if ( DropJob::acceptsMimeData( e->mimeData() ) )
|
||||
e->acceptProposedAction();
|
||||
}
|
||||
|
||||
@@ -538,10 +479,11 @@ void
|
||||
AudioControls::dropEvent( QDropEvent* e )
|
||||
{
|
||||
tDebug() << "AudioControls got drop:" << e->mimeData()->formats();
|
||||
if ( GlobalActionManager::instance()->acceptsMimeData( e->mimeData() ) )
|
||||
if ( DropJob::acceptsMimeData( e->mimeData() ) )
|
||||
{
|
||||
connect( GlobalActionManager::instance(), SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( droppedTracks( QList<Tomahawk::query_ptr> ) ) );
|
||||
GlobalActionManager::instance()->tracksFromMimeData( e->mimeData() );
|
||||
DropJob *dj = new DropJob();
|
||||
connect( dj, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( droppedTracks( QList<Tomahawk::query_ptr> ) ) );
|
||||
dj->tracksFromMimeData( e->mimeData() );
|
||||
|
||||
e->accept();
|
||||
}
|
||||
@@ -551,8 +493,6 @@ AudioControls::dropEvent( QDropEvent* e )
|
||||
void
|
||||
AudioControls::droppedTracks( QList< query_ptr > tracks )
|
||||
{
|
||||
disconnect( GlobalActionManager::instance(), SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( droppedTracks( QList<Tomahawk::query_ptr> ) ) );
|
||||
|
||||
if ( !tracks.isEmpty() )
|
||||
{
|
||||
// queue and play the first if nothign is playing
|
||||
|
@@ -82,11 +82,6 @@ private slots:
|
||||
private:
|
||||
Ui::AudioControls *ui;
|
||||
|
||||
QAction* m_playAction;
|
||||
QAction* m_pauseAction;
|
||||
QAction* m_prevAction;
|
||||
QAction* m_nextAction;
|
||||
|
||||
QPixmap m_defaultCover;
|
||||
|
||||
Tomahawk::result_ptr m_currentTrack;
|
||||
|
@@ -337,7 +337,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="seekSlider">
|
||||
<widget class="SeekSlider" name="seekSlider">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
@@ -489,7 +489,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="volumeSlider">
|
||||
<widget class="SeekSlider" name="volumeSlider">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
@@ -529,6 +529,11 @@
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SeekSlider</class>
|
||||
<extends>QSlider</extends>
|
||||
<header location="global">widgets/SeekSlider.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ImageButton</class>
|
||||
<extends>QPushButton</extends>
|
||||
|
@@ -31,6 +31,7 @@ set( libSources
|
||||
viewmanager.cpp
|
||||
globalactionmanager.cpp
|
||||
contextmenu.cpp
|
||||
dropjob.cpp
|
||||
|
||||
sip/SipPlugin.cpp
|
||||
sip/SipHandler.cpp
|
||||
@@ -176,6 +177,7 @@ set( libSources
|
||||
|
||||
widgets/newplaylistwidget.cpp
|
||||
widgets/searchwidget.cpp
|
||||
widgets/SeekSlider.cpp
|
||||
widgets/playlisttypeselectordlg.cpp
|
||||
widgets/welcomewidget.cpp
|
||||
widgets/welcomeplaylistmodel.cpp
|
||||
@@ -208,6 +210,7 @@ set( libHeaders
|
||||
viewmanager.h
|
||||
globalactionmanager.h
|
||||
contextmenu.h
|
||||
dropjob.h
|
||||
|
||||
artist.h
|
||||
album.h
|
||||
@@ -354,6 +357,7 @@ set( libHeaders
|
||||
|
||||
widgets/newplaylistwidget.h
|
||||
widgets/searchwidget.h
|
||||
widgets/SeekSlider.h
|
||||
widgets/playlisttypeselectordlg.h
|
||||
widgets/welcomewidget.h
|
||||
widgets/welcomeplaylistmodel.h
|
||||
|
@@ -212,7 +212,7 @@ AudioEngine::next()
|
||||
return;
|
||||
|
||||
if ( !m_currentTrack.isNull() && !m_playlist.data()->hasNextItem() &&
|
||||
m_currentTrack->id() == m_playlist.data()->currentItem()->id() )
|
||||
( m_playlist.data()->currentItem().isNull() || ( m_currentTrack->id() == m_playlist.data()->currentItem()->id() ) ) )
|
||||
{
|
||||
//For instance, when doing a catch-up while listening along, but the person
|
||||
//you're following hasn't started a new track yet...don't do anything
|
||||
@@ -487,8 +487,6 @@ AudioEngine::playItem( Tomahawk::PlaylistInterface* playlist, const Tomahawk::re
|
||||
{
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : result->url() );
|
||||
|
||||
if ( !result->isOnline() )
|
||||
return;
|
||||
if ( !m_playlist.isNull() )
|
||||
m_playlist.data()->reset();
|
||||
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include "databasecommand_collectionstats.h"
|
||||
#include "databaseimpl.h"
|
||||
#include "network/controlconnection.h"
|
||||
#include "sourcelist.h"
|
||||
|
||||
#include "utils/logger.h"
|
||||
|
||||
@@ -72,7 +73,15 @@ DatabaseCommand_AddFiles::postCommitHook()
|
||||
emit notify( m_queries );
|
||||
|
||||
if( source()->isLocal() )
|
||||
{
|
||||
Servent::instance()->triggerDBSync();
|
||||
|
||||
// Re-calculate local db stats
|
||||
DatabaseCommand_CollectionStats* cmd = new DatabaseCommand_CollectionStats( SourceList::instance()->getLocal() );
|
||||
connect( cmd, SIGNAL( done( QVariantMap ) ),
|
||||
SourceList::instance()->getLocal().data(), SLOT( setStats( QVariantMap ) ), Qt::QueuedConnection );
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -74,8 +74,7 @@ DatabaseCommand_AllAlbums::execForArtist( DatabaseImpl* dbi )
|
||||
al << album;
|
||||
}
|
||||
|
||||
if ( al.count() )
|
||||
emit albums( al, data() );
|
||||
emit albums( al, data() );
|
||||
emit done();
|
||||
}
|
||||
|
||||
@@ -124,8 +123,7 @@ DatabaseCommand_AllAlbums::execForCollection( DatabaseImpl* dbi )
|
||||
al << album;
|
||||
}
|
||||
|
||||
if ( al.count() )
|
||||
emit albums( al, data() );
|
||||
emit albums( al, data() );
|
||||
emit done();
|
||||
}
|
||||
|
||||
|
358
src/libtomahawk/dropjob.cpp
Normal file
358
src/libtomahawk/dropjob.cpp
Normal file
@@ -0,0 +1,358 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2011, Michael Zanetti <mzanetti@kde.org>
|
||||
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dropjob.h"
|
||||
|
||||
#include "artist.h"
|
||||
#include "album.h"
|
||||
|
||||
#include "utils/spotifyparser.h"
|
||||
#include "utils/rdioparser.h"
|
||||
#include "utils/shortenedlinkparser.h"
|
||||
#include "utils/logger.h"
|
||||
#include "globalactionmanager.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
DropJob::DropJob( QObject *parent )
|
||||
: QObject( parent )
|
||||
, m_queryCount( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
DropJob::~DropJob()
|
||||
{
|
||||
qDebug() << "destryong DropJob";
|
||||
}
|
||||
|
||||
/// QMIMEDATA HANDLING
|
||||
|
||||
QStringList
|
||||
DropJob::mimeTypes()
|
||||
{
|
||||
QStringList mimeTypes;
|
||||
mimeTypes << "application/tomahawk.query.list"
|
||||
<< "application/tomahawk.plentry.list"
|
||||
<< "application/tomahawk.result.list"
|
||||
<< "application/tomahawk.result"
|
||||
<< "application/tomahawk.metadata.artist"
|
||||
<< "application/tomahawk.metadata.album"
|
||||
<< "application/tomahawk.mixed"
|
||||
<< "text/plain";
|
||||
return mimeTypes;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DropJob::acceptsMimeData( const QMimeData* data, bool tracksOnly )
|
||||
{
|
||||
if ( data->hasFormat( "application/tomahawk.query.list" )
|
||||
|| data->hasFormat( "application/tomahawk.plentry.list" )
|
||||
|| data->hasFormat( "application/tomahawk.result.list" )
|
||||
|| data->hasFormat( "application/tomahawk.result" )
|
||||
|| data->hasFormat( "application/tomahawk.mixed" )
|
||||
|| data->hasFormat( "application/tomahawk.metadata.album" )
|
||||
|| data->hasFormat( "application/tomahawk.metadata.artist" ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// crude check for spotify tracks
|
||||
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "spotify" ) &&
|
||||
( tracksOnly ? data->data( "text/plain" ).contains( "track" ) : true ) )
|
||||
return true;
|
||||
|
||||
// crude check for rdio tracks
|
||||
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "rdio.com" ) &&
|
||||
( tracksOnly ? data->data( "text/plain" ).contains( "track" ) : true ) )
|
||||
return true;
|
||||
|
||||
// We whitelist t.co and bit.ly (and j.mp) since they do some link checking. Often playable (e.g. spotify..) links hide behind them,
|
||||
// so we do an extra level of lookup
|
||||
if ( ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "bit.ly" ) ) ||
|
||||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "j.mp" ) ) ||
|
||||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "t.co" ) ) ||
|
||||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "rd.io" ) ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DropJob::tracksFromMimeData( const QMimeData* data, bool allowDuplicates )
|
||||
{
|
||||
m_allowDuplicates = allowDuplicates;
|
||||
|
||||
parseMimeData( data );
|
||||
|
||||
if ( m_queryCount == 0 )
|
||||
{
|
||||
if ( !allowDuplicates )
|
||||
removeDuplicates();
|
||||
|
||||
emit tracks( m_resultList );
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DropJob::parseMimeData( const QMimeData *data )
|
||||
{
|
||||
QList< query_ptr > results;
|
||||
if ( data->hasFormat( "application/tomahawk.query.list" ) )
|
||||
results = tracksFromQueryList( data );
|
||||
else if ( data->hasFormat( "application/tomahawk.result.list" ) )
|
||||
results = tracksFromResultList( data );
|
||||
else if ( data->hasFormat( "application/tomahawk.metadata.album" ) )
|
||||
results = tracksFromAlbumMetaData( data );
|
||||
else if ( data->hasFormat( "application/tomahawk.metadata.artist" ) )
|
||||
results = tracksFromArtistMetaData( data );
|
||||
else if ( data->hasFormat( "application/tomahawk.mixed" ) )
|
||||
tracksFromMixedData( data );
|
||||
else if ( data->hasFormat( "text/plain" ) )
|
||||
{
|
||||
QString plainData = QString::fromUtf8( data->data( "text/plain" ).constData() );
|
||||
tDebug() << "Got text/plain mime data:" << data->data( "text/plain" ) << "decoded to:" << plainData;
|
||||
handleTrackUrls ( plainData );
|
||||
}
|
||||
|
||||
m_resultList.append( results );
|
||||
}
|
||||
|
||||
QList< query_ptr >
|
||||
DropJob::tracksFromQueryList( const QMimeData* data )
|
||||
{
|
||||
QList< query_ptr > queries;
|
||||
QByteArray itemData = data->data( "application/tomahawk.query.list" );
|
||||
QDataStream stream( &itemData, QIODevice::ReadOnly );
|
||||
|
||||
while ( !stream.atEnd() )
|
||||
{
|
||||
qlonglong qptr;
|
||||
stream >> qptr;
|
||||
|
||||
query_ptr* query = reinterpret_cast<query_ptr*>(qptr);
|
||||
if ( query && !query->isNull() )
|
||||
{
|
||||
tDebug() << "Dropped query item:" << query->data()->artist() << "-" << query->data()->track();
|
||||
queries << *query;
|
||||
}
|
||||
}
|
||||
|
||||
return queries;
|
||||
}
|
||||
|
||||
QList< query_ptr >
|
||||
DropJob::tracksFromResultList( const QMimeData* data )
|
||||
{
|
||||
QList< query_ptr > queries;
|
||||
QByteArray itemData = data->data( "application/tomahawk.result.list" );
|
||||
QDataStream stream( &itemData, QIODevice::ReadOnly );
|
||||
|
||||
while ( !stream.atEnd() )
|
||||
{
|
||||
qlonglong qptr;
|
||||
stream >> qptr;
|
||||
|
||||
result_ptr* result = reinterpret_cast<result_ptr*>(qptr);
|
||||
if ( result && !result->isNull() )
|
||||
{
|
||||
tDebug() << "Dropped result item:" << result->data()->artist()->name() << "-" << result->data()->track();
|
||||
query_ptr q = result->data()->toQuery();
|
||||
q->addResults( QList< result_ptr >() << *result );
|
||||
queries << q;
|
||||
}
|
||||
}
|
||||
|
||||
return queries;
|
||||
}
|
||||
|
||||
QList< query_ptr >
|
||||
DropJob::tracksFromAlbumMetaData( const QMimeData *data )
|
||||
{
|
||||
QList<query_ptr> queries;
|
||||
QByteArray itemData = data->data( "application/tomahawk.metadata.album" );
|
||||
QDataStream stream( &itemData, QIODevice::ReadOnly );
|
||||
|
||||
while ( !stream.atEnd() )
|
||||
{
|
||||
QString artist;
|
||||
stream >> artist;
|
||||
QString album;
|
||||
stream >> album;
|
||||
|
||||
artist_ptr artistPtr = Artist::get( artist );
|
||||
album_ptr albumPtr = Album::get( artistPtr, album );
|
||||
if ( albumPtr->tracks().isEmpty() )
|
||||
{
|
||||
connect( albumPtr.data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr> ) ),
|
||||
SLOT( onTracksAdded( QList<Tomahawk::query_ptr> ) ) );
|
||||
m_queryCount++;
|
||||
}
|
||||
else
|
||||
queries << albumPtr->tracks();
|
||||
}
|
||||
return queries;
|
||||
}
|
||||
|
||||
QList< query_ptr >
|
||||
DropJob::tracksFromArtistMetaData( const QMimeData *data )
|
||||
{
|
||||
QList<query_ptr> queries;
|
||||
QByteArray itemData = data->data( "application/tomahawk.metadata.artist" );
|
||||
QDataStream stream( &itemData, QIODevice::ReadOnly );
|
||||
|
||||
while ( !stream.atEnd() )
|
||||
{
|
||||
QString artist;
|
||||
stream >> artist;
|
||||
|
||||
artist_ptr artistPtr = Artist::get( artist );
|
||||
if ( artistPtr->tracks().isEmpty() )
|
||||
{
|
||||
connect( artistPtr.data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr> ) ),
|
||||
SLOT( onTracksAdded( QList<Tomahawk::query_ptr> ) ) );
|
||||
m_queryCount++;
|
||||
}
|
||||
else
|
||||
queries << artistPtr->tracks();
|
||||
}
|
||||
return queries;
|
||||
}
|
||||
|
||||
QList< query_ptr >
|
||||
DropJob::tracksFromMixedData( const QMimeData *data )
|
||||
{
|
||||
QList< query_ptr > queries;
|
||||
QByteArray itemData = data->data( "application/tomahawk.mixed" );
|
||||
QDataStream stream( &itemData, QIODevice::ReadOnly );
|
||||
|
||||
QString mimeType;
|
||||
|
||||
while ( !stream.atEnd() )
|
||||
{
|
||||
stream >> mimeType;
|
||||
qDebug() << "mimetype is" << mimeType;
|
||||
|
||||
QByteArray singleData;
|
||||
QDataStream singleStream( &singleData, QIODevice::WriteOnly );
|
||||
|
||||
QMimeData singleMimeData;
|
||||
if ( mimeType == "application/tomahawk.query.list" || mimeType == "application/tomahawk.result.list" )
|
||||
{
|
||||
qlonglong query;
|
||||
stream >> query;
|
||||
singleStream << query;
|
||||
}
|
||||
else if ( mimeType == "application/tomahawk.metadata.album" )
|
||||
{
|
||||
QString artist;
|
||||
stream >> artist;
|
||||
singleStream << artist;
|
||||
QString album;
|
||||
stream >> album;
|
||||
singleStream << album;
|
||||
qDebug() << "got artist" << artist << "and album" << album;
|
||||
}
|
||||
else if ( mimeType == "application/tomahawk.metadata.artist" )
|
||||
{
|
||||
QString artist;
|
||||
stream >> artist;
|
||||
singleStream << artist;
|
||||
qDebug() << "got artist" << artist;
|
||||
}
|
||||
|
||||
singleMimeData.setData( mimeType, singleData );
|
||||
parseMimeData( &singleMimeData );
|
||||
}
|
||||
return queries;
|
||||
}
|
||||
|
||||
void
|
||||
DropJob::handleTrackUrls( const QString& urls )
|
||||
{
|
||||
if ( urls.contains( "open.spotify.com/track") ||
|
||||
urls.contains( "spotify:track" ) )
|
||||
{
|
||||
QStringList tracks = urls.split( "\n" );
|
||||
|
||||
tDebug() << "Got a list of spotify urls!" << tracks;
|
||||
SpotifyParser* spot = new SpotifyParser( tracks, this );
|
||||
connect( spot, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ) );
|
||||
} else if ( urls.contains( "rdio.com" ) )
|
||||
{
|
||||
QStringList tracks = urls.split( "\n" );
|
||||
|
||||
tDebug() << "Got a list of rdio urls!" << tracks;
|
||||
RdioParser* rdio = new RdioParser( this );
|
||||
connect( rdio, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ) );
|
||||
rdio->parse( tracks );
|
||||
} else if ( urls.contains( "bit.ly" ) ||
|
||||
urls.contains( "j.mp" ) ||
|
||||
urls.contains( "t.co" ) ||
|
||||
urls.contains( "rd.io" ) )
|
||||
{
|
||||
QStringList tracks = urls.split( "\n" );
|
||||
|
||||
tDebug() << "Got a list of shortened urls!" << tracks;
|
||||
ShortenedLinkParser* parser = new ShortenedLinkParser( tracks, this );
|
||||
connect( parser, SIGNAL( urls( QStringList ) ), this, SLOT( expandedUrls( QStringList ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DropJob::expandedUrls( QStringList urls )
|
||||
{
|
||||
handleTrackUrls( urls.join( "\n" ) );
|
||||
}
|
||||
|
||||
void
|
||||
DropJob::onTracksAdded( const QList<Tomahawk::query_ptr>& tracksList )
|
||||
{
|
||||
m_resultList.append( tracksList );
|
||||
|
||||
if ( --m_queryCount == 0 )
|
||||
{
|
||||
if ( !m_allowDuplicates )
|
||||
removeDuplicates();
|
||||
|
||||
emit tracks( m_resultList );
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DropJob::removeDuplicates()
|
||||
{
|
||||
QList< Tomahawk::query_ptr > list;
|
||||
foreach ( const Tomahawk::query_ptr& item, m_resultList )
|
||||
{
|
||||
bool contains = false;
|
||||
foreach( const Tomahawk::query_ptr &tmpItem, list )
|
||||
if ( item->album() == tmpItem->album()
|
||||
&& item->artist() == tmpItem->artist()
|
||||
&& item->track() == tmpItem->track() )
|
||||
contains = true;
|
||||
if ( !contains )
|
||||
list.append( item );
|
||||
}
|
||||
m_resultList = list;
|
||||
}
|
76
src/libtomahawk/dropjob.h
Normal file
76
src/libtomahawk/dropjob.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2011, Michael Zanetti <mzanetti@kde.org>
|
||||
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DROPJOB_H
|
||||
#define DROPJOB_H
|
||||
|
||||
#include "query.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
#include <QMimeData>
|
||||
|
||||
class DLLEXPORT DropJob : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DropJob( QObject *parent = 0 );
|
||||
~DropJob();
|
||||
|
||||
/**
|
||||
* QMimeData helpers
|
||||
*
|
||||
* Call this to parse the tracks in a QMimeData object to query_ptrs. This will parse internal tomahawk
|
||||
* data as well as all other formats supported (spotify, etc).
|
||||
*
|
||||
* Connect to tracks( QList< query_ptr> ); for the extracted tracks.
|
||||
*/
|
||||
static bool acceptsMimeData( const QMimeData* data, bool tracksOnly = true );
|
||||
static QStringList mimeTypes();
|
||||
void tracksFromMimeData( const QMimeData* data, bool allowDuplicates = false );
|
||||
|
||||
signals:
|
||||
/// QMimeData parsing results
|
||||
void tracks( const QList< Tomahawk::query_ptr >& tracks );
|
||||
|
||||
private slots:
|
||||
void expandedUrls( QStringList );
|
||||
|
||||
void onTracksAdded( const QList<Tomahawk::query_ptr>& );
|
||||
|
||||
private:
|
||||
/// handle parsing mime data
|
||||
void parseMimeData( const QMimeData* data );
|
||||
|
||||
void handleTrackUrls( const QString& urls );
|
||||
QList< Tomahawk::query_ptr > tracksFromQueryList( const QMimeData* d );
|
||||
QList< Tomahawk::query_ptr > tracksFromResultList( const QMimeData* d );
|
||||
QList< Tomahawk::query_ptr > tracksFromArtistMetaData( const QMimeData* d );
|
||||
QList< Tomahawk::query_ptr > tracksFromAlbumMetaData( const QMimeData* d );
|
||||
QList< Tomahawk::query_ptr > tracksFromMixedData( const QMimeData* d );
|
||||
|
||||
void removeDuplicates();
|
||||
|
||||
int m_queryCount;
|
||||
bool m_allowDuplicates;
|
||||
|
||||
QList< Tomahawk::query_ptr > m_resultList;
|
||||
};
|
||||
|
||||
#endif // DROPJOB_H
|
@@ -64,7 +64,6 @@ GlobalActionManager::instance()
|
||||
GlobalActionManager::GlobalActionManager( QObject* parent )
|
||||
: QObject( parent )
|
||||
{
|
||||
m_mimeTypes << "application/tomahawk.query.list" << "application/tomahawk.plentry.list" << "application/tomahawk.result.list" << "text/plain";
|
||||
}
|
||||
|
||||
GlobalActionManager::~GlobalActionManager()
|
||||
@@ -779,149 +778,6 @@ GlobalActionManager::hostname() const
|
||||
return QString( "http://toma.hk" );
|
||||
}
|
||||
|
||||
/// QMIMEDATA HANDLING
|
||||
|
||||
QStringList
|
||||
GlobalActionManager::mimeTypes() const
|
||||
{
|
||||
return m_mimeTypes;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
GlobalActionManager::acceptsMimeData( const QMimeData* data, bool tracksOnly )
|
||||
{
|
||||
if ( data->hasFormat( "application/tomahawk.query.list" )
|
||||
|| data->hasFormat( "application/tomahawk.plentry.list" )
|
||||
|| data->hasFormat( "application/tomahawk.result.list" ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// crude check for spotify tracks
|
||||
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "spotify" ) &&
|
||||
( tracksOnly ? data->data( "text/plain" ).contains( "track" ) : true ) )
|
||||
return true;
|
||||
|
||||
// crude check for rdio tracks
|
||||
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "rdio.com" ) &&
|
||||
( tracksOnly ? data->data( "text/plain" ).contains( "track" ) : true ) )
|
||||
return true;
|
||||
|
||||
// We whitelist t.co and bit.ly (and j.mp) since they do some link checking. Often playable (e.g. spotify..) links hide behind them,
|
||||
// so we do an extra level of lookup
|
||||
if ( ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "bit.ly" ) ) ||
|
||||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "j.mp" ) ) ||
|
||||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "t.co" ) ) ||
|
||||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "rd.io" ) ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GlobalActionManager::tracksFromMimeData( const QMimeData* data )
|
||||
{
|
||||
if ( data->hasFormat( "application/tomahawk.query.list" ) )
|
||||
emit tracks( tracksFromQueryList( data ) );
|
||||
else if ( data->hasFormat( "application/tomahawk.result.list" ) )
|
||||
emit tracks( tracksFromResultList( data ) );
|
||||
else if ( data->hasFormat( "text/plain" ) )
|
||||
{
|
||||
QString plainData = QString::fromUtf8( data->data( "text/plain" ).constData() );
|
||||
tDebug() << "Got text/plain mime data:" << data->data( "text/plain" ) << "decoded to:" << plainData;
|
||||
handleTrackUrls ( plainData );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GlobalActionManager::handleTrackUrls( const QString& urls )
|
||||
{
|
||||
if ( urls.contains( "open.spotify.com/track") ||
|
||||
urls.contains( "spotify:track" ) )
|
||||
{
|
||||
QStringList tracks = urls.split( "\n" );
|
||||
|
||||
tDebug() << "Got a list of spotify urls!" << tracks;
|
||||
SpotifyParser* spot = new SpotifyParser( tracks, this );
|
||||
connect( spot, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ) );
|
||||
} else if ( urls.contains( "rdio.com" ) )
|
||||
{
|
||||
QStringList tracks = urls.split( "\n" );
|
||||
|
||||
tDebug() << "Got a list of rdio urls!" << tracks;
|
||||
RdioParser* rdio = new RdioParser( this );
|
||||
connect( rdio, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ) );
|
||||
rdio->parse( tracks );
|
||||
} else if ( urls.contains( "bit.ly" ) ||
|
||||
urls.contains( "j.mp" ) ||
|
||||
urls.contains( "t.co" ) ||
|
||||
urls.contains( "rd.io" ) )
|
||||
{
|
||||
QStringList tracks = urls.split( "\n" );
|
||||
|
||||
tDebug() << "Got a list of shortened urls!" << tracks;
|
||||
ShortenedLinkParser* parser = new ShortenedLinkParser( tracks, this );
|
||||
connect( parser, SIGNAL( urls( QStringList ) ), this, SLOT( expandedUrls( QStringList ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GlobalActionManager::expandedUrls( QStringList urls )
|
||||
{
|
||||
handleTrackUrls( urls.join( "\n" ) );
|
||||
}
|
||||
|
||||
|
||||
QList< query_ptr >
|
||||
GlobalActionManager::tracksFromQueryList( const QMimeData* data )
|
||||
{
|
||||
QList< query_ptr > queries;
|
||||
QByteArray itemData = data->data( "application/tomahawk.query.list" );
|
||||
QDataStream stream( &itemData, QIODevice::ReadOnly );
|
||||
|
||||
while ( !stream.atEnd() )
|
||||
{
|
||||
qlonglong qptr;
|
||||
stream >> qptr;
|
||||
|
||||
query_ptr* query = reinterpret_cast<query_ptr*>(qptr);
|
||||
if ( query && !query->isNull() )
|
||||
{
|
||||
tDebug() << "Dropped query item:" << query->data()->artist() << "-" << query->data()->track();
|
||||
queries << *query;
|
||||
}
|
||||
}
|
||||
|
||||
return queries;
|
||||
}
|
||||
|
||||
QList< query_ptr >
|
||||
GlobalActionManager::tracksFromResultList( const QMimeData* data )
|
||||
{
|
||||
QList< query_ptr > queries;
|
||||
QByteArray itemData = data->data( "application/tomahawk.result.list" );
|
||||
QDataStream stream( &itemData, QIODevice::ReadOnly );
|
||||
|
||||
while ( !stream.atEnd() )
|
||||
{
|
||||
qlonglong qptr;
|
||||
stream >> qptr;
|
||||
|
||||
result_ptr* result = reinterpret_cast<result_ptr*>(qptr);
|
||||
if ( result && !result->isNull() )
|
||||
{
|
||||
tDebug() << "Dropped result item:" << result->data()->artist()->name() << "-" << result->data()->track();
|
||||
query_ptr q = result->data()->toQuery();
|
||||
q->addResults( QList< result_ptr >() << *result );
|
||||
queries << q;
|
||||
}
|
||||
}
|
||||
|
||||
return queries;
|
||||
}
|
||||
|
||||
/// SPOTIFY URL HANDLING
|
||||
|
||||
|
@@ -51,18 +51,6 @@ public:
|
||||
QString copyPlaylistToClipboard( const Tomahawk::dynplaylist_ptr& playlist );
|
||||
void savePlaylistToFile( const Tomahawk::playlist_ptr& playlist, const QString& filename );
|
||||
|
||||
/**
|
||||
* QMimeData helpers
|
||||
*
|
||||
* Call this to parse the tracks in a QMimeData object to query_ptrs. This will parse internal tomahawk
|
||||
* data as well as all other formats supported (spotify, etc).
|
||||
*
|
||||
* Connect to tracks( QList< query_ptr> ); for the extracted tracks.
|
||||
*/
|
||||
bool acceptsMimeData( const QMimeData* data, bool tracksOnly = true );
|
||||
void tracksFromMimeData( const QMimeData* data );
|
||||
QStringList mimeTypes() const;
|
||||
|
||||
public slots:
|
||||
bool parseTomahawkLink( const QString& link );
|
||||
void waitingForResolved( bool );
|
||||
@@ -70,16 +58,12 @@ public slots:
|
||||
Tomahawk::dynplaylist_ptr loadDynamicPlaylist( const QUrl& url, bool station );
|
||||
|
||||
void handleOpenTrack( const Tomahawk::query_ptr& qry );
|
||||
signals:
|
||||
/// QMimeData parsing results
|
||||
void tracks( const QList< Tomahawk::query_ptr >& tracks );
|
||||
|
||||
private slots:
|
||||
void bookmarkPlaylistCreated( const Tomahawk::playlist_ptr& pl );
|
||||
void showPlaylist();
|
||||
|
||||
void xspfCreated( const QByteArray& xspf );
|
||||
void expandedUrls( QStringList );
|
||||
|
||||
void spotifyToPlay( const Tomahawk::query_ptr& );
|
||||
private:
|
||||
@@ -101,18 +85,12 @@ private:
|
||||
bool playSpotify( const QUrl& url );
|
||||
bool queueSpotify( const QStringList& parts, const QList< QPair< QString, QString > >& queryItems );
|
||||
|
||||
/// handle parsing mime data
|
||||
void handleTrackUrls( const QString& urls );
|
||||
QList< Tomahawk::query_ptr > tracksFromQueryList( const QMimeData* d );
|
||||
QList< Tomahawk::query_ptr > tracksFromResultList( const QMimeData* d );
|
||||
|
||||
QString hostname() const;
|
||||
|
||||
Tomahawk::playlist_ptr m_toShow;
|
||||
Tomahawk::query_ptr m_waitingToBookmark;
|
||||
Tomahawk::query_ptr m_waitingToPlay;
|
||||
|
||||
QStringList m_mimeTypes;
|
||||
static GlobalActionManager* s_instance;
|
||||
};
|
||||
|
||||
|
@@ -283,7 +283,7 @@ DBSyncConnection::lastOpApplied()
|
||||
void
|
||||
DBSyncConnection::sendOps()
|
||||
{
|
||||
tLog() << "Will send peer all ops since" << m_uscache.value( "lastop" ).toString();
|
||||
tLog() << "Will send peer" << m_source->id() << "all ops since" << m_uscache.value( "lastop" ).toString();
|
||||
|
||||
source_ptr src = SourceList::instance()->getLocal();
|
||||
|
||||
|
@@ -60,6 +60,7 @@ Servent::Servent( QObject* parent )
|
||||
: QTcpServer( parent )
|
||||
, m_port( 0 )
|
||||
, m_externalPort( 0 )
|
||||
, m_ready( false )
|
||||
, m_portfwd( 0 )
|
||||
{
|
||||
s_instance = this;
|
||||
@@ -133,6 +134,7 @@ Servent::startListening( QHostAddress ha, bool upnp, int port )
|
||||
tLog() << "Forcing static preferred host and port";
|
||||
m_externalHostname = TomahawkSettings::instance()->externalHostname();
|
||||
m_externalPort = TomahawkSettings::instance()->externalPort();
|
||||
m_ready = true;
|
||||
emit ready();
|
||||
return true;
|
||||
}
|
||||
@@ -155,7 +157,10 @@ Servent::startListening( QHostAddress ha, bool upnp, int port )
|
||||
QMetaObject::invokeMethod( this, "setExternalAddress", Qt::QueuedConnection, Q_ARG( QHostAddress, ha ), Q_ARG( unsigned int, m_port ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ready = true;
|
||||
emit ready();
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -227,6 +232,7 @@ Servent::setExternalAddress( QHostAddress ha, unsigned int port )
|
||||
qDebug() << "No external access, LAN and outbound connections only!";
|
||||
}
|
||||
|
||||
m_ready = true;
|
||||
emit ready();
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
@@ -123,6 +123,8 @@ public:
|
||||
QSharedPointer<QIODevice> localFileIODeviceFactory( const Tomahawk::result_ptr& result );
|
||||
QSharedPointer<QIODevice> httpIODeviceFactory( const Tomahawk::result_ptr& result );
|
||||
|
||||
bool isReady() const { return m_ready; };
|
||||
|
||||
signals:
|
||||
void streamStarted( StreamConnection* );
|
||||
void streamFinished( StreamConnection* );
|
||||
@@ -159,6 +161,7 @@ private:
|
||||
int m_port, m_externalPort;
|
||||
QHostAddress m_externalAddress;
|
||||
QString m_externalHostname;
|
||||
bool m_ready;
|
||||
|
||||
// currently active file transfers:
|
||||
QList< StreamConnection* > m_scsessions;
|
||||
|
@@ -196,22 +196,7 @@ Pipeline::reportResults( QID qid, const QList< result_ptr >& results )
|
||||
}
|
||||
}
|
||||
|
||||
if ( decQIDState( q ) == 0 )
|
||||
{
|
||||
if ( !q->solved() || q->isFullTextQuery() )
|
||||
q->onResolvingFinished();
|
||||
|
||||
if ( !m_queries_temporary.contains( q ) )
|
||||
m_qids.remove( q->id() );
|
||||
if ( m_qidsTimeout.contains( q->id() ) )
|
||||
m_qidsTimeout.remove( q->id() );
|
||||
|
||||
shuntNext();
|
||||
}
|
||||
else
|
||||
{
|
||||
new FuncTimeout( 0, boost::bind( &Pipeline::timeoutShunt, this, q ), this );
|
||||
}
|
||||
decQIDState( q );
|
||||
}
|
||||
|
||||
|
||||
@@ -260,8 +245,7 @@ Pipeline::timeoutShunt( const query_ptr& q )
|
||||
// are we still waiting for a timeout?
|
||||
if ( m_qidsTimeout.contains( q->id() ) )
|
||||
{
|
||||
m_qidsTimeout.remove( q->id() );
|
||||
shunt( q );
|
||||
decQIDState( q );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,7 +262,7 @@ Pipeline::shunt( const query_ptr& q )
|
||||
|
||||
if ( r )
|
||||
{
|
||||
qDebug() << "Dispatching to resolver" << r->name() << q->toString() << q->solved() << q->id();
|
||||
tDebug() << "Dispatching to resolver" << r->name() << q->toString() << q->solved() << q->id();
|
||||
|
||||
q->setCurrentResolver( r );
|
||||
r->resolve( q );
|
||||
@@ -374,6 +358,25 @@ Pipeline::decQIDState( const Tomahawk::query_ptr& query )
|
||||
// qDebug() << "Queries running:" << m_qidsState.count();
|
||||
}
|
||||
|
||||
if ( state == 0 )
|
||||
{
|
||||
if ( !query->solved() || query->isFullTextQuery() )
|
||||
query->onResolvingFinished();
|
||||
|
||||
if ( !m_queries_temporary.contains( query ) )
|
||||
m_qids.remove( query->id() );
|
||||
if ( m_qidsTimeout.contains( query->id() ) )
|
||||
m_qidsTimeout.remove( query->id() );
|
||||
|
||||
new FuncTimeout( 0, boost::bind( &Pipeline::shuntNext, this ), this );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_qidsTimeout.contains( query->id() ) )
|
||||
m_qidsTimeout.remove( query->id() );
|
||||
new FuncTimeout( 0, boost::bind( &Pipeline::shunt, this, query ), this );
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
@@ -159,6 +159,7 @@ AlbumModel::headerData( int section, Qt::Orientation orientation, int role ) con
|
||||
Qt::ItemFlags
|
||||
AlbumModel::flags( const QModelIndex& index ) const
|
||||
{
|
||||
qDebug() << "asking for flags for index" << index;
|
||||
Qt::ItemFlags defaultFlags = QAbstractItemModel::flags( index );
|
||||
|
||||
if ( index.isValid() && index.column() == 0 )
|
||||
@@ -195,12 +196,13 @@ AlbumModel::mimeData( const QModelIndexList &indexes ) const
|
||||
if ( item )
|
||||
{
|
||||
const album_ptr& album = item->album();
|
||||
queryStream << qlonglong( &album );
|
||||
queryStream << album->artist()->name();
|
||||
queryStream << album->name();
|
||||
}
|
||||
}
|
||||
|
||||
QMimeData* mimeData = new QMimeData();
|
||||
mimeData->setData( "application/tomahawk.query.list", queryData );
|
||||
mimeData->setData( "application/tomahawk.metadata.album", queryData );
|
||||
|
||||
return mimeData;
|
||||
}
|
||||
|
@@ -188,27 +188,6 @@ AlbumView::onScrollTimeout()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlbumView::dragEnterEvent( QDragEnterEvent* event )
|
||||
{
|
||||
QListView::dragEnterEvent( event );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlbumView::dragMoveEvent( QDragMoveEvent* event )
|
||||
{
|
||||
QListView::dragMoveEvent( event );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlbumView::dropEvent( QDropEvent* event )
|
||||
{
|
||||
QListView::dropEvent( event );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlbumView::paintEvent( QPaintEvent* event )
|
||||
{
|
||||
@@ -227,14 +206,30 @@ AlbumView::onFilterChanged( const QString& )
|
||||
void
|
||||
AlbumView::startDrag( Qt::DropActions supportedActions )
|
||||
{
|
||||
Q_UNUSED( supportedActions );
|
||||
}
|
||||
QList<QPersistentModelIndex> pindexes;
|
||||
QModelIndexList indexes;
|
||||
foreach( const QModelIndex& idx, selectedIndexes() )
|
||||
{
|
||||
if ( ( m_proxyModel->flags( idx ) & Qt::ItemIsDragEnabled ) )
|
||||
{
|
||||
indexes << idx;
|
||||
pindexes << idx;
|
||||
}
|
||||
}
|
||||
|
||||
if ( indexes.count() == 0 )
|
||||
return;
|
||||
|
||||
// Inspired from dolphin's draganddrophelper.cpp
|
||||
QPixmap
|
||||
AlbumView::createDragPixmap( int itemCount ) const
|
||||
{
|
||||
Q_UNUSED( itemCount );
|
||||
return QPixmap();
|
||||
qDebug() << "Dragging" << indexes.count() << "indexes";
|
||||
QMimeData* data = m_proxyModel->mimeData( indexes );
|
||||
if ( !data )
|
||||
return;
|
||||
|
||||
QDrag* drag = new QDrag( this );
|
||||
drag->setMimeData( data );
|
||||
const QPixmap p = TomahawkUtils::createDragPixmap( indexes.count() );
|
||||
drag->setPixmap( p );
|
||||
drag->setHotSpot( QPoint( -20, -20 ) );
|
||||
|
||||
Qt::DropAction action = drag->exec( supportedActions, Qt::CopyAction );
|
||||
}
|
||||
|
@@ -60,9 +60,6 @@ public slots:
|
||||
|
||||
protected:
|
||||
virtual void startDrag( Qt::DropActions supportedActions );
|
||||
virtual void dragEnterEvent( QDragEnterEvent* event );
|
||||
virtual void dragMoveEvent( QDragMoveEvent* event );
|
||||
virtual void dropEvent( QDropEvent* event );
|
||||
|
||||
void paintEvent( QPaintEvent* event );
|
||||
|
||||
@@ -73,8 +70,6 @@ private slots:
|
||||
void onScrollTimeout();
|
||||
|
||||
private:
|
||||
QPixmap createDragPixmap( int itemCount ) const;
|
||||
|
||||
AlbumModel* m_model;
|
||||
AlbumProxyModel* m_proxyModel;
|
||||
// PlaylistItemDelegate* m_delegate;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
@@ -21,31 +21,33 @@
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "dllmacro.h"
|
||||
|
||||
class QMovie;
|
||||
class QTimeLine;
|
||||
/**
|
||||
* A small widget that displays an animated loading spinner
|
||||
*/
|
||||
class LoadingSpinner : public QWidget {
|
||||
class DLLEXPORT LoadingSpinner : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
LoadingSpinner( QWidget* parent );
|
||||
virtual ~LoadingSpinner();
|
||||
|
||||
|
||||
virtual QSize sizeHint() const;
|
||||
virtual void paintEvent( QPaintEvent* );
|
||||
virtual void resizeEvent( QResizeEvent* );
|
||||
|
||||
public slots:
|
||||
|
||||
public slots:
|
||||
void fadeIn();
|
||||
void fadeOut();
|
||||
|
||||
|
||||
private slots:
|
||||
void hideFinished();
|
||||
|
||||
|
||||
private:
|
||||
void reposition();
|
||||
|
||||
|
||||
QTimeLine* m_showHide;
|
||||
QMovie* m_anim;
|
||||
};
|
||||
|
@@ -27,7 +27,7 @@
|
||||
#include "database/databasecommand_playbackhistory.h"
|
||||
#include "dynamic/GeneratorInterface.h"
|
||||
#include "utils/logger.h"
|
||||
#include "globalactionmanager.h"
|
||||
#include "dropjob.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
@@ -358,14 +358,15 @@ PlaylistModel::dropMimeData( const QMimeData* data, Qt::DropAction action, int r
|
||||
if ( action == Qt::IgnoreAction || isReadOnly() )
|
||||
return true;
|
||||
|
||||
if ( !GlobalActionManager::instance()->acceptsMimeData( data ) )
|
||||
if ( !DropJob::acceptsMimeData( data ) )
|
||||
return false;
|
||||
|
||||
m_dropStorage.row = row;
|
||||
m_dropStorage.parent = QPersistentModelIndex( parent );
|
||||
m_dropStorage.action = action;
|
||||
connect( GlobalActionManager::instance(), SIGNAL( tracks( QList< Tomahawk::query_ptr > ) ), this, SLOT( parsedDroppedTracks( QList< Tomahawk::query_ptr > ) ) );
|
||||
GlobalActionManager::instance()->tracksFromMimeData( data );
|
||||
DropJob *dj = new DropJob();
|
||||
connect( dj, SIGNAL( tracks( QList< Tomahawk::query_ptr > ) ), this, SLOT( parsedDroppedTracks( QList< Tomahawk::query_ptr > ) ) );
|
||||
dj->tracksFromMimeData( data );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -377,8 +378,6 @@ PlaylistModel::parsedDroppedTracks( QList< query_ptr > tracks )
|
||||
if ( m_dropStorage.row == -10 ) // nope
|
||||
return;
|
||||
|
||||
disconnect( GlobalActionManager::instance(), SIGNAL( tracks( QList< Tomahawk::query_ptr > ) ), this, SLOT( parsedDroppedTracks( QList< Tomahawk::query_ptr > ) ) );
|
||||
|
||||
int beginRow;
|
||||
if ( m_dropStorage.row != -1 )
|
||||
beginRow = m_dropStorage.row;
|
||||
|
@@ -177,7 +177,7 @@ Tomahawk::result_ptr
|
||||
TrackProxyModel::currentItem() const
|
||||
{
|
||||
TrackModelItem* item = itemFromIndex( mapToSource( currentIndex() ) );
|
||||
if ( item && item->query()->playable() )
|
||||
if ( item && !item->query().isNull() && item->query()->playable() )
|
||||
return item->query()->results().at( 0 );
|
||||
return Tomahawk::result_ptr();
|
||||
}
|
||||
@@ -318,8 +318,8 @@ TrackProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) c
|
||||
unsigned int albumpos1 = 0, albumpos2 = 0;
|
||||
unsigned int bitrate1 = 0, bitrate2 = 0;
|
||||
unsigned int mtime1 = 0, mtime2 = 0;
|
||||
unsigned int id1 = 0, id2 = 0;
|
||||
unsigned int size1 = 0, size2 = 0;
|
||||
qint64 id1 = 0, id2 = 0;
|
||||
|
||||
if ( q1->numResults() )
|
||||
{
|
||||
@@ -346,6 +346,13 @@ TrackProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) c
|
||||
size2 = r->size();
|
||||
}
|
||||
|
||||
// This makes it a stable sorter and prevents items from randomly jumping about.
|
||||
if ( id1 == id2 )
|
||||
{
|
||||
id1 = (qint64)&q1;
|
||||
id2 = (qint64)&q2;
|
||||
}
|
||||
|
||||
if ( left.column() == TrackModel::Artist ) // sort by artist
|
||||
{
|
||||
if ( artist1 == artist2 )
|
||||
@@ -396,6 +403,11 @@ TrackProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) c
|
||||
|
||||
return size1 < size2;
|
||||
}
|
||||
return QString::localeAwareCompare( sourceModel()->data( left ).toString(),
|
||||
sourceModel()->data( right ).toString() ) < 0;
|
||||
|
||||
const QString& lefts = sourceModel()->data( left ).toString();
|
||||
const QString& rights = sourceModel()->data( right ).toString();
|
||||
if ( lefts == rights )
|
||||
return id1 < id2;
|
||||
|
||||
return QString::localeAwareCompare( lefts, rights ) < 0;
|
||||
}
|
||||
|
@@ -33,7 +33,7 @@
|
||||
#include "dynamic/widgets/LoadingSpinner.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "utils/logger.h"
|
||||
#include <globalactionmanager.h>
|
||||
#include "dropjob.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
@@ -214,7 +214,7 @@ TrackView::dragEnterEvent( QDragEnterEvent* event )
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
QTreeView::dragEnterEvent( event );
|
||||
|
||||
if ( GlobalActionManager::instance()->acceptsMimeData( event->mimeData() ) )
|
||||
if ( DropJob::acceptsMimeData( event->mimeData() ) )
|
||||
{
|
||||
m_dragging = true;
|
||||
m_dropRect = QRect();
|
||||
@@ -236,7 +236,7 @@ TrackView::dragMoveEvent( QDragMoveEvent* event )
|
||||
return;
|
||||
}
|
||||
|
||||
if ( GlobalActionManager::instance()->acceptsMimeData( event->mimeData() ) )
|
||||
if ( DropJob::acceptsMimeData( event->mimeData() ) )
|
||||
{
|
||||
setDirtyRegion( m_dropRect );
|
||||
const QPoint pos = event->pos();
|
||||
@@ -278,7 +278,7 @@ TrackView::dropEvent( QDropEvent* event )
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( GlobalActionManager::instance()->acceptsMimeData( event->mimeData() ) )
|
||||
if ( DropJob::acceptsMimeData( event->mimeData() ) )
|
||||
{
|
||||
const QPoint pos = event->pos();
|
||||
const QModelIndex index = indexAt( pos );
|
||||
|
@@ -293,6 +293,8 @@ TreeModel::flags( const QModelIndex& index ) const
|
||||
TreeModelItem* item = itemFromIndex( index );
|
||||
if ( item && !item->result().isNull() )
|
||||
return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
|
||||
if ( item && ( !item->album().isNull() || !item->artist().isNull() ) )
|
||||
return Qt::ItemIsDragEnabled | defaultFlags;
|
||||
}
|
||||
|
||||
return defaultFlags;
|
||||
@@ -303,7 +305,7 @@ QStringList
|
||||
TreeModel::mimeTypes() const
|
||||
{
|
||||
QStringList types;
|
||||
types << "application/tomahawk.result.list";
|
||||
types << "application/tomahawk.mixed";
|
||||
return types;
|
||||
}
|
||||
|
||||
@@ -316,23 +318,124 @@ TreeModel::mimeData( const QModelIndexList &indexes ) const
|
||||
QByteArray resultData;
|
||||
QDataStream resultStream( &resultData, QIODevice::WriteOnly );
|
||||
|
||||
foreach ( const QModelIndex& i, indexes )
|
||||
// lets try with artist only
|
||||
bool fail = false;
|
||||
foreach ( const QModelIndex& i, indexes)
|
||||
{
|
||||
if ( i.column() > 0 )
|
||||
if ( i.column() > 0 || indexes.contains( i.parent() ) )
|
||||
continue;
|
||||
|
||||
QModelIndex idx = index( i.row(), 0, i.parent() );
|
||||
TreeModelItem* item = itemFromIndex( idx );
|
||||
if ( item && !item->result().isNull() )
|
||||
TreeModelItem* item = itemFromIndex( i );
|
||||
if ( !item )
|
||||
continue;
|
||||
|
||||
if ( !item->artist().isNull() )
|
||||
{
|
||||
const artist_ptr& artist = item->artist();
|
||||
resultStream << artist->name();
|
||||
}
|
||||
else
|
||||
{
|
||||
fail = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !fail )
|
||||
{
|
||||
QMimeData* mimeData = new QMimeData();
|
||||
mimeData->setData( "application/tomahawk.metadata.artist", resultData );
|
||||
return mimeData;
|
||||
}
|
||||
|
||||
// lets try with album only
|
||||
fail = false;
|
||||
foreach ( const QModelIndex& i, indexes)
|
||||
{
|
||||
if ( i.column() > 0 || indexes.contains( i.parent() ) )
|
||||
continue;
|
||||
|
||||
TreeModelItem* item = itemFromIndex( i );
|
||||
if ( !item )
|
||||
continue;
|
||||
|
||||
if ( !item->album().isNull() )
|
||||
{
|
||||
const album_ptr& album = item->album();
|
||||
resultStream << album->artist()->name();
|
||||
resultStream << album->name();
|
||||
}
|
||||
else
|
||||
{
|
||||
fail = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !fail )
|
||||
{
|
||||
QMimeData* mimeData = new QMimeData();
|
||||
mimeData->setData( "application/tomahawk.metadata.album", resultData );
|
||||
return mimeData;
|
||||
}
|
||||
|
||||
|
||||
// lets try with tracks only
|
||||
fail = false;
|
||||
foreach ( const QModelIndex& i, indexes)
|
||||
{
|
||||
if ( i.column() > 0 || indexes.contains( i.parent() ) )
|
||||
continue;
|
||||
|
||||
TreeModelItem* item = itemFromIndex( i );
|
||||
if ( !item )
|
||||
continue;
|
||||
|
||||
if ( !item->result().isNull() )
|
||||
{
|
||||
const result_ptr& result = item->result();
|
||||
resultStream << qlonglong( &result );
|
||||
}
|
||||
else
|
||||
{
|
||||
fail = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !fail )
|
||||
{
|
||||
QMimeData* mimeData = new QMimeData();
|
||||
mimeData->setData( "application/tomahawk.result.list", resultData );
|
||||
return mimeData;
|
||||
}
|
||||
|
||||
// Ok... we have to use mixed
|
||||
foreach ( const QModelIndex& i, indexes )
|
||||
{
|
||||
if ( i.column() > 0 || indexes.contains( i.parent() ) )
|
||||
continue;
|
||||
|
||||
TreeModelItem* item = itemFromIndex( i );
|
||||
if ( !item )
|
||||
continue;
|
||||
|
||||
if ( !item->artist().isNull() )
|
||||
{
|
||||
const artist_ptr& artist = item->artist();
|
||||
resultStream << QString( "application/tomahawk.metadata.artist" ) << artist->name();
|
||||
}
|
||||
else if ( !item->album().isNull() )
|
||||
{
|
||||
const album_ptr& album = item->album();
|
||||
resultStream << QString( "application/tomahawk.metadata.album" ) << album->artist()->name() << album->name();
|
||||
}
|
||||
else if ( !item->result().isNull() )
|
||||
{
|
||||
const result_ptr& result = item->result();
|
||||
resultStream << QString( "application/tomahawk.result.list" ) << qlonglong( &result );
|
||||
}
|
||||
}
|
||||
|
||||
QMimeData* mimeData = new QMimeData();
|
||||
mimeData->setData( "application/tomahawk.result.list", resultData );
|
||||
|
||||
mimeData->setData( "application/tomahawk.mixed", resultData );
|
||||
return mimeData;
|
||||
}
|
||||
|
||||
@@ -513,6 +616,8 @@ void
|
||||
TreeModel::onAlbumsAdded( const QList<Tomahawk::album_ptr>& albums, const QVariant& data )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << albums.count() << data.toInt();
|
||||
|
||||
emit loadingFinished();
|
||||
if ( !albums.count() )
|
||||
return;
|
||||
|
||||
@@ -555,8 +660,6 @@ TreeModel::onAlbumsAdded( const QList<Tomahawk::album_ptr>& albums, const QVaria
|
||||
emit endInsertRows();
|
||||
else
|
||||
emit dataChanged( albumitem->index, albumitem->index.sibling( albumitem->index.row(), columnCount( QModelIndex() ) - 1 ) );
|
||||
|
||||
emit loadingFinished();
|
||||
}
|
||||
|
||||
|
||||
@@ -564,6 +667,8 @@ void
|
||||
TreeModel::onTracksAdded( const QList<Tomahawk::query_ptr>& tracks, const QVariant& data )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << tracks.count();
|
||||
|
||||
emit loadingFinished();
|
||||
if ( !tracks.count() )
|
||||
return;
|
||||
|
||||
@@ -597,8 +702,6 @@ TreeModel::onTracksAdded( const QList<Tomahawk::query_ptr>& tracks, const QVaria
|
||||
emit endInsertRows();
|
||||
|
||||
emit dataChanged( item->index.sibling( 0, 0 ), item->index.sibling( item->index.row(), columnCount( QModelIndex() ) - 1 ) );
|
||||
|
||||
emit loadingFinished();
|
||||
}
|
||||
|
||||
|
||||
|
@@ -81,8 +81,11 @@ TreeProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent
|
||||
QList< Tomahawk::result_ptr > rl = m_cache.values( sourceParent );
|
||||
foreach ( const Tomahawk::result_ptr& result, rl )
|
||||
{
|
||||
if ( result->track() == pi->result()->track() )
|
||||
if ( result->track() == pi->result()->track() &&
|
||||
( result->albumpos() == pi->result()->albumpos() || result->albumpos() == 0 ) )
|
||||
{
|
||||
return ( result.data() == pi->result().data() );
|
||||
}
|
||||
}
|
||||
|
||||
for ( int i = 0; i < sourceModel()->rowCount( sourceParent ); i++ )
|
||||
@@ -91,7 +94,9 @@ TreeProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent
|
||||
continue;
|
||||
|
||||
TreeModelItem* ti = sourceModel()->itemFromIndex( sourceModel()->index( i, 0, sourceParent ) );
|
||||
if ( ti->result()->track() == pi->result()->track() )
|
||||
|
||||
if ( ti->result()->track() == pi->result()->track() &&
|
||||
( ti->result()->albumpos() == pi->result()->albumpos() || ti->result()->albumpos() == 0 ) )
|
||||
{
|
||||
if ( !pi->result()->isOnline() && ti->result()->isOnline() )
|
||||
return false;
|
||||
@@ -133,13 +138,19 @@ TreeProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) co
|
||||
if ( !p2 )
|
||||
return false;
|
||||
|
||||
const QString& lefts = textForItem( p1 );
|
||||
const QString& rights = textForItem( p2 );
|
||||
|
||||
if ( !p1->result().isNull() )
|
||||
{
|
||||
if ( p1->result()->albumpos() != p2->result()->albumpos() )
|
||||
return p1->result()->albumpos() < p2->result()->albumpos();
|
||||
|
||||
if ( lefts == rights )
|
||||
return (qint64)&p1 < (qint64)&p2;
|
||||
}
|
||||
|
||||
return QString::localeAwareCompare( textForItem( p1 ), textForItem( p2 ) ) < 0;
|
||||
return QString::localeAwareCompare( lefts, rights ) < 0;
|
||||
}
|
||||
|
||||
|
||||
|
66
src/libtomahawk/widgets/SeekSlider.cpp
Normal file
66
src/libtomahawk/widgets/SeekSlider.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "SeekSlider.h"
|
||||
|
||||
#include <QMouseEvent>
|
||||
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "utils/logger.h"
|
||||
|
||||
|
||||
SeekSlider::SeekSlider( QWidget* parent )
|
||||
: QSlider( parent )
|
||||
{
|
||||
setFixedHeight( 20 );
|
||||
setStyleSheet( "QSlider::groove::horizontal {"
|
||||
"margin: 5px; border-width: 3px;"
|
||||
"border-image: url(" RESPATH "images/seek-slider-bkg.png) 3 3 3 3 stretch stretch;"
|
||||
"}"
|
||||
|
||||
"QSlider::sub-page:horizontal {"
|
||||
"margin: 5px; border-width: 3px;"
|
||||
"border-image: url(" RESPATH "images/seek-slider-level.png) 3 3 3 3 stretch stretch;"
|
||||
"}"
|
||||
|
||||
"QSlider::handle::horizontal {"
|
||||
"margin-bottom: -7px; margin-top: -7px;"
|
||||
"margin-left: -4px; margin-right: -4px;"
|
||||
"height: 17px; width: 16px;"
|
||||
"background-image: url(" RESPATH "images/seek-and-volume-knob-rest.png);"
|
||||
"background-repeat: no-repeat;"
|
||||
"}" );
|
||||
}
|
||||
|
||||
|
||||
SeekSlider::~SeekSlider()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SeekSlider::mousePressEvent( QMouseEvent* event )
|
||||
{
|
||||
if ( event->button() == Qt::LeftButton )
|
||||
{
|
||||
QMouseEvent eventSwap( QEvent::MouseButtonRelease, event->pos(), event->globalPos(), Qt::MidButton, Qt::MidButton, event->modifiers() );
|
||||
QSlider::mousePressEvent( &eventSwap );
|
||||
}
|
||||
else
|
||||
QSlider::mousePressEvent( event );
|
||||
}
|
38
src/libtomahawk/widgets/SeekSlider.h
Normal file
38
src/libtomahawk/widgets/SeekSlider.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SEEKSLIDER_H
|
||||
#define SEEKSLIDER_H
|
||||
|
||||
#include <QSlider>
|
||||
|
||||
#include "dllmacro.h"
|
||||
|
||||
class DLLEXPORT SeekSlider : public QSlider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SeekSlider( QWidget* parent = 0 );
|
||||
~SeekSlider();
|
||||
|
||||
protected:
|
||||
void mousePressEvent( QMouseEvent* event );
|
||||
};
|
||||
|
||||
#endif // SEEKSLIDER_H
|
@@ -40,6 +40,15 @@
|
||||
<height>192</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="dragEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragDrop</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -84,16 +93,16 @@
|
||||
<extends>QLabel</extends>
|
||||
<header location="global">widgets/HeaderLabel.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>PlaylistView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>playlist/playlistview.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>AlbumView</class>
|
||||
<extends>QListView</extends>
|
||||
<header>playlist/albumview.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>PlaylistView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>playlist/playlistview.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>CollectionView</class>
|
||||
<extends>QTreeView</extends>
|
||||
|
@@ -108,6 +108,15 @@ void
|
||||
WelcomeWidget::updateRecentTracks()
|
||||
{
|
||||
m_tracksModel->loadHistory( Tomahawk::source_ptr(), HISTORY_TRACK_ITEMS );
|
||||
|
||||
connect( SourceList::instance()->getLocal().data(), SIGNAL( stats( QVariantMap ) ), this, SLOT( updateRecentAdditions() ) );
|
||||
}
|
||||
|
||||
void
|
||||
WelcomeWidget::updateRecentAdditions()
|
||||
{
|
||||
m_recentAlbumsModel->clear();
|
||||
m_recentAlbumsModel->addFilteredCollection( collection_ptr(), 20, DatabaseCommand_AllAlbums::ModificationTime );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -103,6 +103,7 @@ signals:
|
||||
public slots:
|
||||
void updateRecentTracks();
|
||||
void updatePlaylists();
|
||||
void updateRecentAdditions();
|
||||
|
||||
private slots:
|
||||
void onSourceAdded( const Tomahawk::source_ptr& source );
|
||||
|
@@ -30,7 +30,14 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="AlbumView" name="additionsView"/>
|
||||
<widget class="AlbumView" name="additionsView">
|
||||
<property name="dragEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@@ -49,7 +56,7 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="">
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="HeaderLabel" name="label_3">
|
||||
@@ -80,16 +87,16 @@
|
||||
<extends>QLabel</extends>
|
||||
<header location="global">widgets/HeaderLabel.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>PlaylistView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>playlist/playlistview.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>AlbumView</class>
|
||||
<extends>QListView</extends>
|
||||
<header>playlist/albumview.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>PlaylistView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>playlist/playlistview.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>PlaylistWidget</class>
|
||||
<extends>QListWidget</extends>
|
||||
|
@@ -82,7 +82,7 @@ DirLister::scanDir( QDir dir, int depth, DirLister::Mode mode )
|
||||
return;
|
||||
}
|
||||
|
||||
tDebug( LOGVERBOSE ) << "DirLister::scanDir scanning: " << dir.canonicalPath() << " with mode " << mode;
|
||||
tDebug( LOGVERBOSE ) << "DirLister::scanDir scanning:" << dir.canonicalPath() << "with mode" << mode;
|
||||
if( !dir.exists() )
|
||||
{
|
||||
tDebug( LOGVERBOSE ) << "Dir no longer exists, not scanning";
|
||||
@@ -283,14 +283,6 @@ MusicScanner::listerFinished( const QMap<QString, unsigned int>& newmtimes )
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>(cmd) );
|
||||
}
|
||||
|
||||
// re-calculate source stats
|
||||
{
|
||||
DatabaseCommand_CollectionStats* cmd = new DatabaseCommand_CollectionStats( SourceList::instance()->getLocal() );
|
||||
connect( cmd, SIGNAL( done( QVariantMap ) ),
|
||||
SourceList::instance()->getLocal().data(), SLOT( setStats( QVariantMap ) ), Qt::QueuedConnection );
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||
}
|
||||
|
||||
if ( !m_dirLister.isNull() )
|
||||
{
|
||||
m_dirListerThreadController->quit();;
|
||||
|
@@ -183,7 +183,7 @@ QtScriptResolver::init()
|
||||
}
|
||||
const QByteArray scriptContents = scriptFile.readAll();
|
||||
|
||||
m_engine->mainFrame()->setHtml( "<html><body></body></html>" );
|
||||
m_engine->mainFrame()->setHtml( "<html><body></body></html>", QUrl( "file:///invalid/file/for/security/policy" ) );
|
||||
|
||||
// add c++ part of tomahawk javascript library
|
||||
m_engine->mainFrame()->addToJavaScriptWindowObject( "Tomahawk", m_resolverHelper );
|
||||
|
@@ -109,6 +109,11 @@ ResolversModel::setData( const QModelIndex& index, const QVariant& value, int ro
|
||||
m_enabledResolvers.append( resolver );
|
||||
|
||||
TomahawkApp::instance()->enableScriptResolver( resolver );
|
||||
emit dataChanged( index, index );
|
||||
|
||||
if( Tomahawk::ExternalResolver* res = TomahawkApp::instance()->resolverForPath( resolver ) ) {
|
||||
connect( res, SIGNAL( changed() ), this, SLOT( resolverChanged() ) );
|
||||
}
|
||||
} else if( state == Qt::Unchecked ) {
|
||||
m_enabledResolvers.removeAll( resolver );
|
||||
|
||||
|
@@ -51,6 +51,7 @@
|
||||
|
||||
#include "ui_proxydialog.h"
|
||||
#include "ui_stackedsettingsdialog.h"
|
||||
#include <playlist/dynamic/widgets/LoadingSpinner.h>
|
||||
|
||||
static QString
|
||||
md5( const QByteArray& src )
|
||||
@@ -66,6 +67,7 @@ SettingsDialog::SettingsDialog( QWidget *parent )
|
||||
, m_rejected( false )
|
||||
, m_sipModel( 0 )
|
||||
, m_resolversModel( 0 )
|
||||
, m_sipSpinner( 0 )
|
||||
{
|
||||
ui->setupUi( this );
|
||||
TomahawkSettings* s = TomahawkSettings::instance();
|
||||
@@ -107,6 +109,16 @@ SettingsDialog::SettingsDialog( QWidget *parent )
|
||||
m_sipModel = new SipModel( this );
|
||||
ui->accountsView->setModel( m_sipModel );
|
||||
|
||||
if ( !Servent::instance()->isReady() )
|
||||
{
|
||||
m_sipSpinner = new LoadingSpinner( ui->accountsView );
|
||||
m_sipSpinner->fadeIn();
|
||||
|
||||
ui->addSipButton->setEnabled( false );
|
||||
ui->removeSipButton->setEnabled( false );
|
||||
connect( Servent::instance(), SIGNAL( ready() ), this, SLOT( serventReady() ) );
|
||||
}
|
||||
|
||||
setupSipButtons();
|
||||
|
||||
ui->staticHostName->setText( s->externalHostname() );
|
||||
@@ -228,6 +240,13 @@ SettingsDialog::~SettingsDialog()
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void
|
||||
SettingsDialog::serventReady()
|
||||
{
|
||||
m_sipSpinner->fadeOut();
|
||||
ui->addSipButton->setEnabled( true );
|
||||
ui->removeSipButton->setEnabled( true );
|
||||
}
|
||||
|
||||
void
|
||||
SettingsDialog::createIcons()
|
||||
|
@@ -22,6 +22,7 @@
|
||||
#include <QDialog>
|
||||
#include <QModelIndex>
|
||||
|
||||
class LoadingSpinner;
|
||||
class QListWidgetItem;
|
||||
class Ui_StackedSettingsDialog;
|
||||
class SipPluginFactory;
|
||||
@@ -100,6 +101,7 @@ private slots:
|
||||
void sipCreateConfigClosed( int value );
|
||||
|
||||
void changePage( QListWidgetItem*, QListWidgetItem* );
|
||||
void serventReady();
|
||||
|
||||
private:
|
||||
void createIcons();
|
||||
@@ -112,6 +114,7 @@ private:
|
||||
bool m_rejected;
|
||||
SipModel* m_sipModel;
|
||||
ResolversModel* m_resolversModel;
|
||||
LoadingSpinner* m_sipSpinner;
|
||||
};
|
||||
|
||||
#endif // SETTINGSDIALOG_H
|
||||
|
@@ -1,3 +1,22 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2011, Michael Zanetti <mzanetti@kde.org>
|
||||
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "settingslistdelegate.h"
|
||||
#include "utils/logger.h"
|
||||
|
||||
|
@@ -1,3 +1,22 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2011, Michael Zanetti <mzanetti@kde.org>
|
||||
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SETTINGSLISTDELEGATE_H
|
||||
#define SETTINGSLISTDELEGATE_H
|
||||
|
||||
|
@@ -28,7 +28,7 @@
|
||||
#include "widgets/playlisttypeselectordlg.h"
|
||||
#include <playlist/dynamic/GeneratorInterface.h>
|
||||
#include "utils/logger.h"
|
||||
#include <globalactionmanager.h>
|
||||
#include "dropjob.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
@@ -122,7 +122,7 @@ CategoryAddItem::icon() const
|
||||
bool
|
||||
CategoryAddItem::willAcceptDrag( const QMimeData* data ) const
|
||||
{
|
||||
if ( ( m_categoryType == SourcesModel::PlaylistsCategory || m_categoryType == SourcesModel::StationsCategory ) && GlobalActionManager::instance()->acceptsMimeData( data ) )
|
||||
if ( ( m_categoryType == SourcesModel::PlaylistsCategory || m_categoryType == SourcesModel::StationsCategory ) && DropJob::acceptsMimeData( data ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -133,9 +133,96 @@ CategoryAddItem::willAcceptDrag( const QMimeData* data ) const
|
||||
bool
|
||||
CategoryAddItem::dropMimeData( const QMimeData* data, Qt::DropAction )
|
||||
{
|
||||
// As DropJob always converts dropped items to query_ptrs for all tracks we need to extract album/artist metadata ourselves for stations
|
||||
if ( m_categoryType == SourcesModel::StationsCategory &&
|
||||
( data->hasFormat( "application/tomahawk.metadata.artist" ) || data->hasFormat( "application/tomahawk.metadata.album" ) ) )
|
||||
{
|
||||
QByteArray mimeData;
|
||||
if ( data->hasFormat( "application/tomahawk.metadata.artist" ) )
|
||||
mimeData = data->data( "application/tomahawk.metadata.artist" );
|
||||
else if ( data->hasFormat( "application/tomahawk.metadata.album" ) )
|
||||
mimeData = data->data( "application/tomahawk.metadata.album" );
|
||||
|
||||
QDataStream stream( &mimeData, QIODevice::ReadOnly );
|
||||
|
||||
dynplaylist_ptr newpl = DynamicPlaylist::create( SourceList::instance()->getLocal(), uuid(), QString(), "", SourceList::instance()->getLocal()->friendlyName(), OnDemand, false );
|
||||
newpl->setMode( OnDemand );
|
||||
|
||||
QString firstArtist;
|
||||
// now we want to add each artist as a filter...
|
||||
QList< dyncontrol_ptr > contrls;
|
||||
while ( !stream.atEnd() )
|
||||
{
|
||||
QString artist;
|
||||
stream >> artist;
|
||||
if ( firstArtist.isEmpty() )
|
||||
firstArtist = artist;
|
||||
|
||||
QString album;
|
||||
if ( data->hasFormat( "application/tomahawk.metadata.album" ) )
|
||||
stream >> album; // throw away album title... we only create artists filters for now
|
||||
|
||||
dyncontrol_ptr c = newpl->generator()->createControl( "Artist" );
|
||||
c->setInput( QString( "%1" ).arg( artist ) );
|
||||
contrls << c;
|
||||
}
|
||||
|
||||
QString name = firstArtist.isEmpty() ? tr( "New Station" ) : tr( "%1 Station" ).arg( firstArtist );
|
||||
newpl->rename( name );
|
||||
newpl->createNewRevision( uuid(), newpl->currentrevision(), newpl->type(), contrls );
|
||||
|
||||
ViewManager::instance()->show( newpl );
|
||||
return true;
|
||||
}
|
||||
|
||||
// This could be needed once echonest supports filtering by album.
|
||||
// If they never will, or if they do and this code still is not used, throw it away!
|
||||
// If you enable this, make sure to remove the checks for album above.
|
||||
|
||||
/* if ( m_categoryType == SourcesModel::StationsCategory && data->hasFormat( "application/tomahawk.metadata.album" ) )
|
||||
{
|
||||
QByteArray mimeData = data->data( "application/tomahawk.metadata.album" );
|
||||
QDataStream stream( &mimeData, QIODevice::ReadOnly );
|
||||
|
||||
dynplaylist_ptr newpl = DynamicPlaylist::create( SourceList::instance()->getLocal(), uuid(), QString(), "", SourceList::instance()->getLocal()->friendlyName(), OnDemand, false );
|
||||
newpl->setMode( OnDemand );
|
||||
|
||||
QString firstAlbum;
|
||||
// now we want to add each artist as a filter...
|
||||
QList< dyncontrol_ptr > contrls;
|
||||
while ( !stream.atEnd() )
|
||||
{
|
||||
QString artist;
|
||||
stream >> artist;
|
||||
QString album;
|
||||
stream >> album;
|
||||
|
||||
if ( firstAlbum.isEmpty() )
|
||||
{
|
||||
firstAlbum = album;
|
||||
}
|
||||
|
||||
dyncontrol_ptr c = newpl->generator()->createControl( "Album" );
|
||||
c->setInput( QString( "%1" ).arg( artist ) );
|
||||
contrls << c;
|
||||
}
|
||||
|
||||
QString name = firstAlbum.isEmpty() ? tr( "New Station" ) : tr( "%1 Station" ).arg( firstAlbum );
|
||||
newpl->rename( name );
|
||||
newpl->createNewRevision( uuid(), newpl->currentrevision(), newpl->type(), contrls );
|
||||
|
||||
ViewManager::instance()->show( newpl );
|
||||
// Give a shot to try to rename it. The playlist has to be created first. ugly.
|
||||
QTimer::singleShot( 300, APP->mainWindow()->sourceTreeView(), SLOT( renamePlaylist() ) );
|
||||
return true;
|
||||
|
||||
} */
|
||||
|
||||
|
||||
// Create a new playlist seeded with these items
|
||||
connect( GlobalActionManager::instance(), SIGNAL( tracks( QList< Tomahawk::query_ptr > ) ), this, SLOT( parsedDroppedTracks( QList< Tomahawk::query_ptr > ) ) );
|
||||
GlobalActionManager::instance()->tracksFromMimeData( data );
|
||||
DropJob *dj = new DropJob();
|
||||
connect( dj, SIGNAL( tracks( QList< Tomahawk::query_ptr > ) ), this, SLOT( parsedDroppedTracks( QList< Tomahawk::query_ptr > ) ) );
|
||||
dj->tracksFromMimeData( data );
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -143,7 +230,6 @@ CategoryAddItem::dropMimeData( const QMimeData* data, Qt::DropAction )
|
||||
void
|
||||
CategoryAddItem::parsedDroppedTracks( const QList< query_ptr >& tracks )
|
||||
{
|
||||
disconnect( GlobalActionManager::instance(), SIGNAL( tracks( QList< Tomahawk::query_ptr > ) ), this, SLOT( parsedDroppedTracks( QList< Tomahawk::query_ptr > ) ) );
|
||||
if( m_categoryType == SourcesModel::PlaylistsCategory ) {
|
||||
|
||||
playlist_ptr newpl = Playlist::create( SourceList::instance()->getLocal(), uuid(), "New Playlist", "", SourceList::instance()->getLocal()->friendlyName(), false, tracks );
|
||||
|
@@ -139,7 +139,7 @@ CollectionItem::text() const
|
||||
|
||||
|
||||
int
|
||||
CollectionItem::peerSortValue() const
|
||||
CollectionItem::IDValue() const
|
||||
{
|
||||
if( m_source.isNull() )
|
||||
return -1;
|
||||
@@ -150,6 +150,18 @@ CollectionItem::peerSortValue() const
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
CollectionItem::peerSortValue() const
|
||||
{
|
||||
if( m_source.isNull() )
|
||||
return -1;
|
||||
if( m_source->isLocal() )
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CollectionItem::activate()
|
||||
{
|
||||
|
@@ -37,6 +37,7 @@ public:
|
||||
virtual void activate();
|
||||
virtual QIcon icon() const;
|
||||
virtual int peerSortValue() const;
|
||||
virtual int IDValue() const;
|
||||
|
||||
Tomahawk::source_ptr source() const;
|
||||
|
||||
|
@@ -28,7 +28,7 @@
|
||||
#include "collectionitem.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "utils/logger.h"
|
||||
#include "globalactionmanager.h"
|
||||
#include "dropjob.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
@@ -81,6 +81,14 @@ PlaylistItem::onPlaylistChanged()
|
||||
|
||||
int
|
||||
PlaylistItem::peerSortValue() const
|
||||
{
|
||||
// return m_playlist->createdOn();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
PlaylistItem::IDValue() const
|
||||
{
|
||||
return m_playlist->createdOn();
|
||||
}
|
||||
@@ -142,8 +150,9 @@ PlaylistItem::dropMimeData( const QMimeData* data, Qt::DropAction action )
|
||||
data->data( "application/tomahawk.playlist.id" ) == m_playlist->guid() )
|
||||
return false; // don't allow dropping on ourselves
|
||||
|
||||
connect( GlobalActionManager::instance(), SIGNAL( tracks( QList< Tomahawk::query_ptr > ) ), this, SLOT( parsedDroppedTracks( QList< Tomahawk::query_ptr > ) ) );
|
||||
GlobalActionManager::instance()->tracksFromMimeData( data );
|
||||
DropJob *dj = new DropJob();
|
||||
connect( dj, SIGNAL( tracks( QList< Tomahawk::query_ptr > ) ), this, SLOT( parsedDroppedTracks( QList< Tomahawk::query_ptr > ) ) );
|
||||
dj->tracksFromMimeData( data );
|
||||
|
||||
// TODO cant' know if it works or not yet...
|
||||
return true;
|
||||
@@ -152,7 +161,6 @@ PlaylistItem::dropMimeData( const QMimeData* data, Qt::DropAction action )
|
||||
void
|
||||
PlaylistItem::parsedDroppedTracks( const QList< query_ptr >& tracks)
|
||||
{
|
||||
disconnect( GlobalActionManager::instance(), SIGNAL( tracks( QList< Tomahawk::query_ptr > ) ), this, SLOT( parsedDroppedTracks( QList< Tomahawk::query_ptr > ) ) );
|
||||
if ( tracks.count() && !m_playlist.isNull() && m_playlist->author()->isLocal() )
|
||||
{
|
||||
qDebug() << "on playlist:" << m_playlist->title() << m_playlist->guid() << m_playlist->currentrevision();
|
||||
@@ -237,6 +245,14 @@ DynamicPlaylistItem::onDynamicPlaylistLoaded( DynamicPlaylistRevision revision )
|
||||
|
||||
int
|
||||
DynamicPlaylistItem::peerSortValue() const
|
||||
{
|
||||
// return m_dynplaylist->createdOn();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
DynamicPlaylistItem::IDValue() const
|
||||
{
|
||||
return m_dynplaylist->createdOn();
|
||||
}
|
||||
|
@@ -38,6 +38,7 @@ public:
|
||||
virtual QIcon icon() const;
|
||||
virtual bool setData(const QVariant& v, bool role);
|
||||
virtual int peerSortValue() const;
|
||||
virtual int IDValue() const;
|
||||
|
||||
virtual bool activateCurrent();
|
||||
|
||||
@@ -67,6 +68,7 @@ public:
|
||||
virtual bool willAcceptDrag( const QMimeData* data ) const;
|
||||
virtual void activate();
|
||||
virtual int peerSortValue() const;
|
||||
virtual int IDValue() const;
|
||||
virtual QIcon icon() const;
|
||||
|
||||
virtual bool activateCurrent();
|
||||
|
@@ -55,6 +55,7 @@ public:
|
||||
virtual bool dropMimeData( const QMimeData*, Qt::DropAction ) { return false; }
|
||||
virtual bool setData( const QVariant&, bool ) { return false; }
|
||||
virtual int peerSortValue() const { return 0; } // How to sort relative to peers in the tree.
|
||||
virtual int IDValue() const { return 0; }
|
||||
|
||||
/// don't call me unless you are a sourcetreeitem. i prefer this to making everyone a friend
|
||||
void beginRowsAdded( int from, int to ) { emit beginChildRowsAdded( from, to ); }
|
||||
|
@@ -33,6 +33,7 @@
|
||||
|
||||
#include "utils/logger.h"
|
||||
#include "globalactionmanager.h"
|
||||
#include "dropjob.h"
|
||||
#include "items/playlistitems.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
@@ -105,6 +106,8 @@ SourcesModel::data( const QModelIndex& index, int role ) const
|
||||
return itemFromIndex( index )->icon();
|
||||
case SourcesModel::SortRole:
|
||||
return itemFromIndex( index )->peerSortValue();
|
||||
case SourcesModel::IDRole:
|
||||
return itemFromIndex( index )->IDValue();
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
@@ -175,7 +178,7 @@ SourcesModel::setData( const QModelIndex& index, const QVariant& value, int role
|
||||
QStringList
|
||||
SourcesModel::mimeTypes() const
|
||||
{
|
||||
return GlobalActionManager::instance()->mimeTypes();
|
||||
return DropJob::mimeTypes();
|
||||
}
|
||||
|
||||
|
||||
|
@@ -61,7 +61,8 @@ public:
|
||||
enum Roles {
|
||||
SourceTreeItemRole = Qt::UserRole + 10,
|
||||
SourceTreeItemTypeRole = Qt::UserRole + 11,
|
||||
SortRole = Qt::UserRole + 12
|
||||
SortRole = Qt::UserRole + 12,
|
||||
IDRole = Qt::UserRole + 13
|
||||
};
|
||||
|
||||
SourcesModel( QObject* parent = 0 );
|
||||
|
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <QTreeView>
|
||||
|
||||
#include "sourcelist.h"
|
||||
#include "sourcesmodel.h"
|
||||
#include "sourcetree/items/collectionitem.h"
|
||||
|
||||
@@ -36,7 +37,6 @@ SourcesProxyModel::SourcesProxyModel( SourcesModel* model, QObject* parent )
|
||||
|
||||
setSourceModel( model );
|
||||
|
||||
|
||||
if ( model && model->metaObject()->indexOfSignal( "expandRequest(QModelIndex)" ) > -1 )
|
||||
connect( model, SIGNAL( expandRequest( QModelIndex ) ), this, SLOT( expandRequested( QModelIndex ) ) );
|
||||
if ( model && model->metaObject()->indexOfSignal( "selectRequest(QModelIndex)" ) > -1 )
|
||||
@@ -51,13 +51,13 @@ SourcesProxyModel::showOfflineSources( bool offlineSourcesShown )
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SourcesProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const
|
||||
{
|
||||
if ( !m_filtered )
|
||||
return true;
|
||||
|
||||
|
||||
CollectionItem* sti = qobject_cast< CollectionItem* >( m_model->data( sourceModel()->index( sourceRow, 0, sourceParent ), SourcesModel::SourceTreeItemRole ).value< SourceTreeItem* >() );
|
||||
if ( sti )
|
||||
{
|
||||
@@ -70,6 +70,7 @@ SourcesProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourcePar
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourcesProxyModel::selectRequested( const QModelIndex& idx )
|
||||
{
|
||||
@@ -77,6 +78,7 @@ SourcesProxyModel::selectRequested( const QModelIndex& idx )
|
||||
emit selectRequest( mapFromSource( idx ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourcesProxyModel::expandRequested( const QModelIndex& idx )
|
||||
{
|
||||
@@ -84,3 +86,18 @@ SourcesProxyModel::expandRequested( const QModelIndex& idx )
|
||||
emit expandRequest( mapFromSource( idx ) );
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SourcesProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) const
|
||||
{
|
||||
if ( m_model->data( left, SourcesModel::SortRole ) != m_model->data( right, SourcesModel::SortRole ) )
|
||||
return ( m_model->data( left, SourcesModel::SortRole ).toInt() < m_model->data( right, SourcesModel::SortRole ).toInt() );
|
||||
|
||||
const QString& lefts = left.data().toString().toLower();
|
||||
const QString& rights = right.data().toString().toLower();
|
||||
|
||||
if ( lefts == rights )
|
||||
return ( m_model->data( left, SourcesModel::IDRole ).toInt() < m_model->data( right, SourcesModel::IDRole ).toInt() );
|
||||
else
|
||||
return QString::localeAwareCompare( lefts, rights ) < 0;
|
||||
}
|
||||
|
@@ -42,6 +42,7 @@ signals:
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const;
|
||||
bool lessThan( const QModelIndex& left, const QModelIndex& right ) const;
|
||||
|
||||
private:
|
||||
SourcesModel* m_model;
|
||||
|
@@ -37,7 +37,8 @@
|
||||
#include "audio/audioengine.h"
|
||||
#include "sourceplaylistinterface.h"
|
||||
#include "tomahawksettings.h"
|
||||
#include <globalactionmanager.h>
|
||||
#include "globalactionmanager.h"
|
||||
#include "dropjob.h"
|
||||
|
||||
#include "utils/logger.h"
|
||||
|
||||
@@ -439,7 +440,7 @@ SourceTreeView::dragEnterEvent( QDragEnterEvent* event )
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
QTreeView::dragEnterEvent( event );
|
||||
|
||||
if ( GlobalActionManager::instance()->acceptsMimeData( event->mimeData() ) )
|
||||
if ( DropJob::acceptsMimeData( event->mimeData() ) )
|
||||
{
|
||||
m_dragging = true;
|
||||
m_dropRect = QRect();
|
||||
@@ -470,7 +471,7 @@ SourceTreeView::dragMoveEvent( QDragMoveEvent* event )
|
||||
bool accept = false;
|
||||
QTreeView::dragMoveEvent( event );
|
||||
|
||||
if ( GlobalActionManager::instance()->acceptsMimeData( event->mimeData() ) )
|
||||
if ( DropJob::acceptsMimeData( event->mimeData() ) )
|
||||
{
|
||||
setDirtyRegion( m_dropRect );
|
||||
const QPoint pos = event->pos();
|
||||
|
Reference in New Issue
Block a user