mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-09-10 14:10:42 +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_MAJOR 0 )
|
||||||
SET( TOMAHAWK_VERSION_MINOR 2 )
|
SET( TOMAHAWK_VERSION_MINOR 2 )
|
||||||
SET( TOMAHAWK_VERSION_PATCH 1 )
|
SET( TOMAHAWK_VERSION_PATCH 2 )
|
||||||
|
|
||||||
#SET( TOMAHAWK_VERSION_RC 0 )
|
#SET( TOMAHAWK_VERSION_RC 0 )
|
||||||
|
|
||||||
|
@@ -203,7 +203,7 @@ Function PageReinstall
|
|||||||
IntCmp $R0 ${VER_MINOR} build_check new_version older_version
|
IntCmp $R0 ${VER_MINOR} build_check new_version older_version
|
||||||
build_check:
|
build_check:
|
||||||
ReadRegDWORD $R0 HKLM "Software\Tomahawk" "VersionBuild"
|
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:
|
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."
|
!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:
|
Version 0.2.1:
|
||||||
* Fixed crashing trying to play an unavailable track.
|
* Fixed crashing trying to play an unavailable track.
|
||||||
* Fixed a crash caused by using Javascript resolvers.
|
* 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}
|
${QXTWEB_LIBRARIES}
|
||||||
${QJSON_LIBRARIES}
|
${QJSON_LIBRARIES}
|
||||||
${TAGLIB_LIBRARIES}
|
${TAGLIB_LIBRARIES}
|
||||||
${CLUCENE_LIBRARIES}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
#include "utils/tomahawkutils.h"
|
#include "utils/tomahawkutils.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include <globalactionmanager.h>
|
#include <globalactionmanager.h>
|
||||||
|
#include "dropjob.h"
|
||||||
|
|
||||||
using namespace Tomahawk;
|
using namespace Tomahawk;
|
||||||
|
|
||||||
@@ -90,56 +91,9 @@ AudioControls::AudioControls( QWidget* parent )
|
|||||||
ui->ownerLabel->setForegroundRole( QPalette::Dark );
|
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->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->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->setRange( 0, 100 );
|
||||||
ui->volumeSlider->setValue( AudioEngine::instance()->volume() );
|
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->seekSlider, SIGNAL( valueChanged( int ) ), AudioEngine::instance(), SLOT( seek( int ) ) );
|
||||||
connect( ui->volumeSlider, SIGNAL( valueChanged( int ) ), AudioEngine::instance(), SLOT( setVolume( 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 ) ) );
|
connect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ), SLOT( infoSystemFinished( QString ) ) );
|
||||||
|
|
||||||
|
|
||||||
ui->buttonAreaLayout->setSpacing( 0 );
|
ui->buttonAreaLayout->setSpacing( 0 );
|
||||||
ui->stackedLayout->setSpacing( 0 );
|
ui->stackedLayout->setSpacing( 0 );
|
||||||
ui->stackedLayout->setContentsMargins( 0, 0, 0, 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->setValue( 0 );
|
||||||
ui->seekSlider->setVisible( true );
|
ui->seekSlider->setVisible( true );
|
||||||
|
|
||||||
/* m_playAction->setEnabled( false );
|
|
||||||
m_pauseAction->setEnabled( true ); */
|
|
||||||
|
|
||||||
ui->stackedLayout->setCurrentWidget( ui->pauseButton );
|
ui->stackedLayout->setCurrentWidget( ui->pauseButton );
|
||||||
|
|
||||||
ui->loveButton->setEnabled( true );
|
ui->loveButton->setEnabled( true );
|
||||||
@@ -343,18 +293,12 @@ AudioControls::socialActionsLoaded()
|
|||||||
void
|
void
|
||||||
AudioControls::onPlaybackPaused()
|
AudioControls::onPlaybackPaused()
|
||||||
{
|
{
|
||||||
/* m_pauseAction->setEnabled( false );
|
|
||||||
m_playAction->setEnabled( true ); */
|
|
||||||
|
|
||||||
ui->stackedLayout->setCurrentWidget( ui->playPauseButton );
|
ui->stackedLayout->setCurrentWidget( ui->playPauseButton );
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioControls::onPlaybackResumed()
|
AudioControls::onPlaybackResumed()
|
||||||
{
|
{
|
||||||
/* m_playAction->setEnabled( false );
|
|
||||||
m_pauseAction->setEnabled( true ); */
|
|
||||||
|
|
||||||
ui->stackedLayout->setCurrentWidget( ui->pauseButton );
|
ui->stackedLayout->setCurrentWidget( ui->pauseButton );
|
||||||
ui->loveButton->setVisible( true );
|
ui->loveButton->setVisible( true );
|
||||||
}
|
}
|
||||||
@@ -376,9 +320,6 @@ AudioControls::onPlaybackStopped()
|
|||||||
ui->stackedLayout->setCurrentWidget( ui->playPauseButton );
|
ui->stackedLayout->setCurrentWidget( ui->playPauseButton );
|
||||||
ui->loveButton->setEnabled( false );
|
ui->loveButton->setEnabled( false );
|
||||||
ui->loveButton->setVisible( false );
|
ui->loveButton->setVisible( false );
|
||||||
|
|
||||||
/* m_pauseAction->setEnabled( false );
|
|
||||||
m_playAction->setEnabled( true ); */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -521,7 +462,7 @@ AudioControls::onTrackClicked()
|
|||||||
void
|
void
|
||||||
AudioControls::dragEnterEvent( QDragEnterEvent* e )
|
AudioControls::dragEnterEvent( QDragEnterEvent* e )
|
||||||
{
|
{
|
||||||
if ( GlobalActionManager::instance()->acceptsMimeData( e->mimeData() ) )
|
if ( DropJob::acceptsMimeData( e->mimeData() ) )
|
||||||
e->acceptProposedAction();
|
e->acceptProposedAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -538,10 +479,11 @@ void
|
|||||||
AudioControls::dropEvent( QDropEvent* e )
|
AudioControls::dropEvent( QDropEvent* e )
|
||||||
{
|
{
|
||||||
tDebug() << "AudioControls got drop:" << e->mimeData()->formats();
|
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> ) ) );
|
DropJob *dj = new DropJob();
|
||||||
GlobalActionManager::instance()->tracksFromMimeData( e->mimeData() );
|
connect( dj, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( droppedTracks( QList<Tomahawk::query_ptr> ) ) );
|
||||||
|
dj->tracksFromMimeData( e->mimeData() );
|
||||||
|
|
||||||
e->accept();
|
e->accept();
|
||||||
}
|
}
|
||||||
@@ -551,8 +493,6 @@ AudioControls::dropEvent( QDropEvent* e )
|
|||||||
void
|
void
|
||||||
AudioControls::droppedTracks( QList< query_ptr > tracks )
|
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() )
|
if ( !tracks.isEmpty() )
|
||||||
{
|
{
|
||||||
// queue and play the first if nothign is playing
|
// queue and play the first if nothign is playing
|
||||||
|
@@ -82,11 +82,6 @@ private slots:
|
|||||||
private:
|
private:
|
||||||
Ui::AudioControls *ui;
|
Ui::AudioControls *ui;
|
||||||
|
|
||||||
QAction* m_playAction;
|
|
||||||
QAction* m_pauseAction;
|
|
||||||
QAction* m_prevAction;
|
|
||||||
QAction* m_nextAction;
|
|
||||||
|
|
||||||
QPixmap m_defaultCover;
|
QPixmap m_defaultCover;
|
||||||
|
|
||||||
Tomahawk::result_ptr m_currentTrack;
|
Tomahawk::result_ptr m_currentTrack;
|
||||||
|
@@ -337,7 +337,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSlider" name="seekSlider">
|
<widget class="SeekSlider" name="seekSlider">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>0</width>
|
<width>0</width>
|
||||||
@@ -489,7 +489,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSlider" name="volumeSlider">
|
<widget class="SeekSlider" name="volumeSlider">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>0</width>
|
<width>0</width>
|
||||||
@@ -529,6 +529,11 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>SeekSlider</class>
|
||||||
|
<extends>QSlider</extends>
|
||||||
|
<header location="global">widgets/SeekSlider.h</header>
|
||||||
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>ImageButton</class>
|
<class>ImageButton</class>
|
||||||
<extends>QPushButton</extends>
|
<extends>QPushButton</extends>
|
||||||
|
@@ -31,6 +31,7 @@ set( libSources
|
|||||||
viewmanager.cpp
|
viewmanager.cpp
|
||||||
globalactionmanager.cpp
|
globalactionmanager.cpp
|
||||||
contextmenu.cpp
|
contextmenu.cpp
|
||||||
|
dropjob.cpp
|
||||||
|
|
||||||
sip/SipPlugin.cpp
|
sip/SipPlugin.cpp
|
||||||
sip/SipHandler.cpp
|
sip/SipHandler.cpp
|
||||||
@@ -176,6 +177,7 @@ set( libSources
|
|||||||
|
|
||||||
widgets/newplaylistwidget.cpp
|
widgets/newplaylistwidget.cpp
|
||||||
widgets/searchwidget.cpp
|
widgets/searchwidget.cpp
|
||||||
|
widgets/SeekSlider.cpp
|
||||||
widgets/playlisttypeselectordlg.cpp
|
widgets/playlisttypeselectordlg.cpp
|
||||||
widgets/welcomewidget.cpp
|
widgets/welcomewidget.cpp
|
||||||
widgets/welcomeplaylistmodel.cpp
|
widgets/welcomeplaylistmodel.cpp
|
||||||
@@ -208,6 +210,7 @@ set( libHeaders
|
|||||||
viewmanager.h
|
viewmanager.h
|
||||||
globalactionmanager.h
|
globalactionmanager.h
|
||||||
contextmenu.h
|
contextmenu.h
|
||||||
|
dropjob.h
|
||||||
|
|
||||||
artist.h
|
artist.h
|
||||||
album.h
|
album.h
|
||||||
@@ -354,6 +357,7 @@ set( libHeaders
|
|||||||
|
|
||||||
widgets/newplaylistwidget.h
|
widgets/newplaylistwidget.h
|
||||||
widgets/searchwidget.h
|
widgets/searchwidget.h
|
||||||
|
widgets/SeekSlider.h
|
||||||
widgets/playlisttypeselectordlg.h
|
widgets/playlisttypeselectordlg.h
|
||||||
widgets/welcomewidget.h
|
widgets/welcomewidget.h
|
||||||
widgets/welcomeplaylistmodel.h
|
widgets/welcomeplaylistmodel.h
|
||||||
|
@@ -212,7 +212,7 @@ AudioEngine::next()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if ( !m_currentTrack.isNull() && !m_playlist.data()->hasNextItem() &&
|
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
|
//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
|
//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() );
|
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : result->url() );
|
||||||
|
|
||||||
if ( !result->isOnline() )
|
|
||||||
return;
|
|
||||||
if ( !m_playlist.isNull() )
|
if ( !m_playlist.isNull() )
|
||||||
m_playlist.data()->reset();
|
m_playlist.data()->reset();
|
||||||
|
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
#include "databasecommand_collectionstats.h"
|
#include "databasecommand_collectionstats.h"
|
||||||
#include "databaseimpl.h"
|
#include "databaseimpl.h"
|
||||||
#include "network/controlconnection.h"
|
#include "network/controlconnection.h"
|
||||||
|
#include "sourcelist.h"
|
||||||
|
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
|
|
||||||
@@ -72,7 +73,15 @@ DatabaseCommand_AddFiles::postCommitHook()
|
|||||||
emit notify( m_queries );
|
emit notify( m_queries );
|
||||||
|
|
||||||
if( source()->isLocal() )
|
if( source()->isLocal() )
|
||||||
|
{
|
||||||
Servent::instance()->triggerDBSync();
|
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;
|
al << album;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( al.count() )
|
emit albums( al, data() );
|
||||||
emit albums( al, data() );
|
|
||||||
emit done();
|
emit done();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,8 +123,7 @@ DatabaseCommand_AllAlbums::execForCollection( DatabaseImpl* dbi )
|
|||||||
al << album;
|
al << album;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( al.count() )
|
emit albums( al, data() );
|
||||||
emit albums( al, data() );
|
|
||||||
emit done();
|
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 )
|
GlobalActionManager::GlobalActionManager( QObject* parent )
|
||||||
: QObject( parent )
|
: QObject( parent )
|
||||||
{
|
{
|
||||||
m_mimeTypes << "application/tomahawk.query.list" << "application/tomahawk.plentry.list" << "application/tomahawk.result.list" << "text/plain";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalActionManager::~GlobalActionManager()
|
GlobalActionManager::~GlobalActionManager()
|
||||||
@@ -779,149 +778,6 @@ GlobalActionManager::hostname() const
|
|||||||
return QString( "http://toma.hk" );
|
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
|
/// SPOTIFY URL HANDLING
|
||||||
|
|
||||||
|
@@ -51,18 +51,6 @@ public:
|
|||||||
QString copyPlaylistToClipboard( const Tomahawk::dynplaylist_ptr& playlist );
|
QString copyPlaylistToClipboard( const Tomahawk::dynplaylist_ptr& playlist );
|
||||||
void savePlaylistToFile( const Tomahawk::playlist_ptr& playlist, const QString& filename );
|
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:
|
public slots:
|
||||||
bool parseTomahawkLink( const QString& link );
|
bool parseTomahawkLink( const QString& link );
|
||||||
void waitingForResolved( bool );
|
void waitingForResolved( bool );
|
||||||
@@ -70,16 +58,12 @@ public slots:
|
|||||||
Tomahawk::dynplaylist_ptr loadDynamicPlaylist( const QUrl& url, bool station );
|
Tomahawk::dynplaylist_ptr loadDynamicPlaylist( const QUrl& url, bool station );
|
||||||
|
|
||||||
void handleOpenTrack( const Tomahawk::query_ptr& qry );
|
void handleOpenTrack( const Tomahawk::query_ptr& qry );
|
||||||
signals:
|
|
||||||
/// QMimeData parsing results
|
|
||||||
void tracks( const QList< Tomahawk::query_ptr >& tracks );
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void bookmarkPlaylistCreated( const Tomahawk::playlist_ptr& pl );
|
void bookmarkPlaylistCreated( const Tomahawk::playlist_ptr& pl );
|
||||||
void showPlaylist();
|
void showPlaylist();
|
||||||
|
|
||||||
void xspfCreated( const QByteArray& xspf );
|
void xspfCreated( const QByteArray& xspf );
|
||||||
void expandedUrls( QStringList );
|
|
||||||
|
|
||||||
void spotifyToPlay( const Tomahawk::query_ptr& );
|
void spotifyToPlay( const Tomahawk::query_ptr& );
|
||||||
private:
|
private:
|
||||||
@@ -101,18 +85,12 @@ private:
|
|||||||
bool playSpotify( const QUrl& url );
|
bool playSpotify( const QUrl& url );
|
||||||
bool queueSpotify( const QStringList& parts, const QList< QPair< QString, QString > >& queryItems );
|
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;
|
QString hostname() const;
|
||||||
|
|
||||||
Tomahawk::playlist_ptr m_toShow;
|
Tomahawk::playlist_ptr m_toShow;
|
||||||
Tomahawk::query_ptr m_waitingToBookmark;
|
Tomahawk::query_ptr m_waitingToBookmark;
|
||||||
Tomahawk::query_ptr m_waitingToPlay;
|
Tomahawk::query_ptr m_waitingToPlay;
|
||||||
|
|
||||||
QStringList m_mimeTypes;
|
|
||||||
static GlobalActionManager* s_instance;
|
static GlobalActionManager* s_instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -283,7 +283,7 @@ DBSyncConnection::lastOpApplied()
|
|||||||
void
|
void
|
||||||
DBSyncConnection::sendOps()
|
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();
|
source_ptr src = SourceList::instance()->getLocal();
|
||||||
|
|
||||||
|
@@ -60,6 +60,7 @@ Servent::Servent( QObject* parent )
|
|||||||
: QTcpServer( parent )
|
: QTcpServer( parent )
|
||||||
, m_port( 0 )
|
, m_port( 0 )
|
||||||
, m_externalPort( 0 )
|
, m_externalPort( 0 )
|
||||||
|
, m_ready( false )
|
||||||
, m_portfwd( 0 )
|
, m_portfwd( 0 )
|
||||||
{
|
{
|
||||||
s_instance = this;
|
s_instance = this;
|
||||||
@@ -133,6 +134,7 @@ Servent::startListening( QHostAddress ha, bool upnp, int port )
|
|||||||
tLog() << "Forcing static preferred host and port";
|
tLog() << "Forcing static preferred host and port";
|
||||||
m_externalHostname = TomahawkSettings::instance()->externalHostname();
|
m_externalHostname = TomahawkSettings::instance()->externalHostname();
|
||||||
m_externalPort = TomahawkSettings::instance()->externalPort();
|
m_externalPort = TomahawkSettings::instance()->externalPort();
|
||||||
|
m_ready = true;
|
||||||
emit ready();
|
emit ready();
|
||||||
return true;
|
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 ) );
|
QMetaObject::invokeMethod( this, "setExternalAddress", Qt::QueuedConnection, Q_ARG( QHostAddress, ha ), Q_ARG( unsigned int, m_port ) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
m_ready = true;
|
||||||
emit ready();
|
emit ready();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -227,6 +232,7 @@ Servent::setExternalAddress( QHostAddress ha, unsigned int port )
|
|||||||
qDebug() << "No external access, LAN and outbound connections only!";
|
qDebug() << "No external access, LAN and outbound connections only!";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_ready = true;
|
||||||
emit ready();
|
emit ready();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||||
*
|
*
|
||||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||||
*
|
*
|
||||||
* Tomahawk is free software: you can redistribute it and/or modify
|
* 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> localFileIODeviceFactory( const Tomahawk::result_ptr& result );
|
||||||
QSharedPointer<QIODevice> httpIODeviceFactory( const Tomahawk::result_ptr& result );
|
QSharedPointer<QIODevice> httpIODeviceFactory( const Tomahawk::result_ptr& result );
|
||||||
|
|
||||||
|
bool isReady() const { return m_ready; };
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void streamStarted( StreamConnection* );
|
void streamStarted( StreamConnection* );
|
||||||
void streamFinished( StreamConnection* );
|
void streamFinished( StreamConnection* );
|
||||||
@@ -159,6 +161,7 @@ private:
|
|||||||
int m_port, m_externalPort;
|
int m_port, m_externalPort;
|
||||||
QHostAddress m_externalAddress;
|
QHostAddress m_externalAddress;
|
||||||
QString m_externalHostname;
|
QString m_externalHostname;
|
||||||
|
bool m_ready;
|
||||||
|
|
||||||
// currently active file transfers:
|
// currently active file transfers:
|
||||||
QList< StreamConnection* > m_scsessions;
|
QList< StreamConnection* > m_scsessions;
|
||||||
|
@@ -196,22 +196,7 @@ Pipeline::reportResults( QID qid, const QList< result_ptr >& results )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( decQIDState( q ) == 0 )
|
decQIDState( q );
|
||||||
{
|
|
||||||
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 );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -260,8 +245,7 @@ Pipeline::timeoutShunt( const query_ptr& q )
|
|||||||
// are we still waiting for a timeout?
|
// are we still waiting for a timeout?
|
||||||
if ( m_qidsTimeout.contains( q->id() ) )
|
if ( m_qidsTimeout.contains( q->id() ) )
|
||||||
{
|
{
|
||||||
m_qidsTimeout.remove( q->id() );
|
decQIDState( q );
|
||||||
shunt( q );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,7 +262,7 @@ Pipeline::shunt( const query_ptr& q )
|
|||||||
|
|
||||||
if ( r )
|
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 );
|
q->setCurrentResolver( r );
|
||||||
r->resolve( q );
|
r->resolve( q );
|
||||||
@@ -374,6 +358,25 @@ Pipeline::decQIDState( const Tomahawk::query_ptr& query )
|
|||||||
// qDebug() << "Queries running:" << m_qidsState.count();
|
// 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;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -159,6 +159,7 @@ AlbumModel::headerData( int section, Qt::Orientation orientation, int role ) con
|
|||||||
Qt::ItemFlags
|
Qt::ItemFlags
|
||||||
AlbumModel::flags( const QModelIndex& index ) const
|
AlbumModel::flags( const QModelIndex& index ) const
|
||||||
{
|
{
|
||||||
|
qDebug() << "asking for flags for index" << index;
|
||||||
Qt::ItemFlags defaultFlags = QAbstractItemModel::flags( index );
|
Qt::ItemFlags defaultFlags = QAbstractItemModel::flags( index );
|
||||||
|
|
||||||
if ( index.isValid() && index.column() == 0 )
|
if ( index.isValid() && index.column() == 0 )
|
||||||
@@ -195,12 +196,13 @@ AlbumModel::mimeData( const QModelIndexList &indexes ) const
|
|||||||
if ( item )
|
if ( item )
|
||||||
{
|
{
|
||||||
const album_ptr& album = item->album();
|
const album_ptr& album = item->album();
|
||||||
queryStream << qlonglong( &album );
|
queryStream << album->artist()->name();
|
||||||
|
queryStream << album->name();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QMimeData* mimeData = new QMimeData();
|
QMimeData* mimeData = new QMimeData();
|
||||||
mimeData->setData( "application/tomahawk.query.list", queryData );
|
mimeData->setData( "application/tomahawk.metadata.album", queryData );
|
||||||
|
|
||||||
return mimeData;
|
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
|
void
|
||||||
AlbumView::paintEvent( QPaintEvent* event )
|
AlbumView::paintEvent( QPaintEvent* event )
|
||||||
{
|
{
|
||||||
@@ -227,14 +206,30 @@ AlbumView::onFilterChanged( const QString& )
|
|||||||
void
|
void
|
||||||
AlbumView::startDrag( Qt::DropActions supportedActions )
|
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
|
qDebug() << "Dragging" << indexes.count() << "indexes";
|
||||||
QPixmap
|
QMimeData* data = m_proxyModel->mimeData( indexes );
|
||||||
AlbumView::createDragPixmap( int itemCount ) const
|
if ( !data )
|
||||||
{
|
return;
|
||||||
Q_UNUSED( itemCount );
|
|
||||||
return QPixmap();
|
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:
|
protected:
|
||||||
virtual void startDrag( Qt::DropActions supportedActions );
|
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 );
|
void paintEvent( QPaintEvent* event );
|
||||||
|
|
||||||
@@ -73,8 +70,6 @@ private slots:
|
|||||||
void onScrollTimeout();
|
void onScrollTimeout();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPixmap createDragPixmap( int itemCount ) const;
|
|
||||||
|
|
||||||
AlbumModel* m_model;
|
AlbumModel* m_model;
|
||||||
AlbumProxyModel* m_proxyModel;
|
AlbumProxyModel* m_proxyModel;
|
||||||
// PlaylistItemDelegate* m_delegate;
|
// PlaylistItemDelegate* m_delegate;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||||
*
|
*
|
||||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||||
*
|
*
|
||||||
* Tomahawk is free software: you can redistribute it and/or modify
|
* Tomahawk is free software: you can redistribute it and/or modify
|
||||||
@@ -21,31 +21,33 @@
|
|||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include "dllmacro.h"
|
||||||
|
|
||||||
class QMovie;
|
class QMovie;
|
||||||
class QTimeLine;
|
class QTimeLine;
|
||||||
/**
|
/**
|
||||||
* A small widget that displays an animated loading spinner
|
* A small widget that displays an animated loading spinner
|
||||||
*/
|
*/
|
||||||
class LoadingSpinner : public QWidget {
|
class DLLEXPORT LoadingSpinner : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
LoadingSpinner( QWidget* parent );
|
LoadingSpinner( QWidget* parent );
|
||||||
virtual ~LoadingSpinner();
|
virtual ~LoadingSpinner();
|
||||||
|
|
||||||
virtual QSize sizeHint() const;
|
virtual QSize sizeHint() const;
|
||||||
virtual void paintEvent( QPaintEvent* );
|
virtual void paintEvent( QPaintEvent* );
|
||||||
virtual void resizeEvent( QResizeEvent* );
|
virtual void resizeEvent( QResizeEvent* );
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void fadeIn();
|
void fadeIn();
|
||||||
void fadeOut();
|
void fadeOut();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void hideFinished();
|
void hideFinished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void reposition();
|
void reposition();
|
||||||
|
|
||||||
QTimeLine* m_showHide;
|
QTimeLine* m_showHide;
|
||||||
QMovie* m_anim;
|
QMovie* m_anim;
|
||||||
};
|
};
|
||||||
|
@@ -27,7 +27,7 @@
|
|||||||
#include "database/databasecommand_playbackhistory.h"
|
#include "database/databasecommand_playbackhistory.h"
|
||||||
#include "dynamic/GeneratorInterface.h"
|
#include "dynamic/GeneratorInterface.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include "globalactionmanager.h"
|
#include "dropjob.h"
|
||||||
|
|
||||||
using namespace Tomahawk;
|
using namespace Tomahawk;
|
||||||
|
|
||||||
@@ -358,14 +358,15 @@ PlaylistModel::dropMimeData( const QMimeData* data, Qt::DropAction action, int r
|
|||||||
if ( action == Qt::IgnoreAction || isReadOnly() )
|
if ( action == Qt::IgnoreAction || isReadOnly() )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if ( !GlobalActionManager::instance()->acceptsMimeData( data ) )
|
if ( !DropJob::acceptsMimeData( data ) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_dropStorage.row = row;
|
m_dropStorage.row = row;
|
||||||
m_dropStorage.parent = QPersistentModelIndex( parent );
|
m_dropStorage.parent = QPersistentModelIndex( parent );
|
||||||
m_dropStorage.action = action;
|
m_dropStorage.action = action;
|
||||||
connect( GlobalActionManager::instance(), SIGNAL( tracks( QList< Tomahawk::query_ptr > ) ), this, SLOT( parsedDroppedTracks( QList< Tomahawk::query_ptr > ) ) );
|
DropJob *dj = new DropJob();
|
||||||
GlobalActionManager::instance()->tracksFromMimeData( data );
|
connect( dj, SIGNAL( tracks( QList< Tomahawk::query_ptr > ) ), this, SLOT( parsedDroppedTracks( QList< Tomahawk::query_ptr > ) ) );
|
||||||
|
dj->tracksFromMimeData( data );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -377,8 +378,6 @@ PlaylistModel::parsedDroppedTracks( QList< query_ptr > tracks )
|
|||||||
if ( m_dropStorage.row == -10 ) // nope
|
if ( m_dropStorage.row == -10 ) // nope
|
||||||
return;
|
return;
|
||||||
|
|
||||||
disconnect( GlobalActionManager::instance(), SIGNAL( tracks( QList< Tomahawk::query_ptr > ) ), this, SLOT( parsedDroppedTracks( QList< Tomahawk::query_ptr > ) ) );
|
|
||||||
|
|
||||||
int beginRow;
|
int beginRow;
|
||||||
if ( m_dropStorage.row != -1 )
|
if ( m_dropStorage.row != -1 )
|
||||||
beginRow = m_dropStorage.row;
|
beginRow = m_dropStorage.row;
|
||||||
|
@@ -177,7 +177,7 @@ Tomahawk::result_ptr
|
|||||||
TrackProxyModel::currentItem() const
|
TrackProxyModel::currentItem() const
|
||||||
{
|
{
|
||||||
TrackModelItem* item = itemFromIndex( mapToSource( currentIndex() ) );
|
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 item->query()->results().at( 0 );
|
||||||
return Tomahawk::result_ptr();
|
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 albumpos1 = 0, albumpos2 = 0;
|
||||||
unsigned int bitrate1 = 0, bitrate2 = 0;
|
unsigned int bitrate1 = 0, bitrate2 = 0;
|
||||||
unsigned int mtime1 = 0, mtime2 = 0;
|
unsigned int mtime1 = 0, mtime2 = 0;
|
||||||
unsigned int id1 = 0, id2 = 0;
|
|
||||||
unsigned int size1 = 0, size2 = 0;
|
unsigned int size1 = 0, size2 = 0;
|
||||||
|
qint64 id1 = 0, id2 = 0;
|
||||||
|
|
||||||
if ( q1->numResults() )
|
if ( q1->numResults() )
|
||||||
{
|
{
|
||||||
@@ -346,6 +346,13 @@ TrackProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) c
|
|||||||
size2 = r->size();
|
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 ( left.column() == TrackModel::Artist ) // sort by artist
|
||||||
{
|
{
|
||||||
if ( artist1 == artist2 )
|
if ( artist1 == artist2 )
|
||||||
@@ -396,6 +403,11 @@ TrackProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) c
|
|||||||
|
|
||||||
return size1 < size2;
|
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 "dynamic/widgets/LoadingSpinner.h"
|
||||||
#include "utils/tomahawkutils.h"
|
#include "utils/tomahawkutils.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include <globalactionmanager.h>
|
#include "dropjob.h"
|
||||||
|
|
||||||
using namespace Tomahawk;
|
using namespace Tomahawk;
|
||||||
|
|
||||||
@@ -214,7 +214,7 @@ TrackView::dragEnterEvent( QDragEnterEvent* event )
|
|||||||
qDebug() << Q_FUNC_INFO;
|
qDebug() << Q_FUNC_INFO;
|
||||||
QTreeView::dragEnterEvent( event );
|
QTreeView::dragEnterEvent( event );
|
||||||
|
|
||||||
if ( GlobalActionManager::instance()->acceptsMimeData( event->mimeData() ) )
|
if ( DropJob::acceptsMimeData( event->mimeData() ) )
|
||||||
{
|
{
|
||||||
m_dragging = true;
|
m_dragging = true;
|
||||||
m_dropRect = QRect();
|
m_dropRect = QRect();
|
||||||
@@ -236,7 +236,7 @@ TrackView::dragMoveEvent( QDragMoveEvent* event )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( GlobalActionManager::instance()->acceptsMimeData( event->mimeData() ) )
|
if ( DropJob::acceptsMimeData( event->mimeData() ) )
|
||||||
{
|
{
|
||||||
setDirtyRegion( m_dropRect );
|
setDirtyRegion( m_dropRect );
|
||||||
const QPoint pos = event->pos();
|
const QPoint pos = event->pos();
|
||||||
@@ -278,7 +278,7 @@ TrackView::dropEvent( QDropEvent* event )
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( GlobalActionManager::instance()->acceptsMimeData( event->mimeData() ) )
|
if ( DropJob::acceptsMimeData( event->mimeData() ) )
|
||||||
{
|
{
|
||||||
const QPoint pos = event->pos();
|
const QPoint pos = event->pos();
|
||||||
const QModelIndex index = indexAt( pos );
|
const QModelIndex index = indexAt( pos );
|
||||||
|
@@ -293,6 +293,8 @@ TreeModel::flags( const QModelIndex& index ) const
|
|||||||
TreeModelItem* item = itemFromIndex( index );
|
TreeModelItem* item = itemFromIndex( index );
|
||||||
if ( item && !item->result().isNull() )
|
if ( item && !item->result().isNull() )
|
||||||
return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
|
return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
|
||||||
|
if ( item && ( !item->album().isNull() || !item->artist().isNull() ) )
|
||||||
|
return Qt::ItemIsDragEnabled | defaultFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
return defaultFlags;
|
return defaultFlags;
|
||||||
@@ -303,7 +305,7 @@ QStringList
|
|||||||
TreeModel::mimeTypes() const
|
TreeModel::mimeTypes() const
|
||||||
{
|
{
|
||||||
QStringList types;
|
QStringList types;
|
||||||
types << "application/tomahawk.result.list";
|
types << "application/tomahawk.mixed";
|
||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,23 +318,124 @@ TreeModel::mimeData( const QModelIndexList &indexes ) const
|
|||||||
QByteArray resultData;
|
QByteArray resultData;
|
||||||
QDataStream resultStream( &resultData, QIODevice::WriteOnly );
|
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;
|
continue;
|
||||||
|
|
||||||
QModelIndex idx = index( i.row(), 0, i.parent() );
|
TreeModelItem* item = itemFromIndex( i );
|
||||||
TreeModelItem* item = itemFromIndex( idx );
|
if ( !item )
|
||||||
if ( item && !item->result().isNull() )
|
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();
|
const result_ptr& result = item->result();
|
||||||
resultStream << qlonglong( &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();
|
QMimeData* mimeData = new QMimeData();
|
||||||
mimeData->setData( "application/tomahawk.result.list", resultData );
|
mimeData->setData( "application/tomahawk.mixed", resultData );
|
||||||
|
|
||||||
return mimeData;
|
return mimeData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -513,6 +616,8 @@ void
|
|||||||
TreeModel::onAlbumsAdded( const QList<Tomahawk::album_ptr>& albums, const QVariant& data )
|
TreeModel::onAlbumsAdded( const QList<Tomahawk::album_ptr>& albums, const QVariant& data )
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO << albums.count() << data.toInt();
|
qDebug() << Q_FUNC_INFO << albums.count() << data.toInt();
|
||||||
|
|
||||||
|
emit loadingFinished();
|
||||||
if ( !albums.count() )
|
if ( !albums.count() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -555,8 +660,6 @@ TreeModel::onAlbumsAdded( const QList<Tomahawk::album_ptr>& albums, const QVaria
|
|||||||
emit endInsertRows();
|
emit endInsertRows();
|
||||||
else
|
else
|
||||||
emit dataChanged( albumitem->index, albumitem->index.sibling( albumitem->index.row(), columnCount( QModelIndex() ) - 1 ) );
|
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 )
|
TreeModel::onTracksAdded( const QList<Tomahawk::query_ptr>& tracks, const QVariant& data )
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO << tracks.count();
|
qDebug() << Q_FUNC_INFO << tracks.count();
|
||||||
|
|
||||||
|
emit loadingFinished();
|
||||||
if ( !tracks.count() )
|
if ( !tracks.count() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -597,8 +702,6 @@ TreeModel::onTracksAdded( const QList<Tomahawk::query_ptr>& tracks, const QVaria
|
|||||||
emit endInsertRows();
|
emit endInsertRows();
|
||||||
|
|
||||||
emit dataChanged( item->index.sibling( 0, 0 ), item->index.sibling( item->index.row(), columnCount( QModelIndex() ) - 1 ) );
|
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 );
|
QList< Tomahawk::result_ptr > rl = m_cache.values( sourceParent );
|
||||||
foreach ( const Tomahawk::result_ptr& result, rl )
|
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() );
|
return ( result.data() == pi->result().data() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i = 0; i < sourceModel()->rowCount( sourceParent ); i++ )
|
for ( int i = 0; i < sourceModel()->rowCount( sourceParent ); i++ )
|
||||||
@@ -91,7 +94,9 @@ TreeProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
TreeModelItem* ti = sourceModel()->itemFromIndex( sourceModel()->index( i, 0, sourceParent ) );
|
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() )
|
if ( !pi->result()->isOnline() && ti->result()->isOnline() )
|
||||||
return false;
|
return false;
|
||||||
@@ -133,13 +138,19 @@ TreeProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) co
|
|||||||
if ( !p2 )
|
if ( !p2 )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
const QString& lefts = textForItem( p1 );
|
||||||
|
const QString& rights = textForItem( p2 );
|
||||||
|
|
||||||
if ( !p1->result().isNull() )
|
if ( !p1->result().isNull() )
|
||||||
{
|
{
|
||||||
if ( p1->result()->albumpos() != p2->result()->albumpos() )
|
if ( p1->result()->albumpos() != p2->result()->albumpos() )
|
||||||
return 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>
|
<height>192</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</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>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
@@ -84,16 +93,16 @@
|
|||||||
<extends>QLabel</extends>
|
<extends>QLabel</extends>
|
||||||
<header location="global">widgets/HeaderLabel.h</header>
|
<header location="global">widgets/HeaderLabel.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
<customwidget>
|
|
||||||
<class>PlaylistView</class>
|
|
||||||
<extends>QTreeView</extends>
|
|
||||||
<header>playlist/playlistview.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>AlbumView</class>
|
<class>AlbumView</class>
|
||||||
<extends>QListView</extends>
|
<extends>QListView</extends>
|
||||||
<header>playlist/albumview.h</header>
|
<header>playlist/albumview.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>PlaylistView</class>
|
||||||
|
<extends>QTreeView</extends>
|
||||||
|
<header>playlist/playlistview.h</header>
|
||||||
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>CollectionView</class>
|
<class>CollectionView</class>
|
||||||
<extends>QTreeView</extends>
|
<extends>QTreeView</extends>
|
||||||
|
@@ -108,6 +108,15 @@ void
|
|||||||
WelcomeWidget::updateRecentTracks()
|
WelcomeWidget::updateRecentTracks()
|
||||||
{
|
{
|
||||||
m_tracksModel->loadHistory( Tomahawk::source_ptr(), HISTORY_TRACK_ITEMS );
|
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:
|
public slots:
|
||||||
void updateRecentTracks();
|
void updateRecentTracks();
|
||||||
void updatePlaylists();
|
void updatePlaylists();
|
||||||
|
void updateRecentAdditions();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onSourceAdded( const Tomahawk::source_ptr& source );
|
void onSourceAdded( const Tomahawk::source_ptr& source );
|
||||||
|
@@ -30,7 +30,14 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<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>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
@@ -49,7 +56,7 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="">
|
<widget class="QWidget" name="layoutWidget">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="HeaderLabel" name="label_3">
|
<widget class="HeaderLabel" name="label_3">
|
||||||
@@ -80,16 +87,16 @@
|
|||||||
<extends>QLabel</extends>
|
<extends>QLabel</extends>
|
||||||
<header location="global">widgets/HeaderLabel.h</header>
|
<header location="global">widgets/HeaderLabel.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
<customwidget>
|
|
||||||
<class>PlaylistView</class>
|
|
||||||
<extends>QTreeView</extends>
|
|
||||||
<header>playlist/playlistview.h</header>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>AlbumView</class>
|
<class>AlbumView</class>
|
||||||
<extends>QListView</extends>
|
<extends>QListView</extends>
|
||||||
<header>playlist/albumview.h</header>
|
<header>playlist/albumview.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>PlaylistView</class>
|
||||||
|
<extends>QTreeView</extends>
|
||||||
|
<header>playlist/playlistview.h</header>
|
||||||
|
</customwidget>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>PlaylistWidget</class>
|
<class>PlaylistWidget</class>
|
||||||
<extends>QListWidget</extends>
|
<extends>QListWidget</extends>
|
||||||
|
@@ -82,7 +82,7 @@ DirLister::scanDir( QDir dir, int depth, DirLister::Mode mode )
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tDebug( LOGVERBOSE ) << "DirLister::scanDir scanning: " << dir.canonicalPath() << " with mode " << mode;
|
tDebug( LOGVERBOSE ) << "DirLister::scanDir scanning:" << dir.canonicalPath() << "with mode" << mode;
|
||||||
if( !dir.exists() )
|
if( !dir.exists() )
|
||||||
{
|
{
|
||||||
tDebug( LOGVERBOSE ) << "Dir no longer exists, not scanning";
|
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) );
|
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() )
|
if ( !m_dirLister.isNull() )
|
||||||
{
|
{
|
||||||
m_dirListerThreadController->quit();;
|
m_dirListerThreadController->quit();;
|
||||||
|
@@ -183,7 +183,7 @@ QtScriptResolver::init()
|
|||||||
}
|
}
|
||||||
const QByteArray scriptContents = scriptFile.readAll();
|
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
|
// add c++ part of tomahawk javascript library
|
||||||
m_engine->mainFrame()->addToJavaScriptWindowObject( "Tomahawk", m_resolverHelper );
|
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 );
|
m_enabledResolvers.append( resolver );
|
||||||
|
|
||||||
TomahawkApp::instance()->enableScriptResolver( 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 ) {
|
} else if( state == Qt::Unchecked ) {
|
||||||
m_enabledResolvers.removeAll( resolver );
|
m_enabledResolvers.removeAll( resolver );
|
||||||
|
|
||||||
|
@@ -51,6 +51,7 @@
|
|||||||
|
|
||||||
#include "ui_proxydialog.h"
|
#include "ui_proxydialog.h"
|
||||||
#include "ui_stackedsettingsdialog.h"
|
#include "ui_stackedsettingsdialog.h"
|
||||||
|
#include <playlist/dynamic/widgets/LoadingSpinner.h>
|
||||||
|
|
||||||
static QString
|
static QString
|
||||||
md5( const QByteArray& src )
|
md5( const QByteArray& src )
|
||||||
@@ -66,6 +67,7 @@ SettingsDialog::SettingsDialog( QWidget *parent )
|
|||||||
, m_rejected( false )
|
, m_rejected( false )
|
||||||
, m_sipModel( 0 )
|
, m_sipModel( 0 )
|
||||||
, m_resolversModel( 0 )
|
, m_resolversModel( 0 )
|
||||||
|
, m_sipSpinner( 0 )
|
||||||
{
|
{
|
||||||
ui->setupUi( this );
|
ui->setupUi( this );
|
||||||
TomahawkSettings* s = TomahawkSettings::instance();
|
TomahawkSettings* s = TomahawkSettings::instance();
|
||||||
@@ -107,6 +109,16 @@ SettingsDialog::SettingsDialog( QWidget *parent )
|
|||||||
m_sipModel = new SipModel( this );
|
m_sipModel = new SipModel( this );
|
||||||
ui->accountsView->setModel( m_sipModel );
|
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();
|
setupSipButtons();
|
||||||
|
|
||||||
ui->staticHostName->setText( s->externalHostname() );
|
ui->staticHostName->setText( s->externalHostname() );
|
||||||
@@ -228,6 +240,13 @@ SettingsDialog::~SettingsDialog()
|
|||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SettingsDialog::serventReady()
|
||||||
|
{
|
||||||
|
m_sipSpinner->fadeOut();
|
||||||
|
ui->addSipButton->setEnabled( true );
|
||||||
|
ui->removeSipButton->setEnabled( true );
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
SettingsDialog::createIcons()
|
SettingsDialog::createIcons()
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QModelIndex>
|
#include <QModelIndex>
|
||||||
|
|
||||||
|
class LoadingSpinner;
|
||||||
class QListWidgetItem;
|
class QListWidgetItem;
|
||||||
class Ui_StackedSettingsDialog;
|
class Ui_StackedSettingsDialog;
|
||||||
class SipPluginFactory;
|
class SipPluginFactory;
|
||||||
@@ -100,6 +101,7 @@ private slots:
|
|||||||
void sipCreateConfigClosed( int value );
|
void sipCreateConfigClosed( int value );
|
||||||
|
|
||||||
void changePage( QListWidgetItem*, QListWidgetItem* );
|
void changePage( QListWidgetItem*, QListWidgetItem* );
|
||||||
|
void serventReady();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createIcons();
|
void createIcons();
|
||||||
@@ -112,6 +114,7 @@ private:
|
|||||||
bool m_rejected;
|
bool m_rejected;
|
||||||
SipModel* m_sipModel;
|
SipModel* m_sipModel;
|
||||||
ResolversModel* m_resolversModel;
|
ResolversModel* m_resolversModel;
|
||||||
|
LoadingSpinner* m_sipSpinner;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SETTINGSDIALOG_H
|
#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 "settingslistdelegate.h"
|
||||||
#include "utils/logger.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
|
#ifndef SETTINGSLISTDELEGATE_H
|
||||||
#define SETTINGSLISTDELEGATE_H
|
#define SETTINGSLISTDELEGATE_H
|
||||||
|
|
||||||
|
@@ -28,7 +28,7 @@
|
|||||||
#include "widgets/playlisttypeselectordlg.h"
|
#include "widgets/playlisttypeselectordlg.h"
|
||||||
#include <playlist/dynamic/GeneratorInterface.h>
|
#include <playlist/dynamic/GeneratorInterface.h>
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include <globalactionmanager.h>
|
#include "dropjob.h"
|
||||||
|
|
||||||
using namespace Tomahawk;
|
using namespace Tomahawk;
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ CategoryAddItem::icon() const
|
|||||||
bool
|
bool
|
||||||
CategoryAddItem::willAcceptDrag( const QMimeData* data ) const
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -133,9 +133,96 @@ CategoryAddItem::willAcceptDrag( const QMimeData* data ) const
|
|||||||
bool
|
bool
|
||||||
CategoryAddItem::dropMimeData( const QMimeData* data, Qt::DropAction )
|
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
|
// Create a new playlist seeded with these items
|
||||||
connect( GlobalActionManager::instance(), SIGNAL( tracks( QList< Tomahawk::query_ptr > ) ), this, SLOT( parsedDroppedTracks( QList< Tomahawk::query_ptr > ) ) );
|
DropJob *dj = new DropJob();
|
||||||
GlobalActionManager::instance()->tracksFromMimeData( data );
|
connect( dj, SIGNAL( tracks( QList< Tomahawk::query_ptr > ) ), this, SLOT( parsedDroppedTracks( QList< Tomahawk::query_ptr > ) ) );
|
||||||
|
dj->tracksFromMimeData( data );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -143,7 +230,6 @@ CategoryAddItem::dropMimeData( const QMimeData* data, Qt::DropAction )
|
|||||||
void
|
void
|
||||||
CategoryAddItem::parsedDroppedTracks( const QList< query_ptr >& tracks )
|
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 ) {
|
if( m_categoryType == SourcesModel::PlaylistsCategory ) {
|
||||||
|
|
||||||
playlist_ptr newpl = Playlist::create( SourceList::instance()->getLocal(), uuid(), "New Playlist", "", SourceList::instance()->getLocal()->friendlyName(), false, tracks );
|
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
|
int
|
||||||
CollectionItem::peerSortValue() const
|
CollectionItem::IDValue() const
|
||||||
{
|
{
|
||||||
if( m_source.isNull() )
|
if( m_source.isNull() )
|
||||||
return -1;
|
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
|
void
|
||||||
CollectionItem::activate()
|
CollectionItem::activate()
|
||||||
{
|
{
|
||||||
|
@@ -37,6 +37,7 @@ public:
|
|||||||
virtual void activate();
|
virtual void activate();
|
||||||
virtual QIcon icon() const;
|
virtual QIcon icon() const;
|
||||||
virtual int peerSortValue() const;
|
virtual int peerSortValue() const;
|
||||||
|
virtual int IDValue() const;
|
||||||
|
|
||||||
Tomahawk::source_ptr source() const;
|
Tomahawk::source_ptr source() const;
|
||||||
|
|
||||||
|
@@ -28,7 +28,7 @@
|
|||||||
#include "collectionitem.h"
|
#include "collectionitem.h"
|
||||||
#include "utils/tomahawkutils.h"
|
#include "utils/tomahawkutils.h"
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include "globalactionmanager.h"
|
#include "dropjob.h"
|
||||||
|
|
||||||
using namespace Tomahawk;
|
using namespace Tomahawk;
|
||||||
|
|
||||||
@@ -81,6 +81,14 @@ PlaylistItem::onPlaylistChanged()
|
|||||||
|
|
||||||
int
|
int
|
||||||
PlaylistItem::peerSortValue() const
|
PlaylistItem::peerSortValue() const
|
||||||
|
{
|
||||||
|
// return m_playlist->createdOn();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
PlaylistItem::IDValue() const
|
||||||
{
|
{
|
||||||
return m_playlist->createdOn();
|
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() )
|
data->data( "application/tomahawk.playlist.id" ) == m_playlist->guid() )
|
||||||
return false; // don't allow dropping on ourselves
|
return false; // don't allow dropping on ourselves
|
||||||
|
|
||||||
connect( GlobalActionManager::instance(), SIGNAL( tracks( QList< Tomahawk::query_ptr > ) ), this, SLOT( parsedDroppedTracks( QList< Tomahawk::query_ptr > ) ) );
|
DropJob *dj = new DropJob();
|
||||||
GlobalActionManager::instance()->tracksFromMimeData( data );
|
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...
|
// TODO cant' know if it works or not yet...
|
||||||
return true;
|
return true;
|
||||||
@@ -152,7 +161,6 @@ PlaylistItem::dropMimeData( const QMimeData* data, Qt::DropAction action )
|
|||||||
void
|
void
|
||||||
PlaylistItem::parsedDroppedTracks( const QList< query_ptr >& tracks)
|
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() )
|
if ( tracks.count() && !m_playlist.isNull() && m_playlist->author()->isLocal() )
|
||||||
{
|
{
|
||||||
qDebug() << "on playlist:" << m_playlist->title() << m_playlist->guid() << m_playlist->currentrevision();
|
qDebug() << "on playlist:" << m_playlist->title() << m_playlist->guid() << m_playlist->currentrevision();
|
||||||
@@ -237,6 +245,14 @@ DynamicPlaylistItem::onDynamicPlaylistLoaded( DynamicPlaylistRevision revision )
|
|||||||
|
|
||||||
int
|
int
|
||||||
DynamicPlaylistItem::peerSortValue() const
|
DynamicPlaylistItem::peerSortValue() const
|
||||||
|
{
|
||||||
|
// return m_dynplaylist->createdOn();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
DynamicPlaylistItem::IDValue() const
|
||||||
{
|
{
|
||||||
return m_dynplaylist->createdOn();
|
return m_dynplaylist->createdOn();
|
||||||
}
|
}
|
||||||
|
@@ -38,6 +38,7 @@ public:
|
|||||||
virtual QIcon icon() const;
|
virtual QIcon icon() const;
|
||||||
virtual bool setData(const QVariant& v, bool role);
|
virtual bool setData(const QVariant& v, bool role);
|
||||||
virtual int peerSortValue() const;
|
virtual int peerSortValue() const;
|
||||||
|
virtual int IDValue() const;
|
||||||
|
|
||||||
virtual bool activateCurrent();
|
virtual bool activateCurrent();
|
||||||
|
|
||||||
@@ -67,6 +68,7 @@ public:
|
|||||||
virtual bool willAcceptDrag( const QMimeData* data ) const;
|
virtual bool willAcceptDrag( const QMimeData* data ) const;
|
||||||
virtual void activate();
|
virtual void activate();
|
||||||
virtual int peerSortValue() const;
|
virtual int peerSortValue() const;
|
||||||
|
virtual int IDValue() const;
|
||||||
virtual QIcon icon() const;
|
virtual QIcon icon() const;
|
||||||
|
|
||||||
virtual bool activateCurrent();
|
virtual bool activateCurrent();
|
||||||
|
@@ -55,6 +55,7 @@ public:
|
|||||||
virtual bool dropMimeData( const QMimeData*, Qt::DropAction ) { return false; }
|
virtual bool dropMimeData( const QMimeData*, Qt::DropAction ) { return false; }
|
||||||
virtual bool setData( const QVariant&, bool ) { 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 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
|
/// 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 ); }
|
void beginRowsAdded( int from, int to ) { emit beginChildRowsAdded( from, to ); }
|
||||||
|
@@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
#include "globalactionmanager.h"
|
#include "globalactionmanager.h"
|
||||||
|
#include "dropjob.h"
|
||||||
#include "items/playlistitems.h"
|
#include "items/playlistitems.h"
|
||||||
|
|
||||||
using namespace Tomahawk;
|
using namespace Tomahawk;
|
||||||
@@ -105,6 +106,8 @@ SourcesModel::data( const QModelIndex& index, int role ) const
|
|||||||
return itemFromIndex( index )->icon();
|
return itemFromIndex( index )->icon();
|
||||||
case SourcesModel::SortRole:
|
case SourcesModel::SortRole:
|
||||||
return itemFromIndex( index )->peerSortValue();
|
return itemFromIndex( index )->peerSortValue();
|
||||||
|
case SourcesModel::IDRole:
|
||||||
|
return itemFromIndex( index )->IDValue();
|
||||||
}
|
}
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
@@ -175,7 +178,7 @@ SourcesModel::setData( const QModelIndex& index, const QVariant& value, int role
|
|||||||
QStringList
|
QStringList
|
||||||
SourcesModel::mimeTypes() const
|
SourcesModel::mimeTypes() const
|
||||||
{
|
{
|
||||||
return GlobalActionManager::instance()->mimeTypes();
|
return DropJob::mimeTypes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -61,7 +61,8 @@ public:
|
|||||||
enum Roles {
|
enum Roles {
|
||||||
SourceTreeItemRole = Qt::UserRole + 10,
|
SourceTreeItemRole = Qt::UserRole + 10,
|
||||||
SourceTreeItemTypeRole = Qt::UserRole + 11,
|
SourceTreeItemTypeRole = Qt::UserRole + 11,
|
||||||
SortRole = Qt::UserRole + 12
|
SortRole = Qt::UserRole + 12,
|
||||||
|
IDRole = Qt::UserRole + 13
|
||||||
};
|
};
|
||||||
|
|
||||||
SourcesModel( QObject* parent = 0 );
|
SourcesModel( QObject* parent = 0 );
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <QTreeView>
|
#include <QTreeView>
|
||||||
|
|
||||||
|
#include "sourcelist.h"
|
||||||
#include "sourcesmodel.h"
|
#include "sourcesmodel.h"
|
||||||
#include "sourcetree/items/collectionitem.h"
|
#include "sourcetree/items/collectionitem.h"
|
||||||
|
|
||||||
@@ -36,7 +37,6 @@ SourcesProxyModel::SourcesProxyModel( SourcesModel* model, QObject* parent )
|
|||||||
|
|
||||||
setSourceModel( model );
|
setSourceModel( model );
|
||||||
|
|
||||||
|
|
||||||
if ( model && model->metaObject()->indexOfSignal( "expandRequest(QModelIndex)" ) > -1 )
|
if ( model && model->metaObject()->indexOfSignal( "expandRequest(QModelIndex)" ) > -1 )
|
||||||
connect( model, SIGNAL( expandRequest( QModelIndex ) ), this, SLOT( expandRequested( QModelIndex ) ) );
|
connect( model, SIGNAL( expandRequest( QModelIndex ) ), this, SLOT( expandRequested( QModelIndex ) ) );
|
||||||
if ( model && model->metaObject()->indexOfSignal( "selectRequest(QModelIndex)" ) > -1 )
|
if ( model && model->metaObject()->indexOfSignal( "selectRequest(QModelIndex)" ) > -1 )
|
||||||
@@ -51,13 +51,13 @@ SourcesProxyModel::showOfflineSources( bool offlineSourcesShown )
|
|||||||
invalidateFilter();
|
invalidateFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SourcesProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const
|
SourcesProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const
|
||||||
{
|
{
|
||||||
if ( !m_filtered )
|
if ( !m_filtered )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
||||||
CollectionItem* sti = qobject_cast< CollectionItem* >( m_model->data( sourceModel()->index( sourceRow, 0, sourceParent ), SourcesModel::SourceTreeItemRole ).value< SourceTreeItem* >() );
|
CollectionItem* sti = qobject_cast< CollectionItem* >( m_model->data( sourceModel()->index( sourceRow, 0, sourceParent ), SourcesModel::SourceTreeItemRole ).value< SourceTreeItem* >() );
|
||||||
if ( sti )
|
if ( sti )
|
||||||
{
|
{
|
||||||
@@ -70,6 +70,7 @@ SourcesProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourcePar
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SourcesProxyModel::selectRequested( const QModelIndex& idx )
|
SourcesProxyModel::selectRequested( const QModelIndex& idx )
|
||||||
{
|
{
|
||||||
@@ -77,6 +78,7 @@ SourcesProxyModel::selectRequested( const QModelIndex& idx )
|
|||||||
emit selectRequest( mapFromSource( idx ) );
|
emit selectRequest( mapFromSource( idx ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SourcesProxyModel::expandRequested( const QModelIndex& idx )
|
SourcesProxyModel::expandRequested( const QModelIndex& idx )
|
||||||
{
|
{
|
||||||
@@ -84,3 +86,18 @@ SourcesProxyModel::expandRequested( const QModelIndex& idx )
|
|||||||
emit expandRequest( mapFromSource( 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:
|
protected:
|
||||||
bool filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const;
|
bool filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const;
|
||||||
|
bool lessThan( const QModelIndex& left, const QModelIndex& right ) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SourcesModel* m_model;
|
SourcesModel* m_model;
|
||||||
|
@@ -37,7 +37,8 @@
|
|||||||
#include "audio/audioengine.h"
|
#include "audio/audioengine.h"
|
||||||
#include "sourceplaylistinterface.h"
|
#include "sourceplaylistinterface.h"
|
||||||
#include "tomahawksettings.h"
|
#include "tomahawksettings.h"
|
||||||
#include <globalactionmanager.h>
|
#include "globalactionmanager.h"
|
||||||
|
#include "dropjob.h"
|
||||||
|
|
||||||
#include "utils/logger.h"
|
#include "utils/logger.h"
|
||||||
|
|
||||||
@@ -439,7 +440,7 @@ SourceTreeView::dragEnterEvent( QDragEnterEvent* event )
|
|||||||
qDebug() << Q_FUNC_INFO;
|
qDebug() << Q_FUNC_INFO;
|
||||||
QTreeView::dragEnterEvent( event );
|
QTreeView::dragEnterEvent( event );
|
||||||
|
|
||||||
if ( GlobalActionManager::instance()->acceptsMimeData( event->mimeData() ) )
|
if ( DropJob::acceptsMimeData( event->mimeData() ) )
|
||||||
{
|
{
|
||||||
m_dragging = true;
|
m_dragging = true;
|
||||||
m_dropRect = QRect();
|
m_dropRect = QRect();
|
||||||
@@ -470,7 +471,7 @@ SourceTreeView::dragMoveEvent( QDragMoveEvent* event )
|
|||||||
bool accept = false;
|
bool accept = false;
|
||||||
QTreeView::dragMoveEvent( event );
|
QTreeView::dragMoveEvent( event );
|
||||||
|
|
||||||
if ( GlobalActionManager::instance()->acceptsMimeData( event->mimeData() ) )
|
if ( DropJob::acceptsMimeData( event->mimeData() ) )
|
||||||
{
|
{
|
||||||
setDirtyRegion( m_dropRect );
|
setDirtyRegion( m_dropRect );
|
||||||
const QPoint pos = event->pos();
|
const QPoint pos = event->pos();
|
||||||
|
Reference in New Issue
Block a user