mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-09-06 12:10:47 +02:00
Compare commits
190 Commits
vlc-meta-r
...
stable-0.5
Author | SHA1 | Date | |
---|---|---|---|
|
ce76c86171 | ||
|
64d9a0f5d2 | ||
|
aa0f99bcce | ||
|
5be032f39c | ||
|
272add3c3b | ||
|
39e7314acf | ||
|
90e238a352 | ||
|
20b62bfba3 | ||
|
6fa2ad19ee | ||
|
60f2e85965 | ||
|
cbd9d4e0ce | ||
|
22a1f167b0 | ||
|
44a5406a34 | ||
|
611ca21ec6 | ||
|
64274d6d39 | ||
|
34dc6d23ee | ||
|
70a5050443 | ||
|
2a19f20914 | ||
|
33ca71a86a | ||
|
485447be38 | ||
|
4f2cbb32c5 | ||
|
edc6057354 | ||
|
7beab3aea8 | ||
|
3e3e76b66f | ||
|
c33d3c2a67 | ||
|
56e997a159 | ||
|
67d75543e6 | ||
|
e19423e08f | ||
|
e041ce87fc | ||
|
6eacdf808e | ||
|
b6d5c86952 | ||
|
b7fb9a03bf | ||
|
37fad49393 | ||
|
fa83fde05e | ||
|
b3b34cacbd | ||
|
d0f697cd4b | ||
|
c144a0142f | ||
|
318866d37a | ||
|
70e93faa3f | ||
|
89e21289a6 | ||
|
fe0d2d87fc | ||
|
8531ca2234 | ||
|
8d5082fe2c | ||
|
7672c7caec | ||
|
bf2139824d | ||
|
eb749b1e44 | ||
|
53226f37c2 | ||
|
20032a40b2 | ||
|
a6d1bbb91e | ||
|
f7240a5d39 | ||
|
2142a04fda | ||
|
0406b38f1c | ||
|
8e2174baf1 | ||
|
7caeaddc21 | ||
|
f4a01ec6aa | ||
|
ed81799294 | ||
|
0283d534f0 | ||
|
4a00ff4d24 | ||
|
b98c535247 | ||
|
fbcffed27b | ||
|
e521150d33 | ||
|
2a0aa602b6 | ||
|
cf37aae430 | ||
|
292f395c47 | ||
|
047f3cc2d4 | ||
|
97681ace31 | ||
|
6be5257bc0 | ||
|
8cfbe1f38b | ||
|
8db8e42ec4 | ||
|
9492055fc6 | ||
|
3dc624858b | ||
|
f154c2bbcd | ||
|
e9127ae3ec | ||
|
c7d9d8e5b7 | ||
|
e525291213 | ||
|
44269ee8f6 | ||
|
53c4a2d675 | ||
|
ebfc53e009 | ||
|
190845a86e | ||
|
25af4f4275 | ||
|
bca64a70ed | ||
|
10462ee257 | ||
|
ba4532593b | ||
|
c84fd28dd2 | ||
|
dbbb491a81 | ||
|
bab5e27673 | ||
|
17f71bd366 | ||
|
e96bbc11e1 | ||
|
d492ba0317 | ||
|
b6466a6027 | ||
|
6b5d391cde | ||
|
0680dec5df | ||
|
a4e8f4216c | ||
|
355c95e068 | ||
|
da07361ec0 | ||
|
aafe8797ad | ||
|
95343ca024 | ||
|
f85bcc1c64 | ||
|
e53e51aefc | ||
|
d22b33bc50 | ||
|
c36414bb4c | ||
|
a78349f9f1 | ||
|
fa41b96260 | ||
|
7f2bf85663 | ||
|
85fe824df3 | ||
|
c37bbb4deb | ||
|
1a9bf84ab4 | ||
|
a283ea1ed0 | ||
|
d27dd0785a | ||
|
5e1f808d28 | ||
|
aba78c7a24 | ||
|
f45e92a24d | ||
|
5ae04043d4 | ||
|
5f521a6cf5 | ||
|
a4b30dcecd | ||
|
700394a054 | ||
|
819ee17b74 | ||
|
79c55f1699 | ||
|
f42696de23 | ||
|
adfaf5ce53 | ||
|
32aca98a97 | ||
|
294809debb | ||
|
e4593079f3 | ||
|
cfa4210854 | ||
|
91084885fb | ||
|
0b7f420bef | ||
|
046237f009 | ||
|
85d9755a47 | ||
|
98bd7b1857 | ||
|
37510fc2d7 | ||
|
a91ad7dd5f | ||
|
2cc85c8f4f | ||
|
19625fffd4 | ||
|
a98cab55b7 | ||
|
ec7b98e589 | ||
|
1262dcb60a | ||
|
fc9c6e6017 | ||
|
fa4463dc88 | ||
|
3fb403c695 | ||
|
fdb1d1b621 | ||
|
127da50144 | ||
|
5640923d51 | ||
|
4a2ef91638 | ||
|
012556ca0a | ||
|
8d0a51cc64 | ||
|
253120a35c | ||
|
671bd5361b | ||
|
3dc969a31f | ||
|
64a70f5073 | ||
|
1911d4b8a0 | ||
|
92229ce3e2 | ||
|
7df3f867ea | ||
|
6e66c4a192 | ||
|
49fe0f945e | ||
|
0d915513b9 | ||
|
6c69edd0e7 | ||
|
23c2c77869 | ||
|
cd7c64ac0a | ||
|
0637ee7338 | ||
|
7765aa116b | ||
|
c46ed53930 | ||
|
22105d448a | ||
|
4f4efdfbab | ||
|
686730e27c | ||
|
fdfe4d12d4 | ||
|
669e7550f2 | ||
|
d4a2294963 | ||
|
66b0ecc846 | ||
|
c3563a2449 | ||
|
05efe29a67 | ||
|
3480690479 | ||
|
a1fb66e024 | ||
|
02e9f99ce4 | ||
|
95c74fe370 | ||
|
358226bdb1 | ||
|
a2d81d0099 | ||
|
292e97fcee | ||
|
6dafcf3c80 | ||
|
ee1b13aee6 | ||
|
ce8eecd40f | ||
|
f674b3b751 | ||
|
44cd64a8b6 | ||
|
a9418fc8aa | ||
|
44546763b9 | ||
|
66a74ad6e2 | ||
|
6aae2dd96f | ||
|
ffd2cee2ff | ||
|
438f8444c3 | ||
|
b55be311b4 | ||
|
7a4d113af6 |
@@ -13,7 +13,7 @@ SET( TOMAHAWK_DESCRIPTION_SUMMARY "The social media player" )
|
||||
|
||||
SET( TOMAHAWK_VERSION_MAJOR 0 )
|
||||
SET( TOMAHAWK_VERSION_MINOR 5 )
|
||||
SET( TOMAHAWK_VERSION_PATCH 0 )
|
||||
SET( TOMAHAWK_VERSION_PATCH 5 )
|
||||
|
||||
#SET( TOMAHAWK_VERSION_RC 0 )
|
||||
|
||||
@@ -35,8 +35,11 @@ IF( CMAKE_SYSTEM_PROCESSOR MATCHES "arm" )
|
||||
ENDIF()
|
||||
|
||||
# add definitions based on build options
|
||||
IF(WITH_BREAKPAD)
|
||||
IF( WITH_BREAKPAD )
|
||||
message(STATUS "Build with support for breakpad.")
|
||||
IF( CMAKE_COMPILER_IS_GNUCXX )
|
||||
ADD_DEFINITIONS( -DSTDC_HEADERS -std=gnu++98 )
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# generate version string
|
||||
@@ -101,8 +104,8 @@ if(PHONON_FOUND)
|
||||
message(STATUS "Phonon found; ensure that phonon-vlc is at least 0.4")
|
||||
endif()
|
||||
|
||||
macro_optional_find_package(LibEchonest 1.2.1)
|
||||
macro_log_feature(LIBECHONEST_FOUND "Echonest" "Qt library for communicating with The Echo Nest" "http://projects.kde.org/libechonest" TRUE "" "libechonest 1.2.1 is needed for dynamic playlists and the infosystem")
|
||||
macro_optional_find_package(Echonest 2.0.0)
|
||||
macro_log_feature(ECHONEST_FOUND "Echonest" "Qt library for communicating with The Echo Nest" "http://projects.kde.org/libechonest" TRUE "" "libechonest 2.0.0 is needed for dynamic playlists and the infosystem")
|
||||
|
||||
macro_optional_find_package(CLucene 0.9.23)
|
||||
macro_log_feature(CLucene_FOUND "CLucene" "The open-source, C++ search engine" "http://clucene.sf.net" TRUE "" "CLucene is used for indexing the collection")
|
||||
@@ -157,8 +160,8 @@ SET( LIBPORTFWD_LIBRARIES ${LIBPORTFWD_LIBRARY} )
|
||||
ADD_SUBDIRECTORY( ${THIRDPARTY_DIR}/libportfwd )
|
||||
|
||||
# we need pthreads too
|
||||
#macro_optional_find_package(Threads)
|
||||
#macro_log_feature(THREADS_FOUND "Threads" "Threading Library" "" TRUE "" "Platform specific library for threading")
|
||||
macro_optional_find_package(Threads)
|
||||
macro_log_feature(THREADS_FOUND "Threads" "Threading Library" "" TRUE "" "Platform specific library for threading")
|
||||
|
||||
macro_optional_find_package(KDE4)
|
||||
macro_optional_find_package(KDE4Installed)
|
||||
|
36
CMakeModules/FindEchonest.cmake
Normal file
36
CMakeModules/FindEchonest.cmake
Normal file
@@ -0,0 +1,36 @@
|
||||
# - Find libechonest
|
||||
# Find the libechonest includes and the libechonest libraries
|
||||
# This module defines
|
||||
# ECHONEST_INCLUDE_DIR, root echonest include dir. Include echonest includes with echonest/foo.h
|
||||
# ECHONEST_LIBRARIES, the path to libechonest
|
||||
# ECHONEST_FOUND, whether libechonest was found
|
||||
|
||||
FIND_PACKAGE(PkgConfig QUIET)
|
||||
PKG_CHECK_MODULES(PC_ECHONEST QUIET libechonest)
|
||||
|
||||
FIND_PATH(ECHONEST_INCLUDE_DIR NAMES echonest/Track.h
|
||||
HINTS
|
||||
${PC_ECHONEST_INCLUDEDIR}
|
||||
${PC_ECHONEST_INCLUDE_DIRS}
|
||||
${CMAKE_INSTALL_INCLUDEDIR}
|
||||
${KDE4_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
FIND_LIBRARY(ECHONEST_LIBRARIES NAMES echonest
|
||||
HINTS
|
||||
${PC_ECHONEST_LIBDIR}
|
||||
${PC_ECHONEST_LIBRARY_DIRS}
|
||||
${CMAKE_INSTALL_LIBDIR}
|
||||
${KDE4_LIB_DIR}
|
||||
)
|
||||
|
||||
IF(ECHONEST_LIBRARIES AND ECHONEST_INCLUDE_DIR AND NOT PC_ECHONEST_VERSION)
|
||||
MESSAGE(WARNING "You don't have pkg-config and so the libechonest version check does not work!")
|
||||
ENDIF()
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Echonest
|
||||
REQUIRED_VARS ECHONEST_LIBRARIES ECHONEST_INCLUDE_DIR
|
||||
VERSION_VAR PC_ECHONEST_VERSION)
|
||||
|
||||
MARK_AS_ADVANCED(ECHONEST_INCLUDE_DIR ECHONEST_LIBRARIES)
|
@@ -1,42 +0,0 @@
|
||||
# - Find libechonest
|
||||
# Find the libechonest includes and the libechonest libraries
|
||||
# This module defines
|
||||
# LIBECHONEST_INCLUDE_DIR, root echonest include dir. Include echonest includes with echonest/foo.h
|
||||
# LIBECHONEST_LIBRARY, the path to libechonest
|
||||
# LIBECHONEST_FOUND, whether libechonest was found
|
||||
|
||||
|
||||
find_path(LIBECHONEST_INCLUDE_DIR NAMES echonest_export.h
|
||||
HINTS
|
||||
~/usr/include
|
||||
/opt/local/include
|
||||
/usr/include
|
||||
/usr/local/include
|
||||
/opt/kde4/include
|
||||
${KDE4_INCLUDE_DIR}
|
||||
PATH_SUFFIXES echonest
|
||||
)
|
||||
|
||||
find_library( LIBECHONEST_LIBRARY NAMES echonest
|
||||
PATHS
|
||||
~/usr/lib
|
||||
/opt/local/lib
|
||||
/usr/lib
|
||||
/usr/lib64
|
||||
/usr/local/lib
|
||||
/opt/kde4/lib
|
||||
${KDE4_LIB_DIR}
|
||||
)
|
||||
|
||||
|
||||
if(LIBECHONEST_INCLUDE_DIR AND LIBECHONEST_LIBRARY)
|
||||
set(LIBECHONEST_FOUND TRUE)
|
||||
message(STATUS "Found libechonest: ${LIBECHONEST_INCLUDE_DIR}, ${LIBECHONEST_LIBRARY}")
|
||||
else(LIBECHONEST_INCLUDE_DIR AND LIBECHONEST_LIBRARY)
|
||||
set(LIBECHONEST_FOUND FALSE)
|
||||
if (LIBECHONEST_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could NOT find required package libechonest")
|
||||
endif(LIBECHONEST_FIND_REQUIRED)
|
||||
endif(LIBECHONEST_INCLUDE_DIR AND LIBECHONEST_LIBRARY)
|
||||
|
||||
mark_as_advanced(LIBECHONEST_INCLUDE_DIR LIBECHONEST_LIBRARY)
|
45
ChangeLog
45
ChangeLog
@@ -1,3 +1,40 @@
|
||||
Version 0.5.5:
|
||||
* Changed the Spotify config dialog to indicate when the user
|
||||
is logged in.
|
||||
* Fixed bug where the wrong avatar could be shown for a user.
|
||||
* Fixed shortcuts not working in the global search field on OS X.
|
||||
* Fixed The Echo Nest stations.
|
||||
* Code-signed executable on OS X for GateKeeper.
|
||||
* Fixed logging in to Spotify when pressing return in the config dialog.
|
||||
* Fixed queue not auto-collapsing when playing the last track.
|
||||
* Fixed bug where album listings would fail to show up.
|
||||
* Improved stability.
|
||||
* Fixed bug where it was not possible to drop a mixture of resolved
|
||||
and unresolved tracks onto a playlist.
|
||||
|
||||
Version 0.5.4:
|
||||
* Improved stability.
|
||||
* Added support for Spotify album lookups.
|
||||
* Fixed not always updating the database index after scanning.
|
||||
* Fixed connection issue between Tomahawk peers.
|
||||
|
||||
Version 0.5.3:
|
||||
* Fixed broken artist names when importing Last.fm playback history.
|
||||
* Fixed crash when filtering collections.
|
||||
|
||||
Version 0.5.2:
|
||||
* Fixed a crash when invalid results are coming back from a resolver or
|
||||
are found in a playlist.
|
||||
|
||||
Version 0.5.1:
|
||||
* Fixed a few issues with automatic downloading and launching
|
||||
of the Spotify account.
|
||||
* Show an error message when not able to resolve a requested song.
|
||||
* Fixed a few crash and freeze issues.
|
||||
* Better detection of local networks for the Local Network connector.
|
||||
* Don't prompt for access permission for your own accounts.
|
||||
* (OS X) Fixed not being able to connect to Last.fm.
|
||||
|
||||
Version 0.5.0:
|
||||
* SOCKS5 proxy support improvements for resolvers and more.
|
||||
* Initial Access Control support, allowing users to define who is able to
|
||||
@@ -52,7 +89,7 @@ Version 0.4.0:
|
||||
* Fixed bug where filter text would be one step behind filter value.
|
||||
* Fixed bug where resolvers would enable themselves after auto-updating.
|
||||
* Fixed occasional crash when dropping tracks onto New Station item.
|
||||
* Added jump-to-current-track support for search results page.
|
||||
* Added jump-to-current-track support for search results page.
|
||||
* Fixed non-resolving tracks when dragging from album view.
|
||||
* Fixed fetching album covers for albums with special characters.
|
||||
* Show errors and continue gracefully when resolved audio is not available.
|
||||
@@ -77,7 +114,7 @@ Version 0.4.0:
|
||||
* Fixed out of sync Show/Hide menu items on OS X when hidden with cmd-h.
|
||||
* Fixed /Volumes directory not showing up on OS X.
|
||||
* Fixed startup crash on OS X.
|
||||
|
||||
|
||||
Version 0.3.3:
|
||||
* Automatically load Super Collection tracks when no official release
|
||||
information is available.
|
||||
@@ -89,7 +126,7 @@ Version 0.3.3:
|
||||
* Fixed dupe menu entry appearing on OS X.
|
||||
* Fixed invisible sidebar items on Linux.
|
||||
|
||||
Version 0.3.2:
|
||||
Version 0.3.2:
|
||||
* Improved syncing process, it's faster and more reliable now.
|
||||
* Fixed UPnP issues.
|
||||
* Fixed not updating collections and views after a collection changes.
|
||||
@@ -143,7 +180,7 @@ Version 0.3.0:
|
||||
* Added YouTube resolver.
|
||||
* Fixed bug where going offline then online would not re-connect to many
|
||||
peers.
|
||||
* Added support for auto-updating live XSPF playlists.
|
||||
* Added support for auto-updating live XSPF playlists.
|
||||
* Don't show an age of 41 years for tracks that have no age information.
|
||||
* Show config UI for resolvers that have them as soon as you add them.
|
||||
* Add support for Echo Nest Personal Catalogs and User Radio. Synchronize
|
||||
|
2
README
2
README
@@ -34,7 +34,7 @@ Dependencies
|
||||
TagLib 1.6.2 - http://developer.kde.org/~wheeler/taglib.html
|
||||
Boost 1.3 - http://www.boost.org/
|
||||
CLucene 0.9.23 (0.9.21 will fail) - http://clucene.sourceforge.net/download.shtml
|
||||
libechonest 1.2.1 - http://projects.kde.org/projects/playground/libs/libechonest/
|
||||
libechonest 2.0.0 - http://projects.kde.org/projects/playground/libs/libechonest/
|
||||
Attica 0.4.0 - ftp://ftp.kde.org/pub/kde/stable/attica/
|
||||
QuaZip 0.4.3 - http://quazip.sourceforge.net/
|
||||
|
||||
|
@@ -45,6 +45,9 @@ VERSION=$1
|
||||
header "Creating DMG"
|
||||
cd ..
|
||||
|
||||
header "Signing bundle"
|
||||
codesign -s "Developer ID Application: Leonardo Franchi" -f -v ./Tomahawk.app
|
||||
|
||||
$ROOT/../admin/mac/create-dmg.sh Tomahawk.app
|
||||
mv Tomahawk.dmg Tomahawk-$VERSION.dmg
|
||||
|
||||
|
@@ -28,9 +28,6 @@ FRAMEWORK_SEARCH_PATH=[
|
||||
|
||||
LIBRARY_SEARCH_PATH=['/usr/local/lib', '/usr/local/Cellar/gettext/0.18.1.1/lib', '.']
|
||||
|
||||
LIBSPOTIFY_VERSION = commands.getoutput("brew ls -version libspotify | tr -s \" \" \"\\\\012\" | tail -n 1").strip()
|
||||
LIBSPOTIFY_PATH = "/usr/local/lib/libspotify.%s.dylib" % LIBSPOTIFY_VERSION
|
||||
|
||||
VLC_PLUGINS=[
|
||||
'libaccess_attachment_plugin.dylib',
|
||||
#'libaccess_avio_plugin.dylib',
|
||||
@@ -512,11 +509,6 @@ try:
|
||||
except:
|
||||
print 'Failed to find tomahawk_crash_reporter'
|
||||
|
||||
try:
|
||||
FixPlugin(LIBSPOTIFY_PATH, "../Frameworks")
|
||||
except:
|
||||
print "Failed to copy libspotify from os: %s" % LIBSPOTIFY_PATH
|
||||
|
||||
for plugin in QT_PLUGINS:
|
||||
FixPlugin(FindQtPlugin(plugin), os.path.dirname(plugin))
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -85,7 +85,7 @@ AudioControls::AudioControls( QWidget* parent )
|
||||
ui->socialButton->setPixmap( RESPATH "images/share.png" );
|
||||
ui->loveButton->setPixmap( RESPATH "images/not-loved.png" );
|
||||
ui->loveButton->setCheckable( true );
|
||||
|
||||
|
||||
ui->socialButton->setFixedSize( QSize( 20, 20 ) );
|
||||
ui->loveButton->setFixedSize( QSize( 20, 20 ) );
|
||||
|
||||
@@ -352,7 +352,7 @@ AudioControls::onPlaybackStopped()
|
||||
ui->ownerLabel->setText( "" );
|
||||
ui->timeLabel->setText( "" );
|
||||
ui->timeLeftLabel->setText( "" );
|
||||
ui->coverImage->setPixmap( QPixmap(), true );
|
||||
ui->coverImage->setPixmap( QPixmap(), false );
|
||||
ui->seekSlider->setVisible( false );
|
||||
m_sliderTimeLine.stop();
|
||||
m_sliderTimeLine.setCurrentTime( 0 );
|
||||
@@ -588,7 +588,7 @@ AudioControls::droppedTracks( QList< query_ptr > tracks )
|
||||
{
|
||||
// queue and play the first no matter what
|
||||
GlobalActionManager::instance()->handlePlayTrack( tracks.first() );
|
||||
ViewManager::instance()->queue()->model()->append( tracks );
|
||||
ViewManager::instance()->queue()->model()->appendQueries( tracks );
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -113,8 +113,7 @@ INCLUDE_DIRECTORIES(
|
||||
${PHONON_INCLUDES}
|
||||
${QJSON_INCLUDE_DIR}
|
||||
${LIBATTICA_INCLUDE_DIR}
|
||||
${LIBECHONEST_INCLUDE_DIR}
|
||||
${LIBECHONEST_INCLUDE_DIR}/..
|
||||
${ECHONEST_INCLUDE_DIR}
|
||||
${LIBLASTFM_INCLUDE_DIRS}
|
||||
${LIBLASTFM_INCLUDE_DIRS}/..
|
||||
)
|
||||
@@ -129,6 +128,8 @@ IF( UNIX )
|
||||
ENDIF( UNIX )
|
||||
|
||||
IF( APPLE )
|
||||
SET( CMAKE_LINKER_FLAGS "-headerpad_max_install_names ${CMAKE_LINKER_FLAGS}" )
|
||||
|
||||
INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/thirdparty/SPMediaKeyTap )
|
||||
|
||||
SET( tomahawkSources ${tomahawkSources} mac/TomahawkApp_Mac.mm mac/MacShortcutHandler.cpp )
|
||||
@@ -198,7 +199,7 @@ TARGET_LINK_LIBRARIES( tomahawk
|
||||
${OS_SPECIFIC_LINK_LIBRARIES}
|
||||
${QT_LIBRARIES}
|
||||
${MAC_EXTRA_LIBS}
|
||||
${LIBECHONEST_LIBRARY}
|
||||
${ECHONEST_LIBRARIES}
|
||||
${QXTWEB_LIBRARIES}
|
||||
${QJSON_LIBRARIES}
|
||||
${TAGLIB_LIBRARIES}
|
||||
|
@@ -22,10 +22,6 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "accounts/AccountManager.h"
|
||||
#include "network/Servent.h"
|
||||
#include "SourceList.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QTextEdit>
|
||||
#include <QDialogButtonBox>
|
||||
@@ -34,8 +30,13 @@
|
||||
#include <QClipboard>
|
||||
#include <QDebug>
|
||||
|
||||
#include "utils/Logger.h"
|
||||
#include "accounts/AccountManager.h"
|
||||
#include "network/Servent.h"
|
||||
#include "SourceList.h"
|
||||
|
||||
#include "sip/SipHandler.h"
|
||||
#include "utils/TomahawkUtilsGui.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
|
||||
DiagnosticsDialog::DiagnosticsDialog( QWidget *parent )
|
||||
@@ -44,11 +45,10 @@ DiagnosticsDialog::DiagnosticsDialog( QWidget *parent )
|
||||
{
|
||||
ui->setupUi( this );
|
||||
|
||||
connect( ui->clipboardButton, SIGNAL( clicked() ), this, SLOT( copyToClipboard() ) );
|
||||
connect( ui->buttonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
|
||||
connect( ui->clipboardButton, SIGNAL( clicked() ), SLOT( copyToClipboard() ) );
|
||||
connect( ui->logfileButton, SIGNAL( clicked() ), SLOT( openLogfile() ) );
|
||||
connect( ui->buttonBox, SIGNAL( rejected() ), SLOT( reject() ) );
|
||||
|
||||
ui->scrollAreaWidgetContents->setLayout( new QVBoxLayout() );
|
||||
|
||||
updateLogView();
|
||||
}
|
||||
|
||||
@@ -58,16 +58,10 @@ DiagnosticsDialog::updateLogView()
|
||||
{
|
||||
QString log;
|
||||
|
||||
log.append(
|
||||
QString("TOMAHAWK DIAGNOSTICS LOG -%1 \n\n")
|
||||
.arg( QDateTime::currentDateTime().toString() )
|
||||
);
|
||||
|
||||
// network
|
||||
log.append( QString( "TOMAHAWK DIAGNOSTICS LOG -%1 \n\n" ).arg( QDateTime::currentDateTime().toString() ) );
|
||||
log.append( "TOMAHAWK-VERSION: " TOMAHAWK_VERSION "\n\n" );
|
||||
|
||||
// network
|
||||
log.append( "NETWORK:\n General:\n" );
|
||||
|
||||
if ( Servent::instance()->visibleExternally() )
|
||||
{
|
||||
log.append(
|
||||
@@ -86,10 +80,8 @@ DiagnosticsDialog::updateLogView()
|
||||
log.append( " visible: false" );
|
||||
}
|
||||
|
||||
ui->scrollAreaWidgetContents->layout()->addWidget( new QLabel( log, this ) );
|
||||
// Peers / Accounts, TODO
|
||||
ui->scrollAreaWidgetContents->layout()->addWidget( new QLabel( "ACCOUNTS:\n", this ) );
|
||||
|
||||
log.append( "ACCOUNTS:\n" );
|
||||
|
||||
const QList< Tomahawk::source_ptr > sources = SourceList::instance()->sources( true );
|
||||
const QList< Tomahawk::Accounts::Account* > accounts = Tomahawk::Accounts::AccountManager::instance()->accounts( Tomahawk::Accounts::SipType );
|
||||
foreach ( Tomahawk::Accounts::Account* account, accounts )
|
||||
@@ -98,165 +90,98 @@ DiagnosticsDialog::updateLogView()
|
||||
if ( !account || !account->sipPlugin() )
|
||||
continue;
|
||||
|
||||
connect( account, SIGNAL( connectionStateChanged( Tomahawk::Accounts::Account::ConnectionState ) ),
|
||||
SLOT( onAccountConnectionStateChanged( Tomahawk::Accounts::Account::ConnectionState ) ) );
|
||||
connect( account, SIGNAL( error( int, QString ) ),
|
||||
SLOT( onAccountError( int, QString ) ) );
|
||||
connect( account, SIGNAL( connectionStateChanged( Tomahawk::Accounts::Account::ConnectionState ) ), SLOT( updateLogView() ), Qt::UniqueConnection );
|
||||
connect( account, SIGNAL( error( int, QString ) ), SLOT( updateLogView() ), Qt::UniqueConnection );
|
||||
connect( account->sipPlugin(), SIGNAL( peerOnline( QString ) ), SLOT( updateLogView() ), Qt::UniqueConnection );
|
||||
connect( account->sipPlugin(), SIGNAL( peerOffline( QString ) ), SLOT( updateLogView() ), Qt::UniqueConnection );
|
||||
connect( account->sipPlugin(), SIGNAL( sipInfoReceived( QString, SipInfo ) ), SLOT( updateLogView() ), Qt::UniqueConnection );
|
||||
connect( account->sipPlugin(), SIGNAL( softwareVersionReceived( QString, QString ) ), SLOT( updateLogView() ), Qt::UniqueConnection );
|
||||
|
||||
connect( account->sipPlugin(), SIGNAL( peerOnline( QString ) ), SLOT( onPeerOnline( QString ) ) );
|
||||
connect( account->sipPlugin(), SIGNAL( peerOffline( QString ) ), SLOT( onPeerOffline( QString ) ) );
|
||||
connect( account->sipPlugin(), SIGNAL( sipInfoReceived( QString, SipInfo ) ), SLOT( onSipInfoReceived( QString, SipInfo ) ) );
|
||||
connect( account->sipPlugin(), SIGNAL( softwareVersionReceived( QString, QString ) ), SLOT( onSoftwareVersionReceived( QString, QString ) ) );
|
||||
|
||||
QLabel* accountInfoLabel = new QLabel( this );
|
||||
ui->scrollAreaWidgetContents->layout()->addWidget( accountInfoLabel );
|
||||
m_accountDescriptionStore.insert( account, accountInfoLabel );
|
||||
|
||||
updateAccountLabel( account );
|
||||
log.append( accountLog( account ) + "\n" );
|
||||
}
|
||||
|
||||
ui->text->setText( log );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DiagnosticsDialog::copyToClipboard()
|
||||
{
|
||||
QString log;
|
||||
foreach ( QLabel* label, m_accountDescriptionStore.values() )
|
||||
QApplication::clipboard()->setText( ui->text->toPlainText() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DiagnosticsDialog::openLogfile()
|
||||
{
|
||||
TomahawkUtils::openUrl( Logger::logFile() );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
DiagnosticsDialog::accountLog( Tomahawk::Accounts::Account* account )
|
||||
{
|
||||
QString accountInfo;
|
||||
QString stateString;
|
||||
switch( account->connectionState() )
|
||||
{
|
||||
log += label->text() + "\n\n";
|
||||
case Tomahawk::Accounts::Account::Connecting:
|
||||
stateString = "Connecting";
|
||||
break;
|
||||
case Tomahawk::Accounts::Account::Connected:
|
||||
stateString = "Connected";
|
||||
break;
|
||||
|
||||
case Tomahawk::Accounts::Account::Disconnected:
|
||||
stateString = "Disconnected";
|
||||
break;
|
||||
case Tomahawk::Accounts::Account::Disconnecting:
|
||||
stateString = "Disconnecting";
|
||||
}
|
||||
accountInfo.append(
|
||||
QString( " %2 (%1): %3 (%4)\n" )
|
||||
.arg( account->accountServiceName() )
|
||||
.arg( account->sipPlugin()->friendlyName() )
|
||||
.arg( account->accountFriendlyName())
|
||||
.arg( stateString )
|
||||
);
|
||||
|
||||
QApplication::clipboard()->setText( log );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DiagnosticsDialog::onAccountConnectionStateChanged( Tomahawk::Accounts::Account::ConnectionState /* state */ )
|
||||
{
|
||||
Tomahawk::Accounts::Account* account = qobject_cast< Tomahawk::Accounts::Account* >( sender() );
|
||||
Q_ASSERT( account );
|
||||
|
||||
updateAccountLabel( account );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DiagnosticsDialog::onAccountError( int /* errorId */ , QString /* errorString */ )
|
||||
{
|
||||
Tomahawk::Accounts::Account* account = qobject_cast< Tomahawk::Accounts::Account* >( sender() );
|
||||
Q_ASSERT( account );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DiagnosticsDialog::onPeerOnline( const QString& )
|
||||
{
|
||||
Tomahawk::Accounts::Account* account = qobject_cast< SipPlugin* >( sender() )->account();
|
||||
Q_ASSERT( account );
|
||||
|
||||
updateAccountLabel( account );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DiagnosticsDialog::onPeerOffline( const QString& )
|
||||
{
|
||||
Tomahawk::Accounts::Account* account = qobject_cast< SipPlugin* >( sender() )->account();
|
||||
Q_ASSERT( account );
|
||||
|
||||
updateAccountLabel( account );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DiagnosticsDialog::onSipInfoReceived( const QString& /* peerId */ , const SipInfo& /* info */ )
|
||||
{
|
||||
Tomahawk::Accounts::Account* account = qobject_cast< SipPlugin* >( sender() )->account();
|
||||
Q_ASSERT( account );
|
||||
|
||||
updateAccountLabel( account );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DiagnosticsDialog::onSoftwareVersionReceived( const QString& /* peerId */ , const QString& /* versionString */ )
|
||||
{
|
||||
Tomahawk::Accounts::Account* account = qobject_cast< SipPlugin* >( sender() )->account();
|
||||
Q_ASSERT( account );
|
||||
|
||||
updateAccountLabel( account );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DiagnosticsDialog::updateAccountLabel( Tomahawk::Accounts::Account* account )
|
||||
{
|
||||
QLabel* accountInfoLabel = m_accountDescriptionStore.value( account );
|
||||
|
||||
if ( accountInfoLabel )
|
||||
foreach( const QString& peerId, account->sipPlugin()->peersOnline() )
|
||||
{
|
||||
QString accountInfo;
|
||||
QString stateString;
|
||||
switch( account->connectionState() )
|
||||
QString versionString = SipHandler::instance()->versionString( peerId );
|
||||
SipInfo sipInfo = SipHandler::instance()->sipInfo( peerId );
|
||||
if ( !sipInfo.isValid() )
|
||||
{
|
||||
case Tomahawk::Accounts::Account::Connecting:
|
||||
stateString = "Connecting";
|
||||
break;
|
||||
case Tomahawk::Accounts::Account::Connected:
|
||||
stateString = "Connected";
|
||||
break;
|
||||
|
||||
case Tomahawk::Accounts::Account::Disconnected:
|
||||
stateString = "Disconnected";
|
||||
break;
|
||||
case Tomahawk::Accounts::Account::Disconnecting:
|
||||
stateString = "Disconnecting";
|
||||
accountInfo.append(
|
||||
QString(" %1: %2 %3" /*"(%4)"*/ "\n")
|
||||
.arg( peerId )
|
||||
.arg( "sipinfo invalid" )
|
||||
.arg( versionString )
|
||||
// .arg( connected ? "connected" : "not connected")
|
||||
);
|
||||
}
|
||||
accountInfo.append(
|
||||
QString( " %2 (%1): %3 (%4)\n" )
|
||||
.arg( account->accountServiceName() )
|
||||
.arg( account->sipPlugin()->friendlyName() )
|
||||
.arg( account->accountFriendlyName())
|
||||
.arg( stateString )
|
||||
);
|
||||
|
||||
foreach( const QString& peerId, account->sipPlugin()->peersOnline() )
|
||||
else if ( sipInfo.isVisible() )
|
||||
{
|
||||
QString versionString = SipHandler::instance()->versionString( peerId );
|
||||
SipInfo sipInfo = SipHandler::instance()->sipInfo( peerId );
|
||||
if ( !sipInfo.isValid() )
|
||||
{
|
||||
accountInfo.append(
|
||||
QString(" %1: %2 %3" /*"(%4)"*/ "\n")
|
||||
.arg( peerId )
|
||||
.arg( "sipinfo invalid" )
|
||||
.arg( versionString )
|
||||
// .arg( connected ? "connected" : "not connected")
|
||||
);
|
||||
}
|
||||
else if ( sipInfo.isVisible() )
|
||||
{
|
||||
accountInfo.append(
|
||||
QString(" %1: %2:%3 %4" /*" (%5)"*/ "\n")
|
||||
.arg( peerId )
|
||||
.arg( sipInfo.host().hostName() )
|
||||
.arg( sipInfo.port() )
|
||||
.arg( versionString )
|
||||
// .arg( connected ? "connected" : "not connected")
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
accountInfo.append(
|
||||
QString(" %1: visible: false %2" /*" (%3)"*/ "\n")
|
||||
.arg( peerId )
|
||||
.arg( versionString )
|
||||
// .arg( connected ? "connected" : "not connected")
|
||||
);
|
||||
}
|
||||
accountInfo.append(
|
||||
QString(" %1: %2:%3 %4" /*" (%5)"*/ "\n")
|
||||
.arg( peerId )
|
||||
.arg( sipInfo.host() )
|
||||
.arg( sipInfo.port() )
|
||||
.arg( versionString )
|
||||
// .arg( connected ? "connected" : "not connected")
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
accountInfo.append(
|
||||
QString(" %1: visible: false %2" /*" (%3)"*/ "\n")
|
||||
.arg( peerId )
|
||||
.arg( versionString )
|
||||
// .arg( connected ? "connected" : "not connected")
|
||||
);
|
||||
}
|
||||
accountInfo.append( "\n" );
|
||||
|
||||
accountInfoLabel->setText( accountInfo );
|
||||
}
|
||||
accountInfo.append( "\n" );
|
||||
|
||||
return accountInfo;
|
||||
}
|
@@ -45,19 +45,11 @@ public:
|
||||
private slots:
|
||||
void updateLogView();
|
||||
void copyToClipboard();
|
||||
|
||||
void onAccountConnectionStateChanged( Tomahawk::Accounts::Account::ConnectionState state );
|
||||
void onAccountError( int errorId, QString errorString );
|
||||
void onPeerOnline( const QString& );
|
||||
void onPeerOffline( const QString& );
|
||||
void onSipInfoReceived( const QString& peerId, const SipInfo& info );
|
||||
void onSoftwareVersionReceived( const QString& peerId, const QString& versionString );
|
||||
void openLogfile();
|
||||
|
||||
QString accountLog( Tomahawk::Accounts::Account* );
|
||||
|
||||
void updateAccountLabel( Tomahawk::Accounts::Account* );
|
||||
private:
|
||||
|
||||
QMap< Tomahawk::Accounts::Account*, QLabel* > m_accountDescriptionStore;
|
||||
|
||||
Ui::DiagnosticsDialog* ui;
|
||||
};
|
||||
|
||||
|
@@ -26,20 +26,10 @@
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
<widget class="QTextBrowser" name="text">
|
||||
<property name="lineWrapMode">
|
||||
<enum>QTextEdit::NoWrap</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>708</width>
|
||||
<height>386</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -49,7 +39,14 @@
|
||||
<item>
|
||||
<widget class="QPushButton" name="clipboardButton">
|
||||
<property name="text">
|
||||
<string>Copy to Clipboard</string>
|
||||
<string>&Copy to Clipboard</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="logfileButton">
|
||||
<property name="text">
|
||||
<string>Open &Log-file</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@@ -208,6 +208,7 @@ MusicScanner::listerFinished()
|
||||
|
||||
if ( m_filesToDelete.length() || m_scannedfiles.length() )
|
||||
{
|
||||
SourceList::instance()->getLocal()->updateIndexWhenSynced();
|
||||
commitBatch( m_scannedfiles, m_filesToDelete );
|
||||
m_scannedfiles.clear();
|
||||
m_filesToDelete.clear();
|
||||
@@ -335,7 +336,7 @@ MusicScanner::readFile( const QFileInfo& fi )
|
||||
|
||||
int bitrate = 0;
|
||||
int duration = 0;
|
||||
|
||||
|
||||
Tag *tag = Tag::fromFile( f );
|
||||
if ( f.audioProperties() )
|
||||
{
|
||||
|
@@ -200,7 +200,7 @@ TomahawkApp::init()
|
||||
QFontMetrics fm( f );
|
||||
TomahawkUtils::setHeaderHeight( fm.height() + 8 );
|
||||
#endif
|
||||
|
||||
|
||||
TomahawkUtils::setHeadless( m_headless );
|
||||
|
||||
TomahawkSettings* s = TomahawkSettings::instance();
|
||||
@@ -210,11 +210,18 @@ TomahawkApp::init()
|
||||
Q_UNUSED( TomahawkUtils::nam() );
|
||||
|
||||
m_audioEngine = QWeakPointer<AudioEngine>( new AudioEngine );
|
||||
m_scanManager = QWeakPointer<ScanManager>( new ScanManager( this ) );
|
||||
|
||||
// init pipeline and resolver factories
|
||||
new Pipeline();
|
||||
|
||||
m_servent = QWeakPointer<Servent>( new Servent( this ) );
|
||||
connect( m_servent.data(), SIGNAL( ready() ), SLOT( initSIP() ) );
|
||||
|
||||
tDebug() << "Init Database.";
|
||||
initDatabase();
|
||||
|
||||
m_scanManager = QWeakPointer<ScanManager>( new ScanManager( this ) );
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
Pipeline::instance()->addExternalResolverFactory( boost::bind( &QtScriptResolver::factory, _1 ) );
|
||||
Pipeline::instance()->addExternalResolverFactory( boost::bind( &ScriptResolver::factory, _1 ) );
|
||||
@@ -223,12 +230,6 @@ TomahawkApp::init()
|
||||
connect( ActionCollection::instance()->getAction( "quit" ), SIGNAL( triggered() ), SLOT( quit() ), Qt::UniqueConnection );
|
||||
#endif
|
||||
|
||||
m_servent = QWeakPointer<Servent>( new Servent( this ) );
|
||||
connect( m_servent.data(), SIGNAL( ready() ), SLOT( initSIP() ) );
|
||||
|
||||
tDebug() << "Init Database.";
|
||||
initDatabase();
|
||||
|
||||
QByteArray magic = QByteArray::fromBase64( enApiSecret );
|
||||
QByteArray wand = QByteArray::fromBase64( QCoreApplication::applicationName().toLatin1() );
|
||||
int length = magic.length(), n2 = wand.length();
|
||||
@@ -359,35 +360,48 @@ TomahawkApp::~TomahawkApp()
|
||||
|
||||
if ( !m_session.isNull() )
|
||||
delete m_session.data();
|
||||
tLog() << "Deleting connector";
|
||||
if ( !m_connector.isNull() )
|
||||
delete m_connector.data();
|
||||
|
||||
tLog() << "Stopping pipeline";
|
||||
if ( Pipeline::instance() )
|
||||
Pipeline::instance()->stop();
|
||||
|
||||
tLog() << "Deleting servent";
|
||||
if ( !m_servent.isNull() )
|
||||
delete m_servent.data();
|
||||
tLog() << "Deleting ScanManager";
|
||||
if ( !m_scanManager.isNull() )
|
||||
delete m_scanManager.data();
|
||||
|
||||
tLog() << "Deleting AudioEngine";
|
||||
if ( !m_audioEngine.isNull() )
|
||||
delete m_audioEngine.data();
|
||||
|
||||
tLog() << "Deleting AccountManager";
|
||||
delete Tomahawk::Accounts::AccountManager::instance();
|
||||
delete TomahawkUtils::Cache::instance();
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
delete m_mainwindow;
|
||||
tLog() << "Deleting AtticaManager";
|
||||
delete AtticaManager::instance();
|
||||
tLog() << "Deleting Window";
|
||||
delete m_mainwindow;
|
||||
#endif
|
||||
|
||||
tLog() << "Deleting database";
|
||||
if ( !m_database.isNull() )
|
||||
delete m_database.data();
|
||||
|
||||
tLog() << "Deleting Pipeline";
|
||||
delete Pipeline::instance();
|
||||
|
||||
tLog() << "Deleting InfoSystem";
|
||||
if ( !m_infoSystem.isNull() )
|
||||
delete m_infoSystem.data();
|
||||
|
||||
tLog() << "Deleting Cache";
|
||||
delete TomahawkUtils::Cache::instance();
|
||||
|
||||
tLog() << "Finished shutdown.";
|
||||
}
|
||||
|
@@ -59,10 +59,10 @@ public slots:
|
||||
void disconnectPlugin();
|
||||
void configurationChanged();
|
||||
|
||||
void sendMsg( const QString& to, const QString& msg )
|
||||
void sendMsg( const QString& peerId, const SipInfo& info )
|
||||
{
|
||||
Q_UNUSED( to );
|
||||
Q_UNUSED( msg );
|
||||
Q_UNUSED( peerId );
|
||||
Q_UNUSED( info );
|
||||
}
|
||||
|
||||
void broadcastMsg( const QString &msg )
|
||||
@@ -70,9 +70,9 @@ public slots:
|
||||
Q_UNUSED( msg );
|
||||
}
|
||||
|
||||
void addContact( const QString &jid, const QString& msg = QString() )
|
||||
void addContact( const QString &peerId, const QString& msg = QString() )
|
||||
{
|
||||
Q_UNUSED( jid );
|
||||
Q_UNUSED( peerId );
|
||||
Q_UNUSED( msg );
|
||||
}
|
||||
|
||||
|
@@ -73,6 +73,11 @@ AvatarManager::fetchVCard( const QString& jid )
|
||||
void
|
||||
AvatarManager::onNewPresence( const Jreen::Presence& presence )
|
||||
{
|
||||
if ( presence.error() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Jreen::VCardUpdate::Ptr update = presence.payload<Jreen::VCardUpdate>();
|
||||
if ( update )
|
||||
{
|
||||
|
@@ -110,7 +110,7 @@ XmppSipPlugin::XmppSipPlugin( Account* account )
|
||||
Jreen::JID jid = Jreen::JID( readUsername() );
|
||||
|
||||
// general client setup
|
||||
m_client = new Jreen::Client( jid, m_currentPassword );
|
||||
m_client = new Jreen::Client( jid, m_currentPassword );
|
||||
setupClientHelper();
|
||||
|
||||
m_client->registerPayload( new TomahawkXmppMessageFactory );
|
||||
@@ -425,32 +425,17 @@ XmppSipPlugin::errorMessage( Jreen::Client::DisconnectReason reason )
|
||||
|
||||
|
||||
void
|
||||
XmppSipPlugin::sendMsg( const QString& to, const QString& msg )
|
||||
XmppSipPlugin::sendMsg( const QString& to, const SipInfo& info )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << to << msg;
|
||||
qDebug() << Q_FUNC_INFO << to << info;
|
||||
|
||||
if ( !m_client )
|
||||
return;
|
||||
|
||||
/*******************************************************
|
||||
* Obsolete this by a SipMessage class
|
||||
*/
|
||||
QJson::Parser parser;
|
||||
bool ok;
|
||||
QVariant v = parser.parse( msg.toAscii(), &ok );
|
||||
if ( !ok || v.type() != QVariant::Map )
|
||||
{
|
||||
qDebug() << "Invalid JSON in Xmpp msg";
|
||||
return;
|
||||
}
|
||||
|
||||
QVariantMap m = v.toMap();
|
||||
/*******************************************************/
|
||||
|
||||
TomahawkXmppMessage *sipMessage;
|
||||
if ( m["visible"].toBool() )
|
||||
if ( info.isVisible() )
|
||||
{
|
||||
sipMessage = new TomahawkXmppMessage( m["ip"].toString(), m["port"].toInt(), m["uniqname"].toString(), m["key"].toString() );
|
||||
sipMessage = new TomahawkXmppMessage( info.host(), info.port(), info.uniqname(), info.key() );
|
||||
}
|
||||
else
|
||||
sipMessage = new TomahawkXmppMessage();
|
||||
@@ -467,13 +452,6 @@ XmppSipPlugin::sendMsg( const QString& to, const QString& msg )
|
||||
void
|
||||
XmppSipPlugin::broadcastMsg( const QString& msg )
|
||||
{
|
||||
if ( !m_client )
|
||||
return;
|
||||
|
||||
foreach ( const Jreen::JID& jid, m_peers.keys() )
|
||||
{
|
||||
sendMsg( jid.full(), msg );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -914,9 +892,7 @@ XmppSipPlugin::onNewIq( const Jreen::IQ& iq )
|
||||
info.setVisible( sipMessage->visible() );
|
||||
if ( sipMessage->visible() )
|
||||
{
|
||||
QHostInfo hi;
|
||||
hi.setHostName( sipMessage->ip() );
|
||||
info.setHost( hi );
|
||||
info.setHost( sipMessage->ip() );
|
||||
info.setPort( sipMessage->port() );
|
||||
info.setUniqname( sipMessage->uniqname() );
|
||||
info.setKey( sipMessage->key() );
|
||||
|
@@ -86,8 +86,8 @@ public slots:
|
||||
virtual void disconnectPlugin();
|
||||
virtual void checkSettings();
|
||||
virtual void configurationChanged();
|
||||
virtual void sendMsg( const QString& to, const QString& msg );
|
||||
virtual void addContact( const QString& jid, const QString& msg = QString() );
|
||||
virtual void sendMsg( const QString& peerId, const SipInfo& info );
|
||||
virtual void addContact( const QString& peerId, const QString& msg = QString() );
|
||||
|
||||
void broadcastMsg( const QString& msg );
|
||||
void showAddFriendDialog();
|
||||
|
@@ -64,7 +64,7 @@ public slots:
|
||||
|
||||
void advertise();
|
||||
|
||||
void sendMsg( const QString& , const QString& ) {}
|
||||
void sendMsg( const QString& peerId , const SipInfo& ) {}
|
||||
void broadcastMsg( const QString & ) {}
|
||||
void addContact( const QString &, const QString& ) {}
|
||||
|
||||
|
@@ -66,17 +66,17 @@ CrashReporter::CrashReporter( const QStringList& args )
|
||||
m_minidump = m_dir + '/' + args.value( 2 ) + ".dmp";
|
||||
m_product_name = args.value( 3 );
|
||||
|
||||
setFixedSize( sizeHint() );
|
||||
|
||||
//hide until "send report" has been clicked
|
||||
ui.progressBar->setVisible( false );
|
||||
ui.button->setVisible( false );
|
||||
ui.progressLabel->setVisible( false );
|
||||
connect( ui.sendButton, SIGNAL( clicked() ), SLOT( onSendButton() ));
|
||||
|
||||
connect( ui.sendButton, SIGNAL( clicked() ), SLOT( onSendButton() ) );
|
||||
|
||||
adjustSize();
|
||||
setFixedSize( size() );
|
||||
}
|
||||
|
||||
|
||||
CrashReporter::~CrashReporter()
|
||||
{
|
||||
delete m_http;
|
||||
@@ -186,6 +186,7 @@ CrashReporter::onFail( int error, const QString& errorString )
|
||||
qDebug() << "Error:" << error << errorString;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CrashReporter::onSendButton()
|
||||
{
|
||||
@@ -194,5 +195,9 @@ CrashReporter::onSendButton()
|
||||
ui.progressLabel->setVisible( true );
|
||||
ui.sendButton->setEnabled( false );
|
||||
ui.dontSendButton->setEnabled( false );
|
||||
|
||||
adjustSize();
|
||||
setFixedSize( size() );
|
||||
|
||||
QTimer::singleShot( 0, this, SLOT( send() ) );
|
||||
}
|
||||
|
@@ -9,8 +9,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>438</width>
|
||||
<height>246</height>
|
||||
<width>376</width>
|
||||
<height>216</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@@ -1,4 +1,4 @@
|
||||
include_directories(${LIBECHONEST_INCLUDE_DIR})
|
||||
include_directories(${ECHONEST_INCLUDE_DIR})
|
||||
|
||||
list(APPEND simple_plugins
|
||||
Echonest
|
||||
|
@@ -109,7 +109,7 @@ FdoNotifyPlugin::notifyUser( const QString &messageText )
|
||||
arguments << quint32( 0 ); //notification_id
|
||||
arguments << QString(); //app_icon
|
||||
arguments << QString( "Tomahawk" ); //summary
|
||||
arguments << messageText; //body
|
||||
arguments << QString( messageText ); //body
|
||||
arguments << QStringList(); //actions
|
||||
QVariantMap dict;
|
||||
dict["desktop-entry"] = QString( "tomahawk" );
|
||||
|
@@ -174,17 +174,21 @@ Album::infoSystemInfo( const Tomahawk::InfoSystem::InfoRequestData& requestData,
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !output.isNull() && output.isValid() )
|
||||
if ( output.isNull() )
|
||||
{
|
||||
m_coverLoaded = true;
|
||||
}
|
||||
else if ( output.isValid() )
|
||||
{
|
||||
QVariantMap returnedData = output.value< QVariantMap >();
|
||||
const QByteArray ba = returnedData["imgbytes"].toByteArray();
|
||||
if ( ba.length() )
|
||||
{
|
||||
m_coverBuffer = ba;
|
||||
emit coverChanged();
|
||||
}
|
||||
|
||||
m_coverLoaded = true;
|
||||
emit coverChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,6 +241,6 @@ Album::infoid() const
|
||||
{
|
||||
if ( m_uuid.isEmpty() )
|
||||
m_uuid = uuid();
|
||||
|
||||
|
||||
return m_uuid;
|
||||
}
|
@@ -114,13 +114,17 @@ AlbumPlaylistInterface::tracks()
|
||||
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
|
||||
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
|
||||
|
||||
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
|
||||
SIGNAL( finished( QString ) ),
|
||||
SLOT( infoSystemFinished( QString ) ) );
|
||||
}
|
||||
else if ( m_mode == DatabaseMode && !m_databaseLoaded )
|
||||
{
|
||||
DatabaseCommand_AllTracks* cmd = new DatabaseCommand_AllTracks( m_collection );
|
||||
cmd->setAlbum( m_album );
|
||||
cmd->setSortOrder( DatabaseCommand_AllTracks::AlbumPosition );
|
||||
|
||||
|
||||
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr>, QVariant ) ),
|
||||
SLOT( onTracksLoaded( QList<Tomahawk::query_ptr> ) ) );
|
||||
|
||||
@@ -178,9 +182,24 @@ AlbumPlaylistInterface::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData re
|
||||
}
|
||||
}
|
||||
|
||||
if ( !m_queries.isEmpty() )
|
||||
{
|
||||
infoSystemFinished( id() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlbumPlaylistInterface::infoSystemFinished( const QString& infoId )
|
||||
{
|
||||
if ( infoId != id() )
|
||||
return;
|
||||
|
||||
m_infoSystemLoaded = true;
|
||||
disconnect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
this, SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
|
||||
disconnect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ),
|
||||
this, SLOT( infoSystemFinished( QString ) ) );
|
||||
|
||||
if ( m_queries.isEmpty() && m_mode == Mixed )
|
||||
{
|
||||
@@ -188,7 +207,7 @@ AlbumPlaylistInterface::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData re
|
||||
cmd->setAlbum( m_album );
|
||||
//this takes discnumber into account as well
|
||||
cmd->setSortOrder( DatabaseCommand_AllTracks::AlbumPosition );
|
||||
|
||||
|
||||
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr>, QVariant ) ),
|
||||
SLOT( onTracksLoaded( QList<Tomahawk::query_ptr> ) ) );
|
||||
|
||||
@@ -196,6 +215,7 @@ AlbumPlaylistInterface::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData re
|
||||
}
|
||||
else
|
||||
{
|
||||
m_finished = true;
|
||||
emit tracksLoaded( m_mode, m_collection );
|
||||
}
|
||||
}
|
||||
@@ -212,5 +232,6 @@ AlbumPlaylistInterface::onTracksLoaded( const QList< query_ptr >& tracks )
|
||||
else
|
||||
m_queries << tracks;
|
||||
|
||||
m_finished = true;
|
||||
emit tracksLoaded( m_mode, m_collection );
|
||||
}
|
||||
|
@@ -64,6 +64,7 @@ signals:
|
||||
private slots:
|
||||
void onTracksLoaded( const QList< Tomahawk::query_ptr >& tracks );
|
||||
void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
|
||||
void infoSystemFinished( const QString& infoId );
|
||||
|
||||
private:
|
||||
QList< Tomahawk::query_ptr > m_queries;
|
||||
|
@@ -315,16 +315,20 @@ Artist::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVari
|
||||
|
||||
case Tomahawk::InfoSystem::InfoArtistImages:
|
||||
{
|
||||
if ( !output.isNull() && output.isValid() )
|
||||
if ( output.isNull() )
|
||||
{
|
||||
m_coverLoaded = true;
|
||||
}
|
||||
else if ( output.isValid() )
|
||||
{
|
||||
const QByteArray ba = returnedData["imgbytes"].toByteArray();
|
||||
if ( ba.length() )
|
||||
{
|
||||
m_coverBuffer = ba;
|
||||
emit coverChanged();
|
||||
}
|
||||
|
||||
m_coverLoaded = true;
|
||||
emit coverChanged();
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -353,7 +357,7 @@ Artist::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVari
|
||||
if ( source == "last.fm" )
|
||||
m_biography = bmap[ source ].toHash()[ "text" ].toString();
|
||||
}
|
||||
|
||||
|
||||
m_biographyLoaded = true;
|
||||
emit biographyLoaded();
|
||||
|
||||
@@ -459,7 +463,7 @@ Artist::playlistInterface( ModelMode mode, const Tomahawk::collection_ptr& colle
|
||||
pli = Tomahawk::playlistinterface_ptr( new Tomahawk::ArtistPlaylistInterface( this, mode, collection ) );
|
||||
connect( pli.data(), SIGNAL( tracksLoaded( Tomahawk::ModelMode, Tomahawk::collection_ptr ) ),
|
||||
SLOT( onTracksLoaded( Tomahawk::ModelMode, Tomahawk::collection_ptr ) ) );
|
||||
|
||||
|
||||
m_playlistInterface[ mode ][ collection ] = pli;
|
||||
}
|
||||
|
||||
@@ -479,6 +483,6 @@ Artist::infoid() const
|
||||
{
|
||||
if ( m_uuid.isEmpty() )
|
||||
m_uuid = uuid();
|
||||
|
||||
|
||||
return m_uuid;
|
||||
}
|
||||
|
@@ -112,13 +112,17 @@ ArtistPlaylistInterface::tracks()
|
||||
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
|
||||
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
|
||||
|
||||
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
|
||||
SIGNAL( finished( QString ) ),
|
||||
SLOT( infoSystemFinished( QString ) ) );
|
||||
}
|
||||
else if ( m_mode == DatabaseMode && !m_databaseLoaded )
|
||||
{
|
||||
DatabaseCommand_AllTracks* cmd = new DatabaseCommand_AllTracks( m_collection );
|
||||
cmd->setArtist( m_artist );
|
||||
cmd->setSortOrder( DatabaseCommand_AllTracks::AlbumPosition );
|
||||
|
||||
|
||||
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr>, QVariant ) ),
|
||||
SLOT( onTracksLoaded( QList<Tomahawk::query_ptr> ) ) );
|
||||
|
||||
@@ -176,9 +180,23 @@ ArtistPlaylistInterface::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData r
|
||||
}
|
||||
}
|
||||
|
||||
if ( !m_queries.isEmpty() )
|
||||
infoSystemFinished( id() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ArtistPlaylistInterface::infoSystemFinished( const QString &infoId )
|
||||
{
|
||||
if ( infoId != id() )
|
||||
return;
|
||||
|
||||
m_infoSystemLoaded = true;
|
||||
|
||||
disconnect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
this, SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
|
||||
disconnect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ),
|
||||
this, SLOT( infoSystemFinished( QString) ) );
|
||||
|
||||
if ( m_queries.isEmpty() && m_mode == Mixed )
|
||||
{
|
||||
@@ -186,7 +204,7 @@ ArtistPlaylistInterface::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData r
|
||||
cmd->setArtist( m_artist );
|
||||
//this takes discnumber into account as well
|
||||
cmd->setSortOrder( DatabaseCommand_AllTracks::AlbumPosition );
|
||||
|
||||
|
||||
connect( cmd, SIGNAL( tracks( QList<Tomahawk::query_ptr>, QVariant ) ),
|
||||
SLOT( onTracksLoaded( QList<Tomahawk::query_ptr> ) ) );
|
||||
|
||||
@@ -194,6 +212,7 @@ ArtistPlaylistInterface::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData r
|
||||
}
|
||||
else
|
||||
{
|
||||
m_finished = true;
|
||||
emit tracksLoaded( m_mode, m_collection );
|
||||
}
|
||||
}
|
||||
@@ -210,5 +229,6 @@ ArtistPlaylistInterface::onTracksLoaded( const QList< query_ptr >& tracks )
|
||||
else
|
||||
m_queries << tracks;
|
||||
|
||||
m_finished = true;
|
||||
emit tracksLoaded( m_mode, m_collection );
|
||||
}
|
||||
|
@@ -63,6 +63,7 @@ signals:
|
||||
private slots:
|
||||
void onTracksLoaded( const QList< Tomahawk::query_ptr >& tracks );
|
||||
void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
|
||||
void infoSystemFinished( const QString& infoId );
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY( ArtistPlaylistInterface )
|
||||
|
@@ -31,6 +31,9 @@
|
||||
#include <QTemporaryFile>
|
||||
#include <QDir>
|
||||
#include <QTimer>
|
||||
#include <QDomDocument>
|
||||
#include <QDomElement>
|
||||
#include <QDomNode>
|
||||
|
||||
#include "utils/Logger.h"
|
||||
#include "accounts/ResolverAccount.h"
|
||||
@@ -64,7 +67,7 @@ AtticaManager::AtticaManager( QObject* parent )
|
||||
// resolvers
|
||||
// m_manager.addProviderFile( QUrl( "http://bakery.tomahawk-player.org/resolvers/providers.xml" ) );
|
||||
|
||||
const QString url = QString( "http://bakery.tomahawk-player.org/resolvers/providers.xml?version=%1" ).arg( TomahawkUtils::appFriendlyVersion() );
|
||||
const QString url = QString( "%1/resolvers/providers.xml?version=%2" ).arg( hostname() ).arg( TomahawkUtils::appFriendlyVersion() );
|
||||
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( QUrl( url ) ) );
|
||||
NewClosure( reply, SIGNAL( finished() ), this, SLOT( providerFetched( QNetworkReply* ) ), reply );
|
||||
connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( providerError( QNetworkReply::NetworkError ) ) );
|
||||
@@ -90,6 +93,12 @@ AtticaManager::~AtticaManager()
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
AtticaManager::hostname() const
|
||||
{
|
||||
return "http://bakery.tomahawk-player.org";
|
||||
}
|
||||
|
||||
void
|
||||
AtticaManager::loadPixmapsFromCache()
|
||||
{
|
||||
@@ -523,14 +532,15 @@ void AtticaManager::doInstallResolver( const Content& resolver, bool autoCreate,
|
||||
m_resolverStates[ resolver.id() ].version = resolver.version();
|
||||
emit resolverStateChanged( resolver.id() );
|
||||
|
||||
ItemJob< DownloadItem >* job = m_resolverProvider.downloadLink( resolver.id() );
|
||||
connect( job, SIGNAL( finished( Attica::BaseJob* ) ), this, SLOT( resolverDownloadFinished( Attica::BaseJob* ) ) );
|
||||
job->setProperty( "resolverId", resolver.id() );
|
||||
job->setProperty( "createAccount", autoCreate );
|
||||
job->setProperty( "handler", QVariant::fromValue< QObject* >( handler ) );
|
||||
job->setProperty( "binarySignature", resolver.attribute("signature"));
|
||||
|
||||
job->start();
|
||||
// ItemJob< DownloadItem >* job = m_resolverProvider.downloadLink( resolver.id() );
|
||||
QUrl url( QString( "%1/resolvers/v1/content/download/%2/1" ).arg( hostname() ).arg( resolver.id() ) );
|
||||
url.addQueryItem( "tomahawkversion", TomahawkUtils::appFriendlyVersion() );
|
||||
QNetworkReply* r = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
|
||||
NewClosure( r, SIGNAL( finished() ), this, SLOT( resolverDownloadFinished( QNetworkReply* ) ), r );
|
||||
r->setProperty( "resolverId", resolver.id() );
|
||||
r->setProperty( "createAccount", autoCreate );
|
||||
r->setProperty( "handler", QVariant::fromValue< QObject* >( handler ) );
|
||||
r->setProperty( "binarySignature", resolver.attribute("signature"));
|
||||
}
|
||||
|
||||
|
||||
@@ -552,25 +562,49 @@ AtticaManager::upgradeResolver( const Content& resolver )
|
||||
|
||||
|
||||
void
|
||||
AtticaManager::resolverDownloadFinished ( BaseJob* j )
|
||||
AtticaManager::resolverDownloadFinished ( QNetworkReply *j )
|
||||
{
|
||||
ItemJob< DownloadItem >* job = static_cast< ItemJob< DownloadItem >* >( j );
|
||||
Q_ASSERT( j );
|
||||
if ( !j )
|
||||
return;
|
||||
|
||||
if ( job->metadata().error() == Attica::Metadata::NoError )
|
||||
if ( j->error() == QNetworkReply::NoError )
|
||||
{
|
||||
DownloadItem item = job->result();
|
||||
QUrl url = item.url();
|
||||
// download the resolver itself :)
|
||||
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
|
||||
connect( reply, SIGNAL( finished() ), this, SLOT( payloadFetched() ) );
|
||||
reply->setProperty( "resolverId", job->property( "resolverId" ) );
|
||||
reply->setProperty( "createAccount", job->property( "createAccount" ) );
|
||||
reply->setProperty( "handler", job->property( "handler" ) );
|
||||
reply->setProperty( "binarySignature", job->property( "binarySignature" ) );
|
||||
QDomDocument doc;
|
||||
doc.setContent( j );
|
||||
|
||||
const QDomNodeList nodes = doc.documentElement().elementsByTagName( "downloadlink" );
|
||||
if ( nodes.length() < 1 )
|
||||
{
|
||||
tLog() << "Found no download link for resolver:" << doc.toString();
|
||||
return;
|
||||
}
|
||||
|
||||
QUrl url( nodes.item( 0 ).toElement().text() );
|
||||
// download the resolver itself :)
|
||||
tDebug() << "Downloading resolver from url:" << url.toString();
|
||||
|
||||
const QDomNodeList signatures = doc.documentElement().elementsByTagName( "signature" );
|
||||
|
||||
// Use the original signature provided
|
||||
QString signature = j->property( "binarySignature" ).toString();
|
||||
if ( signatures.size() > 0 )
|
||||
{
|
||||
// THis download has an overriding signature. Take that one instead
|
||||
const QString sig = signatures.item( 0 ).toElement().text();
|
||||
tLog() << "Found overridden signature in binary download:" << sig;
|
||||
signature = sig;
|
||||
}
|
||||
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
|
||||
connect( reply, SIGNAL( finished() ), this, SLOT( payloadFetched() ) );
|
||||
reply->setProperty( "resolverId", j->property( "resolverId" ) );
|
||||
reply->setProperty( "createAccount", j->property( "createAccount" ) );
|
||||
reply->setProperty( "handler", j->property( "handler" ) );
|
||||
reply->setProperty( "binarySignature", signature );
|
||||
}
|
||||
else
|
||||
{
|
||||
tLog() << "Failed to do resolver download job!" << job->metadata().error();
|
||||
tLog() << "Failed to do resolver download job!" << j->errorString() << j->error();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -703,19 +737,6 @@ AtticaManager::uninstallResolver( const Content& resolver )
|
||||
|
||||
m_resolverStates[ resolver.id() ].state = Uninstalled;
|
||||
TomahawkSettingsGui::instanceGui()->setAtticaResolverState( resolver.id(), Uninstalled );
|
||||
|
||||
// remove account as well
|
||||
QList< Tomahawk::Accounts::Account* > accounts = Tomahawk::Accounts::AccountManager::instance()->accounts( Tomahawk::Accounts::ResolverType );
|
||||
foreach ( Tomahawk::Accounts::Account* account, accounts )
|
||||
{
|
||||
if ( Tomahawk::Accounts::AtticaResolverAccount* atticaAccount = qobject_cast< Tomahawk::Accounts::AtticaResolverAccount* >( account ) )
|
||||
{
|
||||
if ( atticaAccount->atticaId() == resolver.id() ) // this is the account we want to remove
|
||||
{
|
||||
Tomahawk::Accounts::AccountManager::instance()->removeAccount( atticaAccount );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doResolverRemove( resolver.id() );
|
||||
|
@@ -132,7 +132,7 @@ private slots:
|
||||
void categoriesReturned( Attica::BaseJob* );
|
||||
void resolversList( Attica::BaseJob* );
|
||||
void binaryResolversList( Attica::BaseJob* );
|
||||
void resolverDownloadFinished( Attica::BaseJob* );
|
||||
void resolverDownloadFinished( QNetworkReply* );
|
||||
void payloadFetched();
|
||||
|
||||
void loadPixmapsFromCache();
|
||||
@@ -144,6 +144,7 @@ private slots:
|
||||
private:
|
||||
void doResolverRemove( const QString& id ) const;
|
||||
void doInstallResolver( const Attica::Content& resolver, bool autoCreate, Tomahawk::Accounts::AtticaResolverAccount* handler );
|
||||
QString hostname() const;
|
||||
|
||||
Attica::ProviderManager m_manager;
|
||||
|
||||
|
@@ -17,7 +17,6 @@ add_definitions( -DQT_SHARED )
|
||||
add_definitions( -DDLLEXPORT_PRO )
|
||||
add_definitions( -DQT_SHAREDPOINTER_TRACK_POINTERS )
|
||||
|
||||
|
||||
set( libGuiSources
|
||||
ActionCollection.cpp
|
||||
|
||||
@@ -192,6 +191,7 @@ set( libSources
|
||||
accounts/spotify/SpotifyAccount.cpp
|
||||
accounts/spotify/SpotifyAccountConfig.cpp
|
||||
accounts/spotify/SpotifyPlaylistUpdater.cpp
|
||||
accounts/spotify/SpotifyInfoPlugin.cpp
|
||||
|
||||
accounts/lastfm/LastFmAccount.cpp
|
||||
accounts/lastfm/LastFmConfig.cpp
|
||||
@@ -327,8 +327,7 @@ include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/.
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${QT_INCLUDE_DIR}
|
||||
${QJSON_INCLUDE_DIR}
|
||||
${LIBECHONEST_INCLUDE_DIR}
|
||||
${LIBECHONEST_INCLUDE_DIR}/..
|
||||
${ECHONEST_INCLUDE_DIR}
|
||||
${LIBLASTFM_INCLUDE_DIRS}
|
||||
${LIBLASTFM_INCLUDE_DIRS}/..
|
||||
${CLUCENE_INCLUDE_DIRS}
|
||||
@@ -380,6 +379,8 @@ IF( APPLE )
|
||||
FIND_LIBRARY( SCRIPTINGBRIDGE_LIBRARY ScriptingBridge )
|
||||
MARK_AS_ADVANCED( COREAUDIO_LIBRARY COREFOUNDATION_LIBRARY FOUNDATION_LIBRARY SCRIPTINGBRIDGE_LIBRARY )
|
||||
|
||||
SET( CMAKE_SHARED_LINKER_FLAGS "-headerpad_max_install_names ${CMAKE_SHARED_LINKER_FLAGS}" )
|
||||
|
||||
SET( libSources ${libSources}
|
||||
utils/TomahawkUtils_Mac.mm
|
||||
mac/FileHelpers.mm
|
||||
@@ -438,7 +439,7 @@ TARGET_LINK_LIBRARIES( tomahawklib
|
||||
${PHONON_LIBS}
|
||||
${TAGLIB_LIBRARIES}
|
||||
${CLUCENE_LIBRARIES}
|
||||
${LIBECHONEST_LIBRARY}
|
||||
${ECHONEST_LIBRARIES}
|
||||
${QT_QTSQL_LIBRARY}
|
||||
${QT_QTUITOOLS_LIBRARY}
|
||||
${QT_QTGUI_LIBRARY}
|
||||
|
@@ -85,9 +85,9 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
|
||||
if ( m_supportedActions & ActionStopAfter && itemCount() == 1 )
|
||||
{
|
||||
if ( AudioEngine::instance()->stopAfterTrack() == queries.first() )
|
||||
m_sigmap->setMapping( addAction( tr( "&Continue Playback after this Track" ) ), ActionStopAfter );
|
||||
m_sigmap->setMapping( addAction( tr( "Continue Playback after this &Track" ) ), ActionStopAfter );
|
||||
else
|
||||
m_sigmap->setMapping( addAction( tr( "&Stop Playback after this Track" ) ), ActionStopAfter );
|
||||
m_sigmap->setMapping( addAction( tr( "Stop Playback after this &Track" ) ), ActionStopAfter );
|
||||
}
|
||||
|
||||
addSeparator();
|
||||
@@ -122,6 +122,9 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
|
||||
void
|
||||
ContextMenu::setQuery( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
if ( query.isNull() )
|
||||
return;
|
||||
|
||||
QList<query_ptr> queries;
|
||||
queries << query;
|
||||
setQueries( queries );
|
||||
@@ -151,8 +154,8 @@ ContextMenu::setAlbums( const QList<Tomahawk::album_ptr>& albums )
|
||||
|
||||
addSeparator();
|
||||
|
||||
/* if ( m_supportedActions & ActionCopyLink && itemCount() == 1 )
|
||||
m_sigmap->setMapping( addAction( tr( "Copy Album &Link" ) ), ActionCopyLink ); */
|
||||
if ( m_supportedActions & ActionCopyLink && itemCount() == 1 )
|
||||
m_sigmap->setMapping( addAction( tr( "Copy Album &Link" ) ), ActionCopyLink );
|
||||
|
||||
foreach ( QAction* action, actions() )
|
||||
{
|
||||
@@ -193,8 +196,8 @@ ContextMenu::setArtists( const QList<Tomahawk::artist_ptr>& artists )
|
||||
|
||||
addSeparator();
|
||||
|
||||
/* if ( m_supportedActions & ActionCopyLink && itemCount() == 1 )
|
||||
m_sigmap->setMapping( addAction( tr( "Copy Artist &Link" ) ), ActionCopyLink ); */
|
||||
if ( m_supportedActions & ActionCopyLink && itemCount() == 1 )
|
||||
m_sigmap->setMapping( addAction( tr( "Copy Artist &Link" ) ), ActionCopyLink );
|
||||
|
||||
foreach ( QAction* action, actions() )
|
||||
{
|
||||
@@ -224,7 +227,7 @@ ContextMenu::onTriggered( int action )
|
||||
case ActionCopyLink:
|
||||
copyLink();
|
||||
break;
|
||||
|
||||
|
||||
case ActionPage:
|
||||
openPage();
|
||||
break;
|
||||
@@ -252,15 +255,15 @@ ContextMenu::addToQueue()
|
||||
{
|
||||
foreach ( const query_ptr& query, m_queries )
|
||||
{
|
||||
ViewManager::instance()->queue()->model()->append( query );
|
||||
ViewManager::instance()->queue()->model()->appendQuery( query );
|
||||
}
|
||||
foreach ( const artist_ptr& artist, m_artists )
|
||||
{
|
||||
ViewManager::instance()->queue()->model()->append( artist );
|
||||
ViewManager::instance()->queue()->model()->appendArtist( artist );
|
||||
}
|
||||
foreach ( const album_ptr& album, m_albums )
|
||||
{
|
||||
ViewManager::instance()->queue()->model()->append( album );
|
||||
ViewManager::instance()->queue()->model()->appendAlbum( album );
|
||||
}
|
||||
|
||||
ViewManager::instance()->showQueue();
|
||||
@@ -274,6 +277,14 @@ ContextMenu::copyLink()
|
||||
{
|
||||
GlobalActionManager::instance()->copyToClipboard( m_queries.first() );
|
||||
}
|
||||
else if ( m_albums.count() )
|
||||
{
|
||||
GlobalActionManager::instance()->copyOpenLink( m_albums.first() );
|
||||
}
|
||||
else if ( m_artists.count() )
|
||||
{
|
||||
GlobalActionManager::instance()->copyOpenLink( m_artists.first() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -298,12 +309,15 @@ ContextMenu::openPage()
|
||||
void
|
||||
ContextMenu::onSocialActionsLoaded()
|
||||
{
|
||||
if ( m_queries.first()->loved() )
|
||||
if ( m_queries.isEmpty() || m_queries.first().isNull() )
|
||||
return;
|
||||
|
||||
if ( m_loveAction && m_queries.first()->loved() )
|
||||
{
|
||||
m_loveAction->setText( tr( "Un-&Love" ) );
|
||||
m_loveAction->setIcon( QIcon( RESPATH "images/not-loved.png" ) );
|
||||
}
|
||||
else
|
||||
else if ( m_loveAction )
|
||||
{
|
||||
m_loveAction->setText( tr( "&Love" ) );
|
||||
m_loveAction->setIcon( QIcon( RESPATH "images/loved.png" ) );
|
||||
|
@@ -425,12 +425,18 @@ DropJob::tracksFromMixedData( const QMimeData *data )
|
||||
QDataStream singleStream( &singleData, QIODevice::WriteOnly );
|
||||
|
||||
QMimeData singleMimeData;
|
||||
if ( mimeType == "application/tomahawk.query.list" || mimeType == "application/tomahawk.result.list" )
|
||||
if ( mimeType == "application/tomahawk.query.list" )
|
||||
{
|
||||
qlonglong query;
|
||||
stream >> query;
|
||||
singleStream << query;
|
||||
}
|
||||
else if ( mimeType == "application/tomahawk.result.list" )
|
||||
{
|
||||
qlonglong result;
|
||||
stream >> result;
|
||||
singleStream << result;
|
||||
}
|
||||
else if ( mimeType == "application/tomahawk.metadata.album" )
|
||||
{
|
||||
QString artist;
|
||||
@@ -699,8 +705,21 @@ DropJob::removeDuplicates()
|
||||
foreach ( const Tomahawk::query_ptr& item, m_resultList )
|
||||
{
|
||||
bool contains = false;
|
||||
Q_ASSERT( !item.isNull() );
|
||||
if ( item.isNull() )
|
||||
{
|
||||
m_resultList.removeOne( item );
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach( const Tomahawk::query_ptr &tmpItem, list )
|
||||
{
|
||||
if ( tmpItem.isNull() )
|
||||
{
|
||||
list.removeOne( tmpItem );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( item->album() == tmpItem->album()
|
||||
&& item->artist() == tmpItem->artist()
|
||||
&& item->track() == tmpItem->track() )
|
||||
@@ -726,10 +745,18 @@ DropJob::removeRemoteSources()
|
||||
QList< Tomahawk::query_ptr > list;
|
||||
foreach ( const Tomahawk::query_ptr& item, m_resultList )
|
||||
{
|
||||
Q_ASSERT( !item.isNull() );
|
||||
if ( item.isNull() )
|
||||
{
|
||||
m_resultList.removeOne( item );
|
||||
continue;
|
||||
}
|
||||
|
||||
bool hasLocalSource = false;
|
||||
foreach ( const Tomahawk::result_ptr& result, item->results() )
|
||||
{
|
||||
if ( !result->collection()->source().isNull() && result->collection()->source()->isLocal() )
|
||||
if ( !result->collection().isNull() && !result->collection()->source().isNull() &&
|
||||
!result->collection()->source().isNull() && result->collection()->source()->isLocal() )
|
||||
hasLocalSource = true;
|
||||
}
|
||||
if ( hasLocalSource )
|
||||
|
@@ -553,7 +553,7 @@ GlobalActionManager::handleOpenCommand( const QUrl& url )
|
||||
void
|
||||
GlobalActionManager::handleOpenTrack( const query_ptr& q )
|
||||
{
|
||||
ViewManager::instance()->queue()->model()->append( q );
|
||||
ViewManager::instance()->queue()->model()->appendQuery( q );
|
||||
ViewManager::instance()->showQueue();
|
||||
|
||||
if ( !AudioEngine::instance()->isPlaying() && !AudioEngine::instance()->isPaused() )
|
||||
@@ -570,7 +570,7 @@ GlobalActionManager::handleOpenTracks( const QList< query_ptr >& queries )
|
||||
if ( queries.isEmpty() )
|
||||
return;
|
||||
|
||||
ViewManager::instance()->queue()->model()->append( queries );
|
||||
ViewManager::instance()->queue()->model()->appendQueries( queries );
|
||||
ViewManager::instance()->showQueue();
|
||||
|
||||
if ( !AudioEngine::instance()->isPlaying() && !AudioEngine::instance()->isPaused() )
|
||||
@@ -617,16 +617,15 @@ GlobalActionManager::doQueueAdd( const QStringList& parts, const QList< QPair< Q
|
||||
{
|
||||
if ( parts.size() && parts[ 0 ] == "track" )
|
||||
{
|
||||
|
||||
if ( queueSpotify( parts, queryItems ) )
|
||||
return true;
|
||||
else if ( queueRdio( parts, queryItems ) )
|
||||
return true;
|
||||
|
||||
QPair< QString, QString > pair;
|
||||
|
||||
QString title, artist, album, urlStr;
|
||||
foreach ( pair, queryItems ) {
|
||||
foreach ( pair, queryItems )
|
||||
{
|
||||
pair.second = pair.second.replace( "+", " " ); // QUrl::queryItems doesn't decode + to a space :(
|
||||
if ( pair.first == "title" )
|
||||
title = pair.second;
|
||||
@@ -642,9 +641,12 @@ GlobalActionManager::doQueueAdd( const QStringList& parts, const QList< QPair< Q
|
||||
{
|
||||
// an individual; query to add to queue
|
||||
query_ptr q = Query::get( artist, title, album, uuid(), false );
|
||||
if ( q.isNull() )
|
||||
return false;
|
||||
|
||||
if ( !urlStr.isEmpty() )
|
||||
q->setResultHint( urlStr );
|
||||
Pipeline::instance()->resolve( q, true );
|
||||
Pipeline::instance()->resolve( q );
|
||||
|
||||
handleOpenTrack( q );
|
||||
return true;
|
||||
@@ -666,11 +668,13 @@ GlobalActionManager::doQueueAdd( const QStringList& parts, const QList< QPair< Q
|
||||
{ // give it a web result hint
|
||||
QFileInfo info( track.path() );
|
||||
query_ptr q = Query::get( QString(), info.baseName(), QString(), uuid(), false );
|
||||
if ( q.isNull() )
|
||||
continue;
|
||||
|
||||
q->setResultHint( track.toString() );
|
||||
Pipeline::instance()->resolve( q );
|
||||
|
||||
Pipeline::instance()->resolve( q, true );
|
||||
|
||||
ViewManager::instance()->queue()->model()->append( q );
|
||||
ViewManager::instance()->queue()->model()->appendQuery( q );
|
||||
ViewManager::instance()->showQueue();
|
||||
}
|
||||
return true;
|
||||
@@ -1067,6 +1071,9 @@ GlobalActionManager::handlePlayCommand( const QUrl& url )
|
||||
}
|
||||
|
||||
query_ptr q = Query::get( artist, title, album );
|
||||
if ( q.isNull() )
|
||||
return false;
|
||||
|
||||
if ( !urlStr.isEmpty() )
|
||||
q->setResultHint( urlStr );
|
||||
|
||||
@@ -1155,18 +1162,25 @@ bool GlobalActionManager::handleBookmarkCommand(const QUrl& url)
|
||||
urlStr = pair.second;
|
||||
}
|
||||
query_ptr q = Query::get( artist, title, album );
|
||||
if ( q.isNull() )
|
||||
return false;
|
||||
|
||||
if ( !urlStr.isEmpty() )
|
||||
q->setResultHint( urlStr );
|
||||
Pipeline::instance()->resolve( q, true );
|
||||
Pipeline::instance()->resolve( q );
|
||||
|
||||
// now we add it to the special "bookmarks" playlist, creating it if it doesn't exist. if nothing is playing, start playing the track
|
||||
QSharedPointer< LocalCollection > col = SourceList::instance()->getLocal()->collection().dynamicCast< LocalCollection >();
|
||||
playlist_ptr bookmarkpl = col->bookmarksPlaylist();
|
||||
if ( bookmarkpl.isNull() ) { // create it and do the deed then
|
||||
if ( bookmarkpl.isNull() )
|
||||
{
|
||||
// create it and do the deed then
|
||||
m_waitingToBookmark = q;
|
||||
col->createBookmarksPlaylist();
|
||||
connect( col.data(), SIGNAL( bookmarkPlaylistCreated( Tomahawk::playlist_ptr ) ), this, SLOT( bookmarkPlaylistCreated( Tomahawk::playlist_ptr ) ), Qt::UniqueConnection );
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
doBookmark( bookmarkpl, q );
|
||||
}
|
||||
|
||||
@@ -1343,7 +1357,7 @@ GlobalActionManager::waitingForResolved( bool /* success */ )
|
||||
AudioEngine::instance()->playItem( AudioEngine::instance()->playlist(), m_waitingToPlay->results().first() );
|
||||
else
|
||||
{
|
||||
ViewManager::instance()->queue()->model()->append( m_waitingToPlay );
|
||||
ViewManager::instance()->queue()->model()->appendQuery( m_waitingToPlay );
|
||||
AudioEngine::instance()->play();
|
||||
}
|
||||
}
|
||||
|
@@ -272,9 +272,16 @@ Pipeline::reportResults( QID qid, const QList< result_ptr >& results )
|
||||
}
|
||||
const query_ptr& q = m_qids.value( qid );
|
||||
|
||||
Q_ASSERT( !q.isNull() );
|
||||
if ( q.isNull() )
|
||||
return;
|
||||
|
||||
QList< result_ptr > cleanResults;
|
||||
foreach ( const result_ptr& r, results )
|
||||
{
|
||||
if ( r.isNull() )
|
||||
continue;
|
||||
|
||||
float score = q->howSimilar( r );
|
||||
r->setScore( score );
|
||||
if ( !q->isFullTextQuery() && score < MINSCORE )
|
||||
|
@@ -54,6 +54,7 @@ PlaylistEntry::setQueryVariant( const QVariant& v )
|
||||
QString artist = m.value( "artist" ).toString();
|
||||
QString album = m.value( "album" ).toString();
|
||||
QString track = m.value( "track" ).toString();
|
||||
|
||||
m_query = Tomahawk::Query::get( artist, track, album );
|
||||
}
|
||||
|
||||
|
@@ -59,10 +59,11 @@ public:
|
||||
PlaylistEntry();
|
||||
virtual ~PlaylistEntry();
|
||||
|
||||
bool isValid() const { return !m_query.isNull(); }
|
||||
|
||||
void setQuery( const Tomahawk::query_ptr& q );
|
||||
const Tomahawk::query_ptr& query() const;
|
||||
|
||||
// I wish Qt did this for me once i specified the Q_PROPERTIES:
|
||||
void setQueryVariant( const QVariant& v );
|
||||
QVariant queryVariant() const;
|
||||
|
||||
|
@@ -29,6 +29,7 @@ using namespace Tomahawk;
|
||||
PlaylistInterface::PlaylistInterface ()
|
||||
: QObject()
|
||||
, m_latchMode( PlaylistModes::StayOnSong )
|
||||
, m_finished( false )
|
||||
{
|
||||
m_id = uuid();
|
||||
}
|
||||
|
@@ -40,6 +40,7 @@ public:
|
||||
const QString id() { return m_id; }
|
||||
|
||||
virtual QList< Tomahawk::query_ptr > tracks() = 0;
|
||||
virtual bool isFinished() const { return m_finished; }
|
||||
|
||||
virtual int unfilteredTrackCount() const = 0;
|
||||
virtual int trackCount() const = 0;
|
||||
@@ -91,7 +92,8 @@ protected:
|
||||
virtual QList<Tomahawk::query_ptr> filterTracks( const QList<Tomahawk::query_ptr>& queries );
|
||||
|
||||
PlaylistModes::LatchMode m_latchMode;
|
||||
|
||||
bool m_finished;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY( PlaylistInterface )
|
||||
|
||||
|
@@ -82,6 +82,9 @@ PlaybackLog::PlaybackLog( const PlaybackLog& other )
|
||||
query_ptr
|
||||
Query::get( const QString& artist, const QString& track, const QString& album, const QID& qid, bool autoResolve )
|
||||
{
|
||||
if ( artist.trimmed().isEmpty() || track.trimmed().isEmpty() )
|
||||
return query_ptr();
|
||||
|
||||
if ( qid.isEmpty() )
|
||||
autoResolve = false;
|
||||
|
||||
@@ -98,6 +101,8 @@ Query::get( const QString& artist, const QString& track, const QString& album, c
|
||||
query_ptr
|
||||
Query::get( const QString& query, const QID& qid )
|
||||
{
|
||||
Q_ASSERT( !query.trimmed().isEmpty() );
|
||||
|
||||
query_ptr q = query_ptr( new Query( query, qid ), &QObject::deleteLater );
|
||||
q->setWeakRef( q.toWeakRef() );
|
||||
|
||||
@@ -170,14 +175,14 @@ Query::updateSortNames()
|
||||
if ( isFullTextQuery() )
|
||||
{
|
||||
m_artistSortname = DatabaseImpl::sortname( m_fullTextQuery, true );
|
||||
m_composerSortName = DatabaseImpl::sortname( m_composer, true );
|
||||
m_composerSortname = DatabaseImpl::sortname( m_composer, true );
|
||||
m_albumSortname = DatabaseImpl::sortname( m_fullTextQuery );
|
||||
m_trackSortname = m_albumSortname;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_artistSortname = DatabaseImpl::sortname( m_artist, true );
|
||||
m_composerSortName = DatabaseImpl::sortname( m_composer, true );
|
||||
m_composerSortname = DatabaseImpl::sortname( m_composer, true );
|
||||
m_albumSortname = DatabaseImpl::sortname( m_album );
|
||||
m_trackSortname = DatabaseImpl::sortname( m_track );
|
||||
}
|
||||
@@ -189,7 +194,7 @@ Query::displayQuery() const
|
||||
{
|
||||
if ( !results().isEmpty() )
|
||||
return results().first()->toQuery();
|
||||
|
||||
|
||||
return m_ownRef.toStrongRef();
|
||||
}
|
||||
|
||||
@@ -223,6 +228,7 @@ Query::addResults( const QList< Tomahawk::result_ptr >& newresults )
|
||||
|
||||
checkResults();
|
||||
emit resultsAdded( newresults );
|
||||
emit resultsChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -287,6 +293,7 @@ Query::removeResult( const Tomahawk::result_ptr& result )
|
||||
|
||||
emit resultsRemoved( result );
|
||||
checkResults();
|
||||
emit resultsChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -491,15 +498,20 @@ Query::toString() const
|
||||
float
|
||||
Query::howSimilar( const Tomahawk::result_ptr& r )
|
||||
{
|
||||
Q_ASSERT( !r->artist().isNull() );
|
||||
Q_ASSERT( !r->album().isNull() );
|
||||
if ( r->artist().isNull() || r->album().isNull() )
|
||||
return 0.0;
|
||||
|
||||
// result values
|
||||
const QString rArtistname = r->artist()->sortname();
|
||||
const QString rAlbumname = DatabaseImpl::sortname( r->album()->name() );
|
||||
const QString rAlbumname = r->album()->sortname();
|
||||
const QString rTrackname = DatabaseImpl::sortname( r->track() );
|
||||
|
||||
// normal edit distance
|
||||
int artdist = levenshtein( m_artistSortname, rArtistname );
|
||||
int albdist = levenshtein( m_albumSortname, rAlbumname );
|
||||
int trkdist = levenshtein( m_trackSortname, rTrackname );
|
||||
int artdist = TomahawkUtils::levenshtein( m_artistSortname, rArtistname );
|
||||
int albdist = TomahawkUtils::levenshtein( m_albumSortname, rAlbumname );
|
||||
int trkdist = TomahawkUtils::levenshtein( m_trackSortname, rTrackname );
|
||||
|
||||
// max length of name
|
||||
int mlart = qMax( m_artistSortname.length(), rArtistname.length() );
|
||||
@@ -516,7 +528,7 @@ Query::howSimilar( const Tomahawk::result_ptr& r )
|
||||
const QString artistTrackname = DatabaseImpl::sortname( fullTextQuery() );
|
||||
const QString rArtistTrackname = DatabaseImpl::sortname( r->artist()->name() + " " + r->track() );
|
||||
|
||||
int atrdist = levenshtein( artistTrackname, rArtistTrackname );
|
||||
int atrdist = TomahawkUtils::levenshtein( artistTrackname, rArtistTrackname );
|
||||
int mlatr = qMax( artistTrackname.length(), rArtistTrackname.length() );
|
||||
float dcatr = (float)( mlatr - atrdist ) / mlatr;
|
||||
|
||||
@@ -566,7 +578,7 @@ Query::playbackHistory( const Tomahawk::source_ptr& source ) const
|
||||
history << log;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return history;
|
||||
}
|
||||
|
||||
@@ -588,7 +600,7 @@ Query::playbackCount( const source_ptr& source )
|
||||
if ( source.isNull() || log.source == source )
|
||||
count++;
|
||||
}
|
||||
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -596,6 +608,9 @@ Query::playbackCount( const source_ptr& source )
|
||||
void
|
||||
Query::loadSocialActions()
|
||||
{
|
||||
if ( m_socialActionsLoaded )
|
||||
return;
|
||||
|
||||
m_socialActionsLoaded = true;
|
||||
query_ptr q = m_ownRef.toStrongRef();
|
||||
|
||||
@@ -670,12 +685,12 @@ Query::setLoved( bool loved )
|
||||
trackInfo["album"] = album();
|
||||
|
||||
loveInfo[ "trackinfo" ] = QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( trackInfo );
|
||||
|
||||
|
||||
Tomahawk::InfoSystem::InfoPushData pushData ( id(),
|
||||
( loved ? Tomahawk::InfoSystem::InfoLove : Tomahawk::InfoSystem::InfoUnLove ),
|
||||
loveInfo,
|
||||
Tomahawk::InfoSystem::PushShortUrlFlag );
|
||||
|
||||
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( pushData );
|
||||
|
||||
DatabaseCommand_SocialAction* cmd = new DatabaseCommand_SocialAction( q, QString( "Love" ), loved ? QString( "true" ) : QString( "false" ) );
|
||||
@@ -783,10 +798,10 @@ Query::coverLoaded() const
|
||||
{
|
||||
if ( m_albumPtr.isNull() )
|
||||
return false;
|
||||
|
||||
|
||||
if ( m_albumPtr->coverLoaded() && !m_albumPtr->cover( QSize( 0, 0 ) ).isNull() )
|
||||
return true;
|
||||
|
||||
|
||||
return m_artistPtr->coverLoaded();
|
||||
}
|
||||
|
||||
@@ -809,7 +824,7 @@ Query::similarTracks() const
|
||||
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( trackInfo );
|
||||
requestData.type = Tomahawk::InfoSystem::InfoTrackSimilars;
|
||||
requestData.requestId = TomahawkUtils::infosystemRequestId();
|
||||
|
||||
|
||||
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
|
||||
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
|
||||
@@ -821,7 +836,7 @@ Query::similarTracks() const
|
||||
m_infoJobs++;
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
|
||||
}
|
||||
|
||||
|
||||
return m_similarTracks;
|
||||
}
|
||||
|
||||
@@ -842,7 +857,7 @@ Query::lyrics() const
|
||||
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( trackInfo );
|
||||
requestData.type = Tomahawk::InfoSystem::InfoTrackLyrics;
|
||||
requestData.requestId = TomahawkUtils::infosystemRequestId();
|
||||
|
||||
|
||||
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
|
||||
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
|
||||
@@ -854,7 +869,7 @@ Query::lyrics() const
|
||||
m_infoJobs++;
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
|
||||
}
|
||||
|
||||
|
||||
return m_lyrics;
|
||||
}
|
||||
|
||||
@@ -871,7 +886,7 @@ Query::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVaria
|
||||
case InfoSystem::InfoTrackLyrics:
|
||||
{
|
||||
m_lyrics = output.value< QVariant >().toString().split( "\n" );
|
||||
|
||||
|
||||
m_lyricsLoaded = true;
|
||||
emit lyricsLoaded();
|
||||
break;
|
||||
@@ -887,7 +902,7 @@ Query::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVaria
|
||||
m_similarTracks << Query::get( artists.at( i ), tracks.at( i ), QString(), uuid(), false );
|
||||
}
|
||||
Pipeline::instance()->resolve( m_similarTracks );
|
||||
|
||||
|
||||
m_simTracksLoaded = true;
|
||||
emit similarTracksLoaded();
|
||||
|
||||
@@ -917,83 +932,3 @@ Query::infoSystemFinished( QString target )
|
||||
|
||||
emit updated();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Query::levenshtein( const QString& source, const QString& target )
|
||||
{
|
||||
// Step 1
|
||||
const int n = source.length();
|
||||
const int m = target.length();
|
||||
|
||||
if ( n == 0 )
|
||||
return m;
|
||||
if ( m == 0 )
|
||||
return n;
|
||||
|
||||
// Good form to declare a TYPEDEF
|
||||
typedef QVector< QVector<int> > Tmatrix;
|
||||
Tmatrix matrix;
|
||||
matrix.resize( n + 1 );
|
||||
|
||||
// Size the vectors in the 2.nd dimension. Unfortunately C++ doesn't
|
||||
// allow for allocation on declaration of 2.nd dimension of vec of vec
|
||||
for ( int i = 0; i <= n; i++ )
|
||||
{
|
||||
QVector<int> tmp;
|
||||
tmp.resize( m + 1 );
|
||||
matrix.insert( i, tmp );
|
||||
}
|
||||
|
||||
// Step 2
|
||||
for ( int i = 0; i <= n; i++ )
|
||||
matrix[i][0] = i;
|
||||
for ( int j = 0; j <= m; j++ )
|
||||
matrix[0][j] = j;
|
||||
|
||||
// Step 3
|
||||
for ( int i = 1; i <= n; i++ )
|
||||
{
|
||||
const QChar s_i = source[i - 1];
|
||||
|
||||
// Step 4
|
||||
for ( int j = 1; j <= m; j++ )
|
||||
{
|
||||
const QChar t_j = target[j - 1];
|
||||
|
||||
// Step 5
|
||||
int cost;
|
||||
if ( s_i == t_j )
|
||||
cost = 0;
|
||||
else
|
||||
cost = 1;
|
||||
|
||||
// Step 6
|
||||
const int above = matrix[i - 1][j];
|
||||
const int left = matrix[i][j - 1];
|
||||
const int diag = matrix[i - 1][j - 1];
|
||||
|
||||
int cell = ( ( ( left + 1 ) > ( diag + cost ) ) ? diag + cost : left + 1 );
|
||||
if ( above + 1 < cell )
|
||||
cell = above + 1;
|
||||
|
||||
// Step 6A: Cover transposition, in addition to deletion,
|
||||
// insertion and substitution. This step is taken from:
|
||||
// Berghel, Hal ; Roach, David : "An Extension of Ukkonen's
|
||||
// Enhanced Dynamic Programming ASM Algorithm"
|
||||
// (http://www.acm.org/~hlb/publications/asm/asm.html)
|
||||
if ( i > 2 && j > 2 )
|
||||
{
|
||||
int trans = matrix[i - 2][j - 2] + 1;
|
||||
|
||||
if ( source[ i - 2 ] != t_j ) trans++;
|
||||
if ( s_i != target[ j - 2 ] ) trans++;
|
||||
if ( cell > trans ) cell = trans;
|
||||
}
|
||||
matrix[i][j] = cell;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 7
|
||||
return matrix[n][m];
|
||||
}
|
||||
|
@@ -97,7 +97,7 @@ public:
|
||||
QID id() const;
|
||||
|
||||
/// sorter for list of results
|
||||
static bool resultSorter( const result_ptr &left, const result_ptr& right );
|
||||
static bool resultSorter( const result_ptr& left, const result_ptr& right );
|
||||
|
||||
/// true when a perfect result has been found (score of 1.0)
|
||||
bool solved() const { return m_solved; }
|
||||
@@ -129,6 +129,7 @@ public:
|
||||
|
||||
QString resultHint() const { return m_resultHint; }
|
||||
QString artistSortname() const { return m_artistSortname; }
|
||||
QString composerSortname() const { return m_composerSortname; }
|
||||
QString albumSortname() const { return m_albumSortname; }
|
||||
QString trackSortname() const { return m_trackSortname; }
|
||||
|
||||
@@ -139,7 +140,7 @@ public:
|
||||
int duration() const { return m_duration; }
|
||||
unsigned int albumpos() const { return m_albumpos; }
|
||||
unsigned int discnumber() const { return m_discnumber; }
|
||||
|
||||
|
||||
query_ptr displayQuery() const;
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
@@ -220,7 +221,6 @@ private:
|
||||
void checkResults();
|
||||
|
||||
void updateSortNames();
|
||||
static int levenshtein( const QString& source, const QString& target );
|
||||
|
||||
void parseSocialActions();
|
||||
|
||||
@@ -233,7 +233,7 @@ private:
|
||||
mutable QID m_qid;
|
||||
|
||||
QString m_artistSortname;
|
||||
QString m_composerSortName;
|
||||
QString m_composerSortname;
|
||||
QString m_albumSortname;
|
||||
QString m_trackSortname;
|
||||
|
||||
@@ -266,10 +266,10 @@ private:
|
||||
|
||||
bool m_simTracksLoaded;
|
||||
QList<Tomahawk::query_ptr> m_similarTracks;
|
||||
|
||||
|
||||
bool m_lyricsLoaded;
|
||||
QStringList m_lyrics;
|
||||
|
||||
|
||||
mutable int m_infoJobs;
|
||||
};
|
||||
|
||||
|
@@ -207,6 +207,10 @@ Result::toQuery()
|
||||
if ( m_query.isNull() )
|
||||
{
|
||||
m_query = Tomahawk::Query::get( artist()->name(), track(), album()->name() );
|
||||
|
||||
if ( m_query.isNull() )
|
||||
return query_ptr();
|
||||
|
||||
m_query->setAlbumPos( albumpos() );
|
||||
m_query->setDiscNumber( discnumber() );
|
||||
m_query->setDuration( duration() );
|
||||
|
@@ -36,6 +36,7 @@ class DatabaseCommand_LogPlayback;
|
||||
class DatabaseCommand_SocialAction;
|
||||
class DatabaseCommand_UpdateSearchIndex;
|
||||
class DatabaseCommand_DeleteFiles;
|
||||
class MusicScanner;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
@@ -50,6 +51,7 @@ friend class ::DatabaseCommand_LogPlayback;
|
||||
friend class ::DatabaseCommand_SocialAction;
|
||||
friend class ::DatabaseCommand_AddFiles;
|
||||
friend class ::DatabaseCommand_DeleteFiles;
|
||||
friend class ::MusicScanner;
|
||||
|
||||
public:
|
||||
enum AvatarStyle { Original, FancyStyle };
|
||||
|
@@ -305,7 +305,7 @@ ViewManager::show( const Tomahawk::collection_ptr& collection )
|
||||
view = new TreeView();
|
||||
TreeModel* model = new TreeModel();
|
||||
view->setTreeModel( model );
|
||||
|
||||
|
||||
if ( collection && collection->source()->isLocal() )
|
||||
view->setEmptyTip( tr( "After you have scanned your music collection you will find your tracks right here." ) );
|
||||
else
|
||||
@@ -483,7 +483,7 @@ ViewManager::showRecentPlaysPage()
|
||||
{
|
||||
PlaylistView* pv = new PlaylistView( m_widget );
|
||||
|
||||
RecentlyPlayedModel* raModel = new RecentlyPlayedModel( source_ptr(), pv );
|
||||
RecentlyPlayedModel* raModel = new RecentlyPlayedModel( pv );
|
||||
raModel->setTitle( tr( "Recently Played Tracks" ) );
|
||||
raModel->setDescription( tr( "Recently played tracks from all your friends" ) );
|
||||
raModel->setStyle( PlayableModel::Large );
|
||||
@@ -493,6 +493,7 @@ ViewManager::showRecentPlaysPage()
|
||||
pv->setItemDelegate( del );
|
||||
|
||||
pv->setPlaylistModel( raModel );
|
||||
raModel->setSource( source_ptr() );
|
||||
|
||||
m_recentPlaysWidget = pv;
|
||||
}
|
||||
@@ -570,7 +571,7 @@ ViewManager::historyBack()
|
||||
return;
|
||||
|
||||
ViewPage* page = m_pageHistoryBack.takeLast();
|
||||
|
||||
|
||||
if ( m_currentPage )
|
||||
{
|
||||
m_pageHistoryFwd << m_currentPage;
|
||||
@@ -589,7 +590,7 @@ ViewManager::historyForward()
|
||||
return;
|
||||
|
||||
ViewPage* page = m_pageHistoryFwd.takeLast();
|
||||
|
||||
|
||||
if ( m_currentPage )
|
||||
{
|
||||
m_pageHistoryBack << m_currentPage;
|
||||
@@ -615,14 +616,7 @@ ViewManager::destroyPage( ViewPage* page )
|
||||
return;
|
||||
|
||||
tDebug() << Q_FUNC_INFO << "Deleting page:" << page->title();
|
||||
if ( m_currentPage == page )
|
||||
{
|
||||
delete page;
|
||||
m_currentPage = 0;
|
||||
|
||||
historyBack();
|
||||
}
|
||||
else if ( historyPages().contains( page ) )
|
||||
if ( historyPages().contains( page ) )
|
||||
{
|
||||
m_pageHistoryBack.removeAll( page );
|
||||
m_pageHistoryFwd.removeAll( page );
|
||||
@@ -632,6 +626,13 @@ ViewManager::destroyPage( ViewPage* page )
|
||||
|
||||
delete page;
|
||||
}
|
||||
|
||||
if ( m_currentPage == page )
|
||||
{
|
||||
m_currentPage = 0;
|
||||
|
||||
historyBack();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -640,6 +641,8 @@ ViewManager::setPage( ViewPage* page, bool trackHistory )
|
||||
{
|
||||
if ( !page )
|
||||
return;
|
||||
if ( page == m_currentPage )
|
||||
return;
|
||||
|
||||
// save the old playlist shuffle state in config before we change playlists
|
||||
saveCurrentPlaylistSettings();
|
||||
@@ -865,7 +868,7 @@ ViewManager::onWidgetDestroyed( QWidget* widget )
|
||||
{
|
||||
m_dynamicWidgets.remove( dynamicPlaylistForInterface( page->playlistInterface() ) );
|
||||
}
|
||||
|
||||
|
||||
m_pageHistoryBack.removeAll( page );
|
||||
m_pageHistoryFwd.removeAll( page );
|
||||
}
|
||||
|
@@ -132,7 +132,7 @@ LastFmConfig::onHistoryLoaded()
|
||||
uint total = 0;
|
||||
bool finished = false;
|
||||
QNetworkReply* reply = qobject_cast< QNetworkReply* >( sender() );
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
lastfm::XmlQuery lfm;
|
||||
@@ -140,24 +140,27 @@ LastFmConfig::onHistoryLoaded()
|
||||
|
||||
foreach ( lastfm::XmlQuery e, lfm.children( "track" ) )
|
||||
{
|
||||
// tDebug() << "Found:" << e["artist"].text() << e["name"].text() << e["date"].attribute( "uts" ).toUInt();
|
||||
Tomahawk::query_ptr query = Query::get( e["artist"].text(), e["name"].text(), QString(), QString(), false );
|
||||
// tDebug() << "Found:" << e.children( "artist" ).first()["name"].text() << e["name"].text() << e["date"].attribute( "uts" ).toUInt();
|
||||
Tomahawk::query_ptr query = Query::get( e.children( "artist" ).first()["name"].text(), e["name"].text(), QString(), QString(), false );
|
||||
if ( query.isNull() )
|
||||
continue;
|
||||
|
||||
m_lastTimeStamp = e["date"].attribute( "uts" ).toUInt();
|
||||
|
||||
|
||||
DatabaseCommand_LogPlayback* cmd = new DatabaseCommand_LogPlayback( query, DatabaseCommand_LogPlayback::Finished, m_lastTimeStamp );
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>(cmd) );
|
||||
}
|
||||
|
||||
|
||||
if ( !lfm.children( "recenttracks" ).isEmpty() )
|
||||
{
|
||||
lastfm::XmlQuery stats = lfm.children( "recenttracks" ).first();
|
||||
|
||||
|
||||
uint page = stats.attribute( "page" ).toUInt();
|
||||
total = stats.attribute( "totalPages" ).toUInt();
|
||||
|
||||
|
||||
m_ui->progressBar->setMaximum( total );
|
||||
m_ui->progressBar->setValue( page );
|
||||
|
||||
|
||||
if ( page < total )
|
||||
{
|
||||
m_page = page + 1;
|
||||
@@ -174,7 +177,7 @@ LastFmConfig::onHistoryLoaded()
|
||||
tDebug() << "XmlQuery error:" << e.message();
|
||||
finished = true;
|
||||
}
|
||||
|
||||
|
||||
if ( finished )
|
||||
{
|
||||
if ( m_page != total )
|
||||
|
@@ -212,7 +212,7 @@ LastFmInfoPlugin::scrobble()
|
||||
return;
|
||||
|
||||
tLog() << Q_FUNC_INFO << "Scrobbling now:" << m_track.toString();
|
||||
|
||||
|
||||
// FIXME: workaround for the duration-less dilandau (and others) tracks
|
||||
if ( m_track.duration() == 0 )
|
||||
m_track.setDuration( 31 );
|
||||
@@ -525,7 +525,7 @@ LastFmInfoPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::In
|
||||
imgurl.addEncodedQueryItem( "artist", QUrl::toPercentEncoding( artistName, "", "+" ) );
|
||||
imgurl.addEncodedQueryItem( "album", QUrl::toPercentEncoding( albumName, "", "+" ) );
|
||||
imgurl.addQueryItem( "autocorrect", QString::number( 1 ) );
|
||||
imgurl.addQueryItem( "size", "largesquare" );
|
||||
imgurl.addQueryItem( "size", "large" );
|
||||
imgurl.addQueryItem( "api_key", "7a90f6672a04b809ee309af169f34b8b" );
|
||||
|
||||
QNetworkRequest req( imgurl );
|
||||
|
@@ -29,6 +29,8 @@
|
||||
#include "Pipeline.h"
|
||||
#include "accounts/AccountManager.h"
|
||||
#include "utils/Closure.h"
|
||||
#include "SpotifyInfoPlugin.h"
|
||||
#include "infosystem/InfoSystem.h"
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
#include "jobview/JobStatusView.h"
|
||||
@@ -80,6 +82,7 @@ SpotifyAccountFactory::icon() const
|
||||
SpotifyAccount::SpotifyAccount( const QString& accountId )
|
||||
: CustomAtticaAccount( accountId )
|
||||
, m_preventEnabling( false )
|
||||
, m_loggedIn( false )
|
||||
{
|
||||
init();
|
||||
}
|
||||
@@ -106,6 +109,12 @@ SpotifyAccount::init()
|
||||
AtticaManager::instance()->registerCustomAccount( s_resolverId, this );
|
||||
qRegisterMetaType< Tomahawk::Accounts::SpotifyPlaylistInfo* >( "Tomahawk::Accounts::SpotifyPlaylist*" );
|
||||
|
||||
if ( infoPlugin() && Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() )
|
||||
{
|
||||
infoPlugin().data()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin() );
|
||||
}
|
||||
|
||||
if ( !AtticaManager::instance()->resolversLoaded() )
|
||||
{
|
||||
// If we're still waiting to load, wait for the attica resolvers to come down the pipe
|
||||
@@ -121,7 +130,6 @@ SpotifyAccount::init()
|
||||
void
|
||||
SpotifyAccount::delayedInit()
|
||||
{
|
||||
|
||||
connect( AtticaManager::instance(), SIGNAL( resolverInstalled( QString ) ), this, SLOT( resolverInstalled( QString ) ) );
|
||||
|
||||
const Attica::Content res = AtticaManager::instance()->resolverForId( s_resolverId );
|
||||
@@ -131,6 +139,11 @@ SpotifyAccount::delayedInit()
|
||||
if ( !checkForResolver() && state != AtticaManager::Uninstalled )
|
||||
{
|
||||
// If the user manually deleted the resolver, mark it as uninstalled, so we re-fetch for the user
|
||||
QVariantHash conf = configuration();
|
||||
conf.remove( "path" );
|
||||
setConfiguration( conf );
|
||||
sync();
|
||||
|
||||
AtticaManager::instance()->uninstallResolver( res );
|
||||
}
|
||||
else if ( state == AtticaManager::Installed || !path.isEmpty() )
|
||||
@@ -138,9 +151,15 @@ SpotifyAccount::delayedInit()
|
||||
if ( !path.isEmpty() )
|
||||
{
|
||||
QFileInfo info( path );
|
||||
// Resolver was deleted, so abort.
|
||||
// Resolver was deleted, so abort and remove our manual override, as it's no longer valid
|
||||
if ( !info.exists() )
|
||||
{
|
||||
QVariantHash conf = configuration();
|
||||
conf.remove( "path" );
|
||||
setConfiguration( conf );
|
||||
sync();
|
||||
return;
|
||||
}
|
||||
}
|
||||
hookupResolver();
|
||||
}
|
||||
@@ -165,20 +184,44 @@ SpotifyAccount::hookupResolver()
|
||||
}
|
||||
|
||||
qDebug() << "Starting spotify resolver with path:" << path;
|
||||
if ( !m_spotifyResolver.isNull() )
|
||||
{
|
||||
delete m_spotifyResolver.data();
|
||||
}
|
||||
|
||||
if ( !QFile::exists( path ) )
|
||||
{
|
||||
qWarning() << "Asked to hook up spotify resolver but it doesn't exist, ignoring";
|
||||
return;
|
||||
}
|
||||
|
||||
// HACK
|
||||
// Since the resolver in 0.4.x used an incompatible version of kdsingleappguard, we can't auto-kill old resolvers on the
|
||||
// 0.4.x->0.5.x upgrade. So we do it manually for a while
|
||||
killExistingResolvers();
|
||||
m_spotifyResolver = QWeakPointer< ScriptResolver >( qobject_cast< ScriptResolver* >( Pipeline::instance()->addScriptResolver( path ) ) );
|
||||
|
||||
connect( m_spotifyResolver.data(), SIGNAL( changed() ), this, SLOT( resolverChanged() ) );
|
||||
connect( m_spotifyResolver.data(), SIGNAL( customMessage( QString,QVariantMap ) ), this, SLOT( resolverMessage( QString, QVariantMap ) ) );
|
||||
|
||||
const bool hasMigrated = configuration().value( "hasMigrated" ).toBool();
|
||||
if ( !hasMigrated )
|
||||
{
|
||||
qDebug() << "Getting credentials from spotify resolver to migrate to in-app config";
|
||||
QVariantMap msg;
|
||||
msg[ "_msgtype" ] = "getCredentials";
|
||||
m_spotifyResolver.data()->sendMessage( msg );
|
||||
}
|
||||
// Always get logged in status
|
||||
QVariantMap msg;
|
||||
msg[ "_msgtype" ] = "getCredentials";
|
||||
m_spotifyResolver.data()->sendMessage( msg );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccount::killExistingResolvers()
|
||||
{
|
||||
QProcess p;
|
||||
#if defined(Q_OS_UNIX)
|
||||
const int ret = p.execute( "killall -9 spotify_tomahawkresolver" );
|
||||
qDebug() << "Tried to killall -9 spotify_tomahawkresolver with return code:" << ret;
|
||||
#elif defined(Q_OS_WIN)
|
||||
const int ret = p.execute( "taskkill.exe /F /im spotify_tomahawkresolver.exe" );
|
||||
qDebug() << "Tried to taskkill.exe /F /im spotify_tomahawkresolver.exe with return code:" << ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -228,13 +271,18 @@ SpotifyAccount::authenticate()
|
||||
const AtticaManager::ResolverState state = AtticaManager::instance()->resolverState( res );
|
||||
|
||||
qDebug() << "Spotify account authenticating...";
|
||||
|
||||
const QString path = configuration().value( "path" ).toString();
|
||||
const QFileInfo info( path );
|
||||
const bool manualResolverRemoved = !path.isEmpty() && !info.exists();
|
||||
|
||||
if ( m_spotifyResolver.isNull() && state == AtticaManager::Installed )
|
||||
{
|
||||
// We don;t have the resolver but it has been installed via attica already, so lets just turn it on
|
||||
qDebug() << "No valid spotify resolver running, but attica reports it is installed, so start it up";
|
||||
hookupResolver();
|
||||
}
|
||||
else if ( m_spotifyResolver.isNull() )
|
||||
else if ( m_spotifyResolver.isNull() || manualResolverRemoved )
|
||||
{
|
||||
qDebug() << "Got null resolver but asked to authenticate, so installing if we have one from attica:" << res.isValid() << res.id();
|
||||
if ( res.isValid() && !res.id().isEmpty() )
|
||||
@@ -284,6 +332,18 @@ SpotifyAccount::connectionState() const
|
||||
}
|
||||
|
||||
|
||||
InfoSystem::InfoPluginPtr
|
||||
SpotifyAccount::infoPlugin()
|
||||
{
|
||||
if ( m_infoPlugin.isNull() )
|
||||
{
|
||||
m_infoPlugin = QWeakPointer< InfoSystem::SpotifyInfoPlugin >( new InfoSystem::SpotifyInfoPlugin( this ) );
|
||||
}
|
||||
|
||||
return InfoSystem::InfoPluginPtr( m_infoPlugin.data() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccount::resolverInstalled(const QString& resolverId)
|
||||
{
|
||||
@@ -318,6 +378,11 @@ SpotifyAccount::setManualResolverPath( const QString &resolverPath )
|
||||
setConfiguration( conf );
|
||||
sync();
|
||||
|
||||
// uninstall
|
||||
const Attica::Content res = AtticaManager::instance()->resolverForId( s_resolverId );
|
||||
if ( AtticaManager::instance()->resolverState( res ) != AtticaManager::Uninstalled )
|
||||
AtticaManager::instance()->uninstallResolver( res );
|
||||
|
||||
m_preventEnabling = false;
|
||||
|
||||
if ( !m_spotifyResolver.isNull() )
|
||||
@@ -335,6 +400,13 @@ SpotifyAccount::setManualResolverPath( const QString &resolverPath )
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SpotifyAccount::loggedIn() const
|
||||
{
|
||||
return m_loggedIn;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccount::hookupAfterDeletion( bool autoEnable )
|
||||
{
|
||||
@@ -466,6 +538,15 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg
|
||||
creds[ "highQuality" ] = msg.value( "highQuality" );
|
||||
setCredentials( creds );
|
||||
|
||||
m_loggedIn = msg.value( "loggedIn", false ).toBool();
|
||||
if ( m_loggedIn )
|
||||
{
|
||||
configurationWidget();
|
||||
|
||||
if ( !m_configWidget.isNull() )
|
||||
m_configWidget.data()->loginResponse( true, QString(), creds[ "username" ].toString() );
|
||||
}
|
||||
|
||||
qDebug() << "Set creds:" << creds.value( "username" ) << creds.value( "password" ) << msg.value( "username" ) << msg.value( "password" );
|
||||
|
||||
QVariantHash config = configuration();
|
||||
@@ -483,8 +564,12 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg
|
||||
QObject* receiver = m_qidToSlotMap[ qid ].first;
|
||||
QString slot = m_qidToSlotMap[ qid ].second;
|
||||
m_qidToSlotMap.remove( qid );
|
||||
|
||||
QVariant extraData;
|
||||
if ( m_qidToExtraData.contains( qid ) )
|
||||
extraData = m_qidToExtraData.take( qid );
|
||||
|
||||
QMetaObject::invokeMethod( receiver, slot.toLatin1(), Q_ARG( QString, msgType ), Q_ARG( QVariantMap, msg ) );
|
||||
QMetaObject::invokeMethod( receiver, slot.toLatin1(), Q_ARG( QString, msgType ), Q_ARG( QVariantMap, msg ), Q_ARG( QVariant, extraData ) );
|
||||
}
|
||||
else if ( msgType == "allPlaylists" )
|
||||
{
|
||||
@@ -626,6 +711,8 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg
|
||||
|
||||
const bool success = msg.value( "success" ).toBool();
|
||||
|
||||
m_loggedIn = success;
|
||||
|
||||
if ( success )
|
||||
createActions();
|
||||
|
||||
@@ -633,7 +720,7 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg
|
||||
if ( m_configWidget.data() )
|
||||
{
|
||||
const QString message = msg.value( "message" ).toString();
|
||||
m_configWidget.data()->loginResponse( success, message );
|
||||
m_configWidget.data()->loginResponse( success, message, creds[ "username" ].toString() );
|
||||
}
|
||||
}
|
||||
else if ( msgType == "playlistDeleted" )
|
||||
@@ -646,6 +733,23 @@ SpotifyAccount::resolverMessage( const QString &msgType, const QVariantMap &msg
|
||||
SpotifyPlaylistUpdater* updater = m_updaters.take( plid );
|
||||
updater->remove( false );
|
||||
}
|
||||
else if ( msgType == "status" )
|
||||
{
|
||||
const bool loggedIn = msg.value( "loggedIn" ).toBool();
|
||||
const QString username = msg.value( "username" ).toString();
|
||||
|
||||
qDebug() << "Got status message with login info:" << loggedIn << username;
|
||||
|
||||
if ( !loggedIn || username.isEmpty() || credentials().value( "username").toString() != username )
|
||||
m_loggedIn = false;
|
||||
|
||||
QVariantMap msg;
|
||||
msg[ "_msgtype" ] = "status";
|
||||
msg[ "_status" ] = 1;
|
||||
sendMessage( msg );
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -685,16 +789,17 @@ SpotifyAccount::icon() const
|
||||
QWidget*
|
||||
SpotifyAccount::configurationWidget()
|
||||
{
|
||||
if ( m_spotifyResolver.isNull() || !m_spotifyResolver.data()->running() )
|
||||
return 0;
|
||||
|
||||
if ( m_configWidget.isNull() )
|
||||
{
|
||||
m_configWidget = QWeakPointer< SpotifyAccountConfig >( new SpotifyAccountConfig( this ) );
|
||||
connect( m_configWidget.data(), SIGNAL( login( QString,QString ) ), this, SLOT( login( QString,QString ) ) );
|
||||
connect( m_configWidget.data(), SIGNAL( logout() ), this, SLOT( logout() ) );
|
||||
m_configWidget.data()->setPlaylists( m_allSpotifyPlaylists );
|
||||
}
|
||||
|
||||
if ( m_spotifyResolver.isNull() || !m_spotifyResolver.data()->running() )
|
||||
return 0;
|
||||
|
||||
return static_cast< QWidget* >( m_configWidget.data() );
|
||||
}
|
||||
|
||||
@@ -774,7 +879,6 @@ SpotifyAccount::saveConfig()
|
||||
void
|
||||
SpotifyAccount::login( const QString& username, const QString& password )
|
||||
{
|
||||
// Send the result to the resolver
|
||||
QVariantMap msg;
|
||||
msg[ "_msgtype" ] = "login";
|
||||
msg[ "username" ] = username;
|
||||
@@ -786,6 +890,15 @@ SpotifyAccount::login( const QString& username, const QString& password )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccount::logout()
|
||||
{
|
||||
QVariantMap msg;
|
||||
msg[ "_msgtype" ] = "logout";
|
||||
m_spotifyResolver.data()->sendMessage( msg );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccount::startPlaylistSync( SpotifyPlaylistInfo* playlist )
|
||||
{
|
||||
@@ -802,7 +915,7 @@ SpotifyAccount::startPlaylistSync( SpotifyPlaylistInfo* playlist )
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccount::startPlaylistSyncWithPlaylist( const QString& msgType, const QVariantMap& msg )
|
||||
SpotifyAccount::startPlaylistSyncWithPlaylist( const QString& msgType, const QVariantMap& msg, const QVariant& )
|
||||
{
|
||||
Q_UNUSED( msgType );
|
||||
qDebug() << Q_FUNC_INFO << "Got full spotify playlist body, creating a tomahawk playlist and enabling sync!!";
|
||||
@@ -850,7 +963,7 @@ SpotifyAccount::startPlaylistSyncWithPlaylist( const QString& msgType, const QVa
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccount::playlistCreated( const QString& msgType, const QVariantMap& msg )
|
||||
SpotifyAccount::playlistCreated( const QString& msgType, const QVariantMap& msg, const QVariant& )
|
||||
{
|
||||
Q_UNUSED( msgType );
|
||||
|
||||
@@ -881,20 +994,20 @@ SpotifyAccount::playlistCreated( const QString& msgType, const QVariantMap& msg
|
||||
|
||||
|
||||
QString
|
||||
SpotifyAccount::sendMessage( const QVariantMap &m, QObject* obj, const QString& slot )
|
||||
SpotifyAccount::sendMessage( const QVariantMap &m, QObject* obj, const QString& slot, const QVariant& extraData )
|
||||
{
|
||||
QVariantMap msg = m;
|
||||
QString qid;
|
||||
const QString qid = uuid();
|
||||
|
||||
if ( obj )
|
||||
{
|
||||
qid = QUuid::createUuid().toString().replace( "{", "" ).replace( "}", "" );
|
||||
|
||||
m_qidToSlotMap[ qid ] = qMakePair( obj, slot );
|
||||
msg[ "qid" ] = qid;
|
||||
|
||||
}
|
||||
|
||||
m_qidToExtraData[ qid ] = extraData;
|
||||
|
||||
m_spotifyResolver.data()->sendMessage( msg );
|
||||
|
||||
return qid;
|
||||
|
@@ -35,6 +35,12 @@ class QTimer;
|
||||
class ScriptResolver;
|
||||
|
||||
namespace Tomahawk {
|
||||
|
||||
namespace InfoSystem
|
||||
{
|
||||
class SpotifyInfoPlugin;
|
||||
}
|
||||
|
||||
namespace Accounts {
|
||||
|
||||
class SpotifyAccountConfig;
|
||||
@@ -89,11 +95,10 @@ public:
|
||||
virtual void deauthenticate();
|
||||
|
||||
virtual QWidget* aclWidget() { return 0; }
|
||||
virtual Tomahawk::InfoSystem::InfoPluginPtr infoPlugin() { return Tomahawk::InfoSystem::InfoPluginPtr(); }
|
||||
virtual Tomahawk::InfoSystem::InfoPluginPtr infoPlugin();
|
||||
virtual SipPlugin* sipPlugin() { return 0; }
|
||||
virtual bool preventEnabling() const { return m_preventEnabling; }
|
||||
|
||||
QString sendMessage( const QVariantMap& msg, QObject* receiver = 0, const QString& slot = QString() );
|
||||
|
||||
void registerUpdaterForPlaylist( const QString& plId, SpotifyPlaylistUpdater* updater );
|
||||
void unregisterUpdater( const QString& plid );
|
||||
@@ -102,7 +107,11 @@ public:
|
||||
|
||||
void setManualResolverPath( const QString& resolverPath );
|
||||
|
||||
bool loggedIn() const;
|
||||
|
||||
public slots:
|
||||
QString sendMessage( const QVariantMap& msg, QObject* receiver = 0, const QString& slot = QString(), const QVariant& extraData = QVariant() );
|
||||
|
||||
void aboutToShow( QAction* action, const Tomahawk::playlist_ptr& playlist );
|
||||
void syncActionTriggered( bool );
|
||||
void atticaLoaded(Attica::Content::List);
|
||||
@@ -114,10 +123,12 @@ private slots:
|
||||
void resolverMessage( const QString& msgType, const QVariantMap& msg );
|
||||
|
||||
void login( const QString& username, const QString& password );
|
||||
void logout();
|
||||
|
||||
// SpotifyResolver message handlers, all take msgtype, msg as argument
|
||||
// void <here>( const QString& msgType, const QVariantMap& msg );
|
||||
void startPlaylistSyncWithPlaylist( const QString& msgType, const QVariantMap& msg );
|
||||
void playlistCreated( const QString& msgType, const QVariantMap& msg );
|
||||
// void <here>( const QString& msgType, const QVariantMap& msg, const QVariant& extraData );
|
||||
void startPlaylistSyncWithPlaylist( const QString& msgType, const QVariantMap& msg, const QVariant& extraData );
|
||||
void playlistCreated( const QString& msgType, const QVariantMap& msg, const QVariant& extraData );
|
||||
|
||||
void delayedInit();
|
||||
void hookupAfterDeletion( bool autoEnable );
|
||||
@@ -126,6 +137,7 @@ private:
|
||||
void init();
|
||||
bool checkForResolver();
|
||||
void hookupResolver();
|
||||
void killExistingResolvers();
|
||||
|
||||
void loadPlaylists();
|
||||
void clearUser( bool permanentlyDelete = false );
|
||||
@@ -142,8 +154,10 @@ private:
|
||||
QWeakPointer<SpotifyAccountConfig> m_configWidget;
|
||||
QWeakPointer<QWidget> m_aboutWidget;
|
||||
QWeakPointer<ScriptResolver> m_spotifyResolver;
|
||||
QWeakPointer< InfoSystem::SpotifyInfoPlugin > m_infoPlugin;
|
||||
|
||||
QMap<QString, QPair<QObject*, QString> > m_qidToSlotMap;
|
||||
QMap<QString, QVariant > m_qidToExtraData;
|
||||
|
||||
// List of synced spotify playlists in config UI
|
||||
QList< SpotifyPlaylistInfo* > m_allSpotifyPlaylists;
|
||||
@@ -151,7 +165,7 @@ private:
|
||||
|
||||
QHash< QString, playlist_ptr > m_waitingForCreateReply;
|
||||
|
||||
bool m_preventEnabling;
|
||||
bool m_preventEnabling, m_loggedIn;
|
||||
|
||||
SmartPointerList< QAction > m_customActions;
|
||||
friend class ::SpotifyPlaylistUpdater;
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include <QListWidget>
|
||||
#include <QListWidgetItem>
|
||||
#include <QShowEvent>
|
||||
#include <QLabel>
|
||||
|
||||
using namespace Tomahawk;
|
||||
using namespace Accounts;
|
||||
@@ -32,16 +33,20 @@ using namespace Accounts;
|
||||
SpotifyAccountConfig::SpotifyAccountConfig( SpotifyAccount *account )
|
||||
: QWidget( 0 )
|
||||
, m_ui( new Ui::SpotifyConfig )
|
||||
, m_loggedInUser( 0 )
|
||||
, m_account( account )
|
||||
, m_playlistsLoading( 0 )
|
||||
, m_loggedInManually( false )
|
||||
, m_isLoggedIn( false )
|
||||
{
|
||||
m_ui->setupUi( this );
|
||||
|
||||
m_ui->loginButton->setDefault( true );
|
||||
|
||||
connect( m_ui->loginButton, SIGNAL( clicked( bool ) ), this, SLOT( doLogin() ) );
|
||||
|
||||
connect( m_ui->usernameEdit, SIGNAL( textChanged( QString ) ), this, SLOT( resetLoginButton() ) );
|
||||
connect( m_ui->passwordEdit, SIGNAL( textChanged( QString ) ), this, SLOT( resetLoginButton() ) );
|
||||
connect( m_ui->usernameEdit, SIGNAL( textEdited( QString ) ), this, SLOT( resetLoginButton() ) );
|
||||
connect( m_ui->passwordEdit, SIGNAL( textEdited( QString ) ), this, SLOT( resetLoginButton() ) );
|
||||
loadFromConfig();
|
||||
|
||||
m_playlistsLoading = new AnimatedSpinner( m_ui->playlistList );
|
||||
@@ -61,10 +66,21 @@ SpotifyAccountConfig::showEvent( QShowEvent *event )
|
||||
void
|
||||
SpotifyAccountConfig::loadFromConfig()
|
||||
{
|
||||
m_ui->usernameEdit->setText( m_account->credentials().value( "username" ).toString() );
|
||||
const QString username = m_account->credentials().value( "username" ).toString();
|
||||
m_ui->usernameEdit->setText( username );
|
||||
m_ui->passwordEdit->setText( m_account->credentials().value( "password" ).toString() );
|
||||
m_ui->streamingCheckbox->setChecked( m_account->credentials().value( "highQuality" ).toBool() );
|
||||
m_ui->deleteOnUnsync->setChecked( m_account->deleteOnUnsync() );
|
||||
|
||||
if ( m_account->loggedIn() )
|
||||
{
|
||||
qDebug() << "Loading spotify config widget with logged in username:" << username;
|
||||
if ( !username.isEmpty() )
|
||||
m_verifiedUsername = username;
|
||||
showLoggedIn();
|
||||
}
|
||||
else
|
||||
showLoggedOut();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -132,28 +148,44 @@ SpotifyAccountConfig::setPlaylists( const QList<SpotifyPlaylistInfo *>& playlist
|
||||
void
|
||||
SpotifyAccountConfig::doLogin()
|
||||
{
|
||||
m_ui->loginButton->setText( tr( "Logging in..." ) );
|
||||
m_ui->loginButton->setEnabled( false );
|
||||
if ( !m_isLoggedIn )
|
||||
{
|
||||
m_ui->loginButton->setText( tr( "Logging in..." ) );
|
||||
m_ui->loginButton->setEnabled( false );
|
||||
|
||||
m_playlistsLoading->fadeIn();
|
||||
m_loggedInManually = true;
|
||||
m_playlistsLoading->fadeIn();
|
||||
m_loggedInManually = true;
|
||||
|
||||
emit login( username(), password() );
|
||||
emit login( username(), password() );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Log out
|
||||
m_isLoggedIn = false;
|
||||
m_loggedInManually = true;
|
||||
m_verifiedUsername.clear();
|
||||
m_ui->playlistList->clear();
|
||||
emit logout();
|
||||
showLoggedOut();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccountConfig::loginResponse( bool success, const QString& msg )
|
||||
SpotifyAccountConfig::loginResponse( bool success, const QString& msg, const QString& username )
|
||||
{
|
||||
if ( success )
|
||||
{
|
||||
m_ui->loginButton->setText( tr( "Logged in!" ) );
|
||||
m_ui->loginButton->setEnabled( false );
|
||||
qDebug() << Q_FUNC_INFO << "Login response with username:" << username;
|
||||
m_verifiedUsername = username;
|
||||
m_isLoggedIn = true;
|
||||
showLoggedIn();
|
||||
}
|
||||
else
|
||||
{
|
||||
setPlaylists( QList< SpotifyPlaylistInfo* >() );
|
||||
m_playlistsLoading->fadeOut();
|
||||
|
||||
m_ui->loginButton->setText( tr( "Failed: %1" ).arg( msg ) );
|
||||
m_ui->loginButton->setEnabled( true );
|
||||
}
|
||||
@@ -162,9 +194,51 @@ SpotifyAccountConfig::loginResponse( bool success, const QString& msg )
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccountConfig::resetLoginButton()
|
||||
SpotifyAccountConfig::showLoggedIn()
|
||||
{
|
||||
m_ui->passwordEdit->hide();
|
||||
m_ui->passwordLabel->hide();
|
||||
m_ui->usernameEdit->hide();
|
||||
m_ui->usernameLabel->hide();
|
||||
|
||||
if ( !m_loggedInUser )
|
||||
{
|
||||
m_loggedInUser = new QLabel( this );
|
||||
m_ui->verticalLayout->insertWidget( 1, m_loggedInUser, 0, Qt::AlignCenter );
|
||||
}
|
||||
|
||||
qDebug() << "Showing logged in withuserame:" << m_verifiedUsername;
|
||||
m_loggedInUser->show();
|
||||
m_loggedInUser->setText( tr( "Logged in as %1" ).arg( m_verifiedUsername ) );
|
||||
|
||||
m_ui->loginButton->setText( tr( "Log Out" ) );
|
||||
m_ui->loginButton->setEnabled( true );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccountConfig::showLoggedOut()
|
||||
{
|
||||
m_ui->passwordEdit->show();
|
||||
m_ui->passwordLabel->show();
|
||||
m_ui->usernameEdit->show();
|
||||
m_ui->usernameLabel->show();
|
||||
|
||||
if ( m_loggedInUser )
|
||||
m_loggedInUser->hide();
|
||||
|
||||
m_ui->loginButton->setText( tr( "Log In" ) );
|
||||
m_ui->loginButton->setEnabled( true );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyAccountConfig::resetLoginButton()
|
||||
{
|
||||
if ( !m_isLoggedIn )
|
||||
{
|
||||
m_ui->loginButton->setText( tr( "Log In" ) );
|
||||
m_ui->loginButton->setEnabled( true );
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#include <QVariantMap>
|
||||
#include <QTimer>
|
||||
|
||||
class QLabel;
|
||||
class AnimatedSpinner;
|
||||
class QShowEvent;
|
||||
|
||||
@@ -55,14 +56,13 @@ public:
|
||||
void loadFromConfig();
|
||||
void saveSettings();
|
||||
|
||||
void loginResponse( bool success, const QString& msg );
|
||||
void loginResponse( bool success, const QString& msg, const QString& username );
|
||||
|
||||
bool loggedInManually() const { return m_loggedInManually; }
|
||||
|
||||
signals:
|
||||
void login( const QString& username, const QString& pw );
|
||||
|
||||
public slots:
|
||||
// void verifyResult( const QString& msgType, const QVariantMap& msg );
|
||||
void logout();
|
||||
|
||||
protected:
|
||||
void showEvent( QShowEvent* event );
|
||||
@@ -72,10 +72,15 @@ private slots:
|
||||
void resetLoginButton();
|
||||
|
||||
private:
|
||||
void showLoggedIn();
|
||||
void showLoggedOut();
|
||||
|
||||
Ui::SpotifyConfig* m_ui;
|
||||
QLabel* m_loggedInUser;
|
||||
QString m_verifiedUsername;
|
||||
SpotifyAccount* m_account;
|
||||
AnimatedSpinner* m_playlistsLoading;
|
||||
bool m_loggedInManually;
|
||||
bool m_loggedInManually, m_isLoggedIn;
|
||||
};
|
||||
|
||||
}
|
||||
|
261
src/libtomahawk/accounts/spotify/SpotifyInfoPlugin.cpp
Normal file
261
src/libtomahawk/accounts/spotify/SpotifyInfoPlugin.cpp
Normal file
@@ -0,0 +1,261 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2012 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 "SpotifyInfoPlugin.h"
|
||||
|
||||
#include "SpotifyAccount.h"
|
||||
#include "utils/Closure.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
using namespace Tomahawk::InfoSystem;
|
||||
|
||||
|
||||
SpotifyInfoPlugin::SpotifyInfoPlugin( Accounts::SpotifyAccount* account )
|
||||
: InfoPlugin()
|
||||
, m_account( QWeakPointer< Accounts::SpotifyAccount >( account ) )
|
||||
{
|
||||
if ( !m_account.isNull() )
|
||||
m_supportedGetTypes << InfoAlbumSongs;
|
||||
}
|
||||
|
||||
|
||||
SpotifyInfoPlugin::~SpotifyInfoPlugin()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyInfoPlugin::getInfo( InfoRequestData requestData )
|
||||
{
|
||||
switch ( requestData.type )
|
||||
{
|
||||
case InfoAlbumSongs:
|
||||
{
|
||||
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoStringHash >() )
|
||||
{
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
InfoStringHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoStringHash >();
|
||||
if ( !hash.contains( "album" ) )
|
||||
{
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
criteria[ "album" ] = hash[ "album" ];
|
||||
if ( hash.contains( "artist" ) )
|
||||
criteria["artist"] = hash["artist"];
|
||||
|
||||
emit getCachedInfo( criteria, 2419200000, requestData );
|
||||
|
||||
return;
|
||||
}
|
||||
default:
|
||||
dataError( requestData );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyInfoPlugin::notInCacheSlot( InfoStringHash criteria, InfoRequestData requestData )
|
||||
{
|
||||
switch ( requestData.type )
|
||||
{
|
||||
case InfoAlbumSongs:
|
||||
{
|
||||
const QString album = criteria[ "album" ];
|
||||
const QString artist = criteria[ "artist" ];
|
||||
|
||||
if ( m_account.isNull() || !m_account.data()->loggedIn() )
|
||||
{
|
||||
// No running spotify account, use our webservice
|
||||
QUrl lookupUrl( "http://ws.spotify.com/search/1/album.json" );
|
||||
lookupUrl.addQueryItem( "q", QString( "%1 %2" ).arg( album ).arg( album ) );
|
||||
|
||||
QNetworkReply * reply = TomahawkUtils::nam()->get( QNetworkRequest( lookupUrl ) );
|
||||
NewClosure( reply, SIGNAL( finished() ), this, SLOT( albumIdLookupFinished( QNetworkReply*, Tomahawk::InfoSystem::InfoRequestData ) ), reply, requestData );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Running resolver, so do the lookup through that
|
||||
qDebug() << Q_FUNC_INFO << "Doing album lookup through spotify:" << album << artist;
|
||||
QVariantMap message;
|
||||
message[ "_msgtype" ] = "albumListing";
|
||||
message[ "artist" ] = artist;
|
||||
message[ "album" ] = album;
|
||||
|
||||
QMetaObject::invokeMethod( m_account.data(), "sendMessage", Qt::QueuedConnection, Q_ARG( QVariantMap, message ),
|
||||
Q_ARG( QObject*, this ),
|
||||
Q_ARG( QString, "albumListingResult" ),
|
||||
Q_ARG( QVariant, QVariant::fromValue< InfoRequestData >( requestData ) ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Q_ASSERT( false );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyInfoPlugin::albumListingResult( const QString& msgType, const QVariantMap& msg, const QVariant& extraData )
|
||||
{
|
||||
Q_ASSERT( msg.contains( "qid" ) );
|
||||
Q_ASSERT( extraData.canConvert< InfoRequestData >() );
|
||||
|
||||
const InfoRequestData requestData = extraData.value< InfoRequestData >();
|
||||
|
||||
QVariantList tracks = msg.value( "tracks" ).toList();
|
||||
QStringList trackNameList;
|
||||
|
||||
foreach ( const QVariant track, tracks )
|
||||
{
|
||||
const QVariantMap trackData = track.toMap();
|
||||
if ( trackData.contains( "track" ) && !trackData[ "track" ].toString().isEmpty() )
|
||||
trackNameList << trackData[ "track" ].toString();
|
||||
}
|
||||
|
||||
qDebug() << Q_FUNC_INFO << "Successfully got album listing from spotify resolver";
|
||||
trackListResult( trackNameList, requestData );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyInfoPlugin::albumIdLookupFinished( QNetworkReply* reply, const InfoRequestData& requestData )
|
||||
{
|
||||
Q_ASSERT( reply );
|
||||
|
||||
reply->deleteLater();
|
||||
|
||||
if ( reply->error() == QNetworkReply::NoError )
|
||||
{
|
||||
QJson::Parser p;
|
||||
const QVariantMap response = p.parse( reply ).toMap();
|
||||
if ( !response.contains( "albums" ) )
|
||||
{
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
const QVariantList albums = response.value( "albums" ).toList();
|
||||
if ( albums.isEmpty() )
|
||||
{
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
const QVariantMap album = albums.first().toMap();
|
||||
const QString id = album.value( "href" ).toString();
|
||||
if ( id.isEmpty() || !id.contains( "spotify:album" ) )
|
||||
{
|
||||
qDebug() << "Empty or malformed spotify album ID from json:" << id << response;
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "Doing spotify album lookup via webservice with ID:" << id;
|
||||
|
||||
QUrl lookupUrl( QString( "http://spotikea.tomahawk-player.org/browse/%1" ).arg( id ) );
|
||||
|
||||
|
||||
QNetworkReply * reply = TomahawkUtils::nam()->get( QNetworkRequest( lookupUrl ) );
|
||||
NewClosure( reply, SIGNAL( finished() ), this, SLOT( albumContentsLookupFinished( QNetworkReply*, Tomahawk::InfoSystem::InfoRequestData ) ), reply, requestData );
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Network Error retrieving ID from spotify metadata service:" << reply->error() << reply->errorString() << reply->url();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyInfoPlugin::albumContentsLookupFinished( QNetworkReply* reply, const InfoRequestData& requestData )
|
||||
{
|
||||
Q_ASSERT( reply );
|
||||
|
||||
reply->deleteLater();
|
||||
|
||||
if ( reply->error() == QNetworkReply::NoError )
|
||||
{
|
||||
QJson::Parser p;
|
||||
const QVariantMap response = p.parse( reply ).toMap();
|
||||
|
||||
if ( !response.contains( "album" ) )
|
||||
{
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
const QVariantMap album = response.value( "album" ).toMap();
|
||||
if ( !album.contains( "result" ) || album.value( "result" ).toList().isEmpty() )
|
||||
{
|
||||
dataError( requestData );
|
||||
return;
|
||||
}
|
||||
|
||||
const QVariantList albumTracks = album.value( "result" ).toList();
|
||||
QStringList trackNameList;
|
||||
|
||||
foreach ( const QVariant& track, albumTracks )
|
||||
{
|
||||
const QVariantMap trackMap = track.toMap();
|
||||
if ( trackMap.contains( "title" ) )
|
||||
trackNameList << trackMap.value( "title" ).toString();
|
||||
}
|
||||
|
||||
qDebug() << Q_FUNC_INFO << "Successfully got album listing from spotikea service!";
|
||||
|
||||
if ( trackNameList.isEmpty() )
|
||||
dataError( requestData );
|
||||
else
|
||||
trackListResult( trackNameList, requestData );
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Network Error retrieving ID from spotify metadata service:" << reply->error() << reply->errorString() << reply->url();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SpotifyInfoPlugin::dataError( InfoRequestData requestData )
|
||||
{
|
||||
emit info( requestData, QVariant() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpotifyInfoPlugin::trackListResult( const QStringList& trackNameList, const InfoRequestData& requestData )
|
||||
{
|
||||
QVariantMap returnedData;
|
||||
returnedData["tracks"] = trackNameList;
|
||||
|
||||
emit info( requestData, returnedData );
|
||||
|
||||
Tomahawk::InfoSystem::InfoStringHash criteria;
|
||||
criteria["artist"] = requestData.input.value< InfoStringHash>()["artist"];
|
||||
criteria["album"] = requestData.input.value< InfoStringHash>()["album"];
|
||||
|
||||
emit updateCache( criteria, 0, requestData.type, returnedData );
|
||||
}
|
72
src/libtomahawk/accounts/spotify/SpotifyInfoPlugin.h
Normal file
72
src/libtomahawk/accounts/spotify/SpotifyInfoPlugin.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2012 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 SPOTIFYINFOPLUGIN_H
|
||||
#define SPOTIFYINFOPLUGIN_H
|
||||
|
||||
#include "infosystem/InfoSystem.h"
|
||||
#include "DllMacro.h"
|
||||
|
||||
#include <QWeakPointer>
|
||||
|
||||
class QNetworkReply;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace Accounts
|
||||
{
|
||||
class SpotifyAccount;
|
||||
}
|
||||
|
||||
namespace InfoSystem
|
||||
{
|
||||
|
||||
class DLLEXPORT SpotifyInfoPlugin : public InfoPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SpotifyInfoPlugin( Accounts::SpotifyAccount* account );
|
||||
virtual ~SpotifyInfoPlugin();
|
||||
|
||||
public slots:
|
||||
void albumListingResult( const QString& msgType, const QVariantMap& msg, const QVariant& extraData );
|
||||
|
||||
protected slots:
|
||||
virtual void init() {}
|
||||
virtual void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
virtual void pushInfo( Tomahawk::InfoSystem::InfoPushData ) {}
|
||||
|
||||
private slots:
|
||||
void albumIdLookupFinished( QNetworkReply* reply, const Tomahawk::InfoSystem::InfoRequestData& requestData );
|
||||
void albumContentsLookupFinished( QNetworkReply* reply, const Tomahawk::InfoSystem::InfoRequestData& requestData );
|
||||
|
||||
private:
|
||||
void dataError( InfoRequestData );
|
||||
void trackListResult( const QStringList& trackNameList, const Tomahawk::InfoSystem::InfoRequestData& requestData );
|
||||
|
||||
QWeakPointer< Tomahawk::Accounts::SpotifyAccount > m_account;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // SPOTIFYINFOPLUGIN_H
|
@@ -1,6 +1,7 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2012, Leo Franchi <lfranchi@kde.org>
|
||||
* Copyright 2012, Hugo Lindström <hugolm84@gmail.com>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -353,6 +354,8 @@ SpotifyPlaylistUpdater::tomahawkPlaylistRenamed(const QString &newT, const QStri
|
||||
msg[ "newTitle" ] = newT;
|
||||
msg[ "oldTitle" ] = oldT;
|
||||
msg[ "playlistid" ] = m_spotifyId;
|
||||
|
||||
// TODO check return value
|
||||
m_spotify.data()->sendMessage( msg, this, "onPlaylistRename" );
|
||||
}
|
||||
|
||||
@@ -493,7 +496,7 @@ SpotifyPlaylistUpdater::plentryToVariant( const QList< plentry_ptr >& entries )
|
||||
|
||||
|
||||
void
|
||||
SpotifyPlaylistUpdater::onTracksInsertedReturn( const QString& msgType, const QVariantMap& msg )
|
||||
SpotifyPlaylistUpdater::onTracksInsertedReturn( const QString& msgType, const QVariantMap& msg, const QVariant& )
|
||||
{
|
||||
const bool success = msg.value( "success" ).toBool();
|
||||
|
||||
@@ -577,7 +580,7 @@ SpotifyPlaylistUpdater::tomahawkTracksRemoved( const QList< query_ptr >& tracks
|
||||
|
||||
|
||||
void
|
||||
SpotifyPlaylistUpdater::onTracksRemovedReturn( const QString& msgType, const QVariantMap& msg )
|
||||
SpotifyPlaylistUpdater::onTracksRemovedReturn( const QString& msgType, const QVariantMap& msg, const QVariant& )
|
||||
{
|
||||
const bool success = msg.value( "success" ).toBool();
|
||||
|
||||
@@ -626,7 +629,7 @@ SpotifyPlaylistUpdater::tomahawkTracksMoved( const QList< plentry_ptr >& tracks,
|
||||
|
||||
|
||||
void
|
||||
SpotifyPlaylistUpdater::onTracksMovedReturn( const QString& msgType, const QVariantMap& msg )
|
||||
SpotifyPlaylistUpdater::onTracksMovedReturn( const QString& msgType, const QVariantMap& msg, const QVariant& )
|
||||
{
|
||||
const bool success = msg.value( "success" ).toBool();
|
||||
|
||||
@@ -674,9 +677,14 @@ SpotifyPlaylistUpdater::variantToQueries( const QVariantList& list )
|
||||
{
|
||||
QVariantMap trackMap = blob.toMap();
|
||||
const query_ptr q = Query::get( trackMap.value( "artist" ).toString(), trackMap.value( "track" ).toString(), trackMap.value( "album" ).toString(), uuid(), false );
|
||||
if ( trackMap.contains( "id" ) )
|
||||
q->setProperty( "annotation", trackMap.value( "id" ) );
|
||||
if ( q.isNull() )
|
||||
continue;
|
||||
|
||||
if ( trackMap.contains( "id" ) )
|
||||
{
|
||||
q->setResultHint( trackMap.value( "id" ).toString() );
|
||||
q->setProperty( "annotation", trackMap.value( "id" ) );
|
||||
}
|
||||
queries << q;
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2012, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Copyright 2012, Hugo Lindström <hugolm84@gmail.com>
|
||||
* 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
|
||||
@@ -74,9 +74,9 @@ protected:
|
||||
|
||||
private slots:
|
||||
// SpotifyResolver message handlers, all take msgtype, msg as argument
|
||||
void onTracksInsertedReturn( const QString& msgType, const QVariantMap& msg );
|
||||
void onTracksRemovedReturn( const QString& msgType, const QVariantMap& msg );
|
||||
void onTracksMovedReturn( const QString& msgType, const QVariantMap& msg );
|
||||
void onTracksInsertedReturn( const QString& msgType, const QVariantMap& msg, const QVariant& extraData );
|
||||
void onTracksRemovedReturn( const QString& msgType, const QVariantMap& msg, const QVariant& extraData );
|
||||
void onTracksMovedReturn( const QString& msgType, const QVariantMap& msg, const QVariant& extraData );
|
||||
|
||||
void checkDeleteDialog() const;
|
||||
|
||||
|
@@ -37,6 +37,9 @@
|
||||
#include "infosystem/InfoSystem.h"
|
||||
#include "Album.h"
|
||||
#include "Pipeline.h"
|
||||
#include "jobview/JobStatusView.h"
|
||||
#include "jobview/JobStatusModel.h"
|
||||
#include "jobview/ErrorStatusMessage.h"
|
||||
|
||||
#include "utils/Logger.h"
|
||||
|
||||
@@ -94,12 +97,9 @@ AudioEngine::AudioEngine()
|
||||
AudioEngine::~AudioEngine()
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
|
||||
|
||||
m_mediaObject->stop();
|
||||
TomahawkSettings::instance()->setVolume( volume() );
|
||||
|
||||
delete m_audioOutput;
|
||||
delete m_mediaObject;
|
||||
}
|
||||
|
||||
|
||||
@@ -604,8 +604,17 @@ AudioEngine::playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk:
|
||||
{
|
||||
if ( query->resolvingFinished() )
|
||||
{
|
||||
if ( query->numResults() )
|
||||
if ( query->numResults() && query->results().first()->isOnline() )
|
||||
{
|
||||
playItem( playlist, query->results().first() );
|
||||
return;
|
||||
}
|
||||
|
||||
JobStatusView::instance()->model()->addJob(
|
||||
new ErrorStatusMessage( tr( "Sorry, Tomahawk couldn't find the track '%1' by %2" ).arg( query->track() ).arg( query->artist() ), 15 ) );
|
||||
|
||||
if ( isStopped() )
|
||||
emit stopped(); // we do this so the original caller knows we couldn't find this track
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -621,9 +630,18 @@ void
|
||||
AudioEngine::playItem( const Tomahawk::artist_ptr& artist )
|
||||
{
|
||||
playlistinterface_ptr pli = artist->playlistInterface( Mixed );
|
||||
if ( pli->trackCount() )
|
||||
if ( pli->isFinished() )
|
||||
{
|
||||
playItem( pli, pli->tracks().first() );
|
||||
if ( !pli->tracks().count() )
|
||||
{
|
||||
JobStatusView::instance()->model()->addJob(
|
||||
new ErrorStatusMessage( tr( "Sorry, Tomahawk couldn't find the artist '%1'" ).arg( artist->name() ), 15 ) );
|
||||
|
||||
if ( isStopped() )
|
||||
emit stopped(); // we do this so the original caller knows we couldn't find this track
|
||||
}
|
||||
else
|
||||
playItem( pli, pli->tracks().first() );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -638,9 +656,18 @@ void
|
||||
AudioEngine::playItem( const Tomahawk::album_ptr& album )
|
||||
{
|
||||
playlistinterface_ptr pli = album->playlistInterface( Mixed );
|
||||
if ( pli->trackCount() )
|
||||
if ( pli->isFinished() )
|
||||
{
|
||||
playItem( pli, pli->tracks().first() );
|
||||
if ( !pli->tracks().count() )
|
||||
{
|
||||
JobStatusView::instance()->model()->addJob(
|
||||
new ErrorStatusMessage( tr( "Sorry, Tomahawk couldn't find the album '%1' by %2" ).arg( album->name() ).arg( album->artist()->name() ), 15 ) );
|
||||
|
||||
if ( isStopped() )
|
||||
emit stopped(); // we do this so the original caller knows we couldn't find this track
|
||||
}
|
||||
else
|
||||
playItem( pli, pli->tracks().first() );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -734,7 +761,7 @@ AudioEngine::onStateChanged( Phonon::State newState, Phonon::State oldState )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( newState == Phonon::PausedState || newState == Phonon::PlayingState || newState == Phonon::ErrorState )
|
||||
{
|
||||
tDebug() << "Phonon state now:" << newState;
|
||||
@@ -860,10 +887,10 @@ AudioEngine::checkStateQueue()
|
||||
m_mediaObject->play();
|
||||
if ( paused )
|
||||
setVolume( m_volume );
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case Paused:
|
||||
{
|
||||
m_volume = volume();
|
||||
|
@@ -138,7 +138,7 @@ private slots:
|
||||
|
||||
void sendNowPlayingNotification( const Tomahawk::InfoSystem::InfoType type );
|
||||
void sendWaitingNotification() const;
|
||||
|
||||
|
||||
void queueStateSafety();
|
||||
|
||||
private:
|
||||
|
@@ -100,7 +100,7 @@ TopTracksContext::onTracksFound( const QList<Tomahawk::query_ptr>& queries, Mode
|
||||
{
|
||||
Q_UNUSED( mode );
|
||||
|
||||
m_topHitsModel->append( queries );
|
||||
m_topHitsModel->appendQueries( queries );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -162,11 +162,9 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
|
||||
m_ids << fileid;
|
||||
added++;
|
||||
}
|
||||
|
||||
qDebug() << "Inserted" << added << "tracks to database";
|
||||
|
||||
if ( added )
|
||||
source()->updateIndexWhenSynced();
|
||||
|
||||
tDebug() << "Committing" << added << "tracks...";
|
||||
|
||||
emit done( m_files, source()->collection() );
|
||||
}
|
||||
|
@@ -62,10 +62,13 @@ DatabaseCommand_DeleteDynamicPlaylist::postCommitHook()
|
||||
if( playlist.isNull() )
|
||||
playlist = source()->collection()->station( m_playlistguid );
|
||||
|
||||
qDebug() << "Just tried to load playlist for deletion:" << m_playlistguid << "Did we get a null one?" << playlist.isNull() << "is it a station?" << (playlist->mode() == OnDemand);
|
||||
tLog( LOGVERBOSE ) << "Just tried to load playlist for deletion:" << m_playlistguid << "Did we get a null one?" << playlist.isNull();
|
||||
Q_ASSERT( !playlist.isNull() );
|
||||
|
||||
playlist->reportDeleted( playlist );
|
||||
if ( !playlist.isNull() )
|
||||
{
|
||||
tLog( LOGVERBOSE ) << "is it a station?" << ( playlist->mode() == OnDemand );
|
||||
playlist->reportDeleted( playlist );
|
||||
}
|
||||
|
||||
if( source()->isLocal() )
|
||||
Servent::instance()->triggerDBSync();
|
||||
|
@@ -91,6 +91,8 @@ DatabaseCommand_GenericSelect::exec( DatabaseImpl* dbi )
|
||||
artist = query.value( 1 ).toString();
|
||||
|
||||
qry = Tomahawk::Query::get( artist, track, QString() );
|
||||
if ( qry.isNull() )
|
||||
continue;
|
||||
}
|
||||
else if ( m_queryType == Artist )
|
||||
{
|
||||
|
@@ -77,6 +77,9 @@ DatabaseCommand_LoadPlaylistEntries::generateEntries( DatabaseImpl* dbi )
|
||||
e->setResultHint( query.value( 8 ).toString() );
|
||||
|
||||
Tomahawk::query_ptr q = Tomahawk::Query::get( query.value( 2 ).toString(), query.value( 1 ).toString(), query.value( 3 ).toString() );
|
||||
if ( q.isNull() )
|
||||
continue;
|
||||
|
||||
q->setResultHint( query.value( 8 ).toString() );
|
||||
q->setProperty( "annotation", e->annotation() );
|
||||
e->setQuery( q );
|
||||
|
@@ -54,6 +54,10 @@ DatabaseCommand_LogPlayback::postCommitHook()
|
||||
// do not auto resolve this track
|
||||
m_query = Tomahawk::Query::get( m_artist, m_track, QString() );
|
||||
}
|
||||
|
||||
if ( m_query.isNull() )
|
||||
return;
|
||||
|
||||
m_query->setPlayedBy( source(), m_playtime );
|
||||
|
||||
if ( m_action == Finished )
|
||||
|
@@ -111,11 +111,18 @@ DatabaseCommand_SetDynamicPlaylistRevision::postCommitHook()
|
||||
if( playlist.isNull() ) // if it's neither an auto or station, it must not be auto-loaded, so we MUST have been told about it directly
|
||||
rawPl = m_playlist;
|
||||
|
||||
if ( rawPl == 0 )
|
||||
{
|
||||
tLog() <<"Got null playlist with guid:" << playlistguid() << "from source and collection:" << source()->friendlyName() << source()->collection()->name() << "and mode is static?:" << (m_mode == Static);
|
||||
Q_ASSERT( false );
|
||||
return;
|
||||
}
|
||||
|
||||
// workaround a bug in pre-0.1.0 tomahawks. they created dynamic playlists in OnDemand mode *always*, and then set the mode to the real one.
|
||||
// now that we separate them, if we get them as one and then get a changed mode, the playlist ends up in the wrong bucket in Collection.
|
||||
// so here we fix it if we have to.
|
||||
// HACK
|
||||
tDebug() << "Does this need the 0.3->0.1 playlist category hack fix?" << ( rawPl->mode() == Static && source()->collection()->autoPlaylist( playlistguid() ).isNull() )
|
||||
tDebug() << "Does this need the 0.3->0.1 playlist category hack fix?" << ( rawPl->mode() == Static && source()->collection()->autoPlaylist( playlistguid() ).isNull() )
|
||||
<< ( rawPl->mode() == OnDemand && source()->collection()->station( playlistguid() ).isNull() )
|
||||
<< rawPl->mode() << source()->collection()->autoPlaylist( playlistguid() ).isNull() << source()->collection()->station( playlistguid() ).isNull();
|
||||
if( rawPl->mode() == Static && source()->collection()->autoPlaylist( playlistguid() ).isNull() ) // should be here
|
||||
@@ -123,13 +130,7 @@ DatabaseCommand_SetDynamicPlaylistRevision::postCommitHook()
|
||||
else if ( rawPl->mode() == OnDemand && source()->collection()->station( playlistguid() ).isNull() ) // should be here
|
||||
source()->collection()->moveAutoToStation( playlistguid() );
|
||||
|
||||
if ( rawPl == 0 )
|
||||
{
|
||||
tLog() <<"Got null playlist with guid:" << playlistguid() << "from source and collection:" << source()->friendlyName() << source()->collection()->name() << "and mode is static?:" << (m_mode == Static);
|
||||
Q_ASSERT( false );
|
||||
return;
|
||||
}
|
||||
if ( !m_controlsV.isEmpty() && m_controls.isEmpty() )
|
||||
if ( !m_controlsV.isEmpty() && m_controls.isEmpty() )
|
||||
{
|
||||
QList<QVariantMap> controlMap;
|
||||
foreach( const QVariant& v, m_controlsV )
|
||||
|
@@ -80,7 +80,6 @@ DatabaseCommand_SetPlaylistRevision::DatabaseCommand_SetPlaylistRevision(
|
||||
tmp << s;
|
||||
|
||||
setOrderedguids( tmp );
|
||||
|
||||
setPlaylistguid( playlistguid );
|
||||
}
|
||||
|
||||
@@ -100,7 +99,6 @@ DatabaseCommand_SetPlaylistRevision::postCommitHook()
|
||||
playlist_ptr playlist = source()->collection()->playlist( m_playlistguid );
|
||||
if ( playlist.isNull() )
|
||||
{
|
||||
qDebug() << m_playlistguid;
|
||||
Q_ASSERT( !playlist.isNull() );
|
||||
return;
|
||||
}
|
||||
@@ -150,7 +148,9 @@ DatabaseCommand_SetPlaylistRevision::exec( DatabaseImpl* lib )
|
||||
|
||||
foreach( const plentry_ptr& e, m_entries )
|
||||
{
|
||||
if ( e->query()->results().isEmpty() )
|
||||
if ( !e->isValid() )
|
||||
continue;
|
||||
if ( !e->query()->numResults() )
|
||||
continue;
|
||||
|
||||
adde.bindValue( 0, e->query()->results().first()->url() );
|
||||
@@ -167,6 +167,9 @@ DatabaseCommand_SetPlaylistRevision::exec( DatabaseImpl* lib )
|
||||
|
||||
foreach( const plentry_ptr& e, m_entries )
|
||||
{
|
||||
if ( !e->isValid() )
|
||||
continue;
|
||||
|
||||
adde.bindValue( 0, e->query()->track() );
|
||||
adde.bindValue( 1, e->query()->artist() );
|
||||
adde.bindValue( 2, e->query()->album() );
|
||||
@@ -189,6 +192,9 @@ DatabaseCommand_SetPlaylistRevision::exec( DatabaseImpl* lib )
|
||||
qDebug() << "Num new playlist_items to add:" << m_addedentries.length();
|
||||
foreach( const plentry_ptr& e, m_addedentries )
|
||||
{
|
||||
if ( !e->isValid() )
|
||||
continue;
|
||||
|
||||
// qDebug() << "Adding:" << e->guid() << e->query()->track() << e->query()->artist();
|
||||
|
||||
m_addedmap.insert( e->guid(), e ); // needed in postcommithook
|
||||
|
@@ -77,9 +77,11 @@ public:
|
||||
m_addedentries.clear();
|
||||
foreach( const QVariant& v, vlist )
|
||||
{
|
||||
PlaylistEntry * pep = new PlaylistEntry;
|
||||
PlaylistEntry* pep = new PlaylistEntry;
|
||||
QJson::QObjectHelper::qvariant2qobject( v.toMap(), pep );
|
||||
m_addedentries << plentry_ptr(pep);
|
||||
|
||||
if ( pep->isValid() )
|
||||
m_addedentries << plentry_ptr( pep );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +90,9 @@ public:
|
||||
QVariantList vlist;
|
||||
foreach( const plentry_ptr& pe, m_addedentries )
|
||||
{
|
||||
if ( !pe->isValid() )
|
||||
continue;
|
||||
|
||||
QVariant v = QJson::QObjectHelper::qobject2qvariant( pe.data() );
|
||||
vlist << v;
|
||||
}
|
||||
|
@@ -328,9 +328,10 @@ DatabaseImpl::artistId( const QString& name_orig, bool autoCreate )
|
||||
int id = 0;
|
||||
QString sortname = DatabaseImpl::sortname( name_orig );
|
||||
|
||||
QString queryString = QString( "SELECT id FROM artist WHERE sortname = '%1'" ).arg( TomahawkSqlQuery::escape( sortname ) );
|
||||
TomahawkSqlQuery query = newquery();
|
||||
query.exec( queryString );
|
||||
query.prepare( "SELECT id FROM artist WHERE sortname = ?" );
|
||||
query.addBindValue( sortname );
|
||||
query.exec();
|
||||
if ( query.next() )
|
||||
{
|
||||
id = query.value( 0 ).toInt();
|
||||
|
@@ -49,15 +49,24 @@ FuzzyIndex::FuzzyIndex( QObject* parent, bool wipe )
|
||||
QByteArray path = m_lucenePath.toUtf8();
|
||||
const char* cPath = path.constData();
|
||||
|
||||
bool failed = false;
|
||||
tDebug() << "Opening Lucene directory:" << path;
|
||||
try
|
||||
{
|
||||
m_luceneDir = FSDirectory::getDirectory( cPath );
|
||||
m_analyzer = _CLNEW SimpleAnalyzer();
|
||||
m_luceneDir = FSDirectory::getDirectory( cPath );
|
||||
}
|
||||
catch ( CLuceneError& error )
|
||||
{
|
||||
tDebug() << "Caught CLucene error:" << error.what();
|
||||
failed = true;
|
||||
}
|
||||
|
||||
if ( failed )
|
||||
{
|
||||
tDebug() << "Initializing RAM directory instead.";
|
||||
|
||||
m_luceneDir = _CLNEW RAMDirectory();
|
||||
wipe = true;
|
||||
}
|
||||
|
||||
@@ -83,7 +92,7 @@ FuzzyIndex::wipeIndex()
|
||||
endIndexing();
|
||||
|
||||
QTimer::singleShot( 0, this, SLOT( updateIndex() ) );
|
||||
|
||||
|
||||
return true; // FIXME
|
||||
}
|
||||
|
||||
@@ -189,8 +198,8 @@ FuzzyIndex::appendFields( const QMap< unsigned int, QMap< QString, QString > >&
|
||||
catch( CLuceneError& error )
|
||||
{
|
||||
tDebug() << "Caught CLucene error:" << error.what();
|
||||
|
||||
wipeIndex();
|
||||
|
||||
QTimer::singleShot( 0, this, SLOT( wipeIndex() ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,9 +291,9 @@ FuzzyIndex::search( const Tomahawk::query_ptr& query )
|
||||
}
|
||||
catch( CLuceneError& error )
|
||||
{
|
||||
tDebug() << "Caught CLucene error:" << error.what();
|
||||
|
||||
wipeIndex();
|
||||
tDebug() << "Caught CLucene error:" << error.what() << query->toString();
|
||||
|
||||
QTimer::singleShot( 0, this, SLOT( wipeIndex() ) );
|
||||
}
|
||||
|
||||
return resultsmap;
|
||||
@@ -338,8 +347,8 @@ FuzzyIndex::searchAlbum( const Tomahawk::query_ptr& query )
|
||||
catch( CLuceneError& error )
|
||||
{
|
||||
tDebug() << "Caught CLucene error:" << error.what();
|
||||
|
||||
wipeIndex();
|
||||
|
||||
QTimer::singleShot( 0, this, SLOT( wipeIndex() ) );
|
||||
}
|
||||
|
||||
return resultsmap;
|
||||
|
@@ -61,7 +61,7 @@ public:
|
||||
void beginIndexing();
|
||||
void endIndexing();
|
||||
void appendFields( const QMap< unsigned int, QMap< QString, QString > >& trackData );
|
||||
|
||||
|
||||
signals:
|
||||
void indexReady();
|
||||
|
||||
@@ -73,10 +73,9 @@ public slots:
|
||||
|
||||
private slots:
|
||||
void updateIndex();
|
||||
|
||||
private:
|
||||
bool wipeIndex();
|
||||
|
||||
private:
|
||||
QMutex m_mutex;
|
||||
QString m_lucenePath;
|
||||
|
||||
|
@@ -51,6 +51,14 @@ TomahawkSqlQuery::escape( QString identifier )
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TomahawkSqlQuery::prepare( const QString& query )
|
||||
{
|
||||
m_query = query;
|
||||
return QSqlQuery::prepare( query );
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TomahawkSqlQuery::exec( const QString& query )
|
||||
{
|
||||
@@ -76,6 +84,21 @@ TomahawkSqlQuery::exec()
|
||||
unsigned int retries = 0;
|
||||
while ( !QSqlQuery::exec() && ++retries < 10 )
|
||||
{
|
||||
if ( lastError().text().toLower().contains( "no query" ) ||
|
||||
lastError().text().toLower().contains( "parameter count mismatch" ) )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO << "Re-preparing query!";
|
||||
|
||||
QMap< QString, QVariant > bv = boundValues();
|
||||
prepare( m_query );
|
||||
|
||||
foreach ( const QString& key, bv.keys() )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO << "Rebinding key" << key << "with value" << bv.value( key );
|
||||
bindValue( key, bv.value( key ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( isBusyError( lastError() ) )
|
||||
retries = 0;
|
||||
|
||||
@@ -104,7 +127,7 @@ TomahawkSqlQuery::commitTransaction()
|
||||
#endif
|
||||
if ( log )
|
||||
tLog( LOGSQL ) << "TomahawkSqlQuery::commitTransaction running in thread " << QThread::currentThread();
|
||||
|
||||
|
||||
unsigned int retries = 0;
|
||||
while ( !m_db.commit() && ++retries < 10 )
|
||||
{
|
||||
@@ -114,7 +137,7 @@ TomahawkSqlQuery::commitTransaction()
|
||||
tDebug() << "INFO: Retrying failed commit:" << retries << lastError().text();
|
||||
TomahawkUtils::msleep( 10 );
|
||||
}
|
||||
|
||||
|
||||
return ( retries < 10 );
|
||||
}
|
||||
|
||||
@@ -136,5 +159,5 @@ TomahawkSqlQuery::isBusyError( const QSqlError& error ) const
|
||||
{
|
||||
const QString text = error.text().trimmed().toLower();
|
||||
|
||||
return ( text.contains( "no query" ) || text.contains( "locked" ) || text.contains( "busy" ) || text.isEmpty() );
|
||||
return ( text.contains( "locked" ) || text.contains( "busy" ) || text.isEmpty() );
|
||||
}
|
||||
|
@@ -35,17 +35,19 @@ public:
|
||||
|
||||
static QString escape( QString identifier );
|
||||
|
||||
bool prepare( const QString& query );
|
||||
bool exec( const QString& query );
|
||||
bool exec();
|
||||
|
||||
|
||||
bool commitTransaction();
|
||||
|
||||
private:
|
||||
bool isBusyError( const QSqlError& error ) const;
|
||||
|
||||
void showError();
|
||||
|
||||
|
||||
QSqlDatabase m_db;
|
||||
QString m_query;
|
||||
};
|
||||
|
||||
#endif // TOMAHAWKSQLQUERY_H
|
||||
|
@@ -132,10 +132,11 @@ InfoBar::setDescription( const QString& s )
|
||||
ui->descriptionLabel->setText( s );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoBar::setDescription( const artist_ptr& artist )
|
||||
{
|
||||
m_queryLabel->setQuery( Query::get( artist->name(), QString(), QString() ) );
|
||||
m_queryLabel->setArtist( artist );
|
||||
m_queryLabel->setExtraContentsMargins( 4, 0, 0, 0 );
|
||||
|
||||
if ( !m_queryLabel->isVisible() )
|
||||
@@ -151,16 +152,17 @@ InfoBar::setDescription( const artist_ptr& artist )
|
||||
}
|
||||
|
||||
void
|
||||
InfoBar::setDescription( const album_ptr& )
|
||||
InfoBar::setDescription( const album_ptr& )
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoBar::artistClicked()
|
||||
{
|
||||
if ( m_queryLabel && !m_queryLabel->query().isNull() )
|
||||
ViewManager::instance()->show( Artist::get( m_queryLabel->artist() ) );
|
||||
if ( m_queryLabel && !m_queryLabel->artist().isNull() )
|
||||
ViewManager::instance()->show( m_queryLabel->artist() );
|
||||
}
|
||||
|
||||
|
||||
@@ -212,7 +214,6 @@ InfoBar::setUpdaters( const QList<PlaylistUpdaterInterface*>& updaters )
|
||||
newUpdaterWidgets << updater->configurationWidget();
|
||||
}
|
||||
|
||||
|
||||
foreach ( QWidget* updaterWidget, m_updaterConfigurations )
|
||||
{
|
||||
updaterWidget->hide();
|
||||
|
@@ -26,8 +26,10 @@
|
||||
#include <QListView>
|
||||
|
||||
#define ROW_HEIGHT 20
|
||||
#define ICON_PADDING 1
|
||||
#define ICON_PADDING 2
|
||||
#define PADDING 2
|
||||
|
||||
|
||||
JobStatusDelegate::JobStatusDelegate( QObject* parent )
|
||||
: QStyledItemDelegate ( parent )
|
||||
, m_parentView( qobject_cast< QListView* >( parent ) )
|
||||
@@ -35,6 +37,7 @@ JobStatusDelegate::JobStatusDelegate( QObject* parent )
|
||||
Q_ASSERT( m_parentView );
|
||||
}
|
||||
|
||||
|
||||
JobStatusDelegate::~JobStatusDelegate()
|
||||
{
|
||||
|
||||
@@ -55,7 +58,7 @@ JobStatusDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
|
||||
// painter->drawLine( opt.rect.topLeft(), opt.rect.topRight() );
|
||||
|
||||
painter->setRenderHint( QPainter::Antialiasing );
|
||||
QRect iconRect( ICON_PADDING, ICON_PADDING + opt.rect.y(), ROW_HEIGHT - 2*ICON_PADDING, ROW_HEIGHT - 2*ICON_PADDING );
|
||||
QRect iconRect( ICON_PADDING, ICON_PADDING + opt.rect.y(), ROW_HEIGHT - 2 * ICON_PADDING, ROW_HEIGHT - 2 * ICON_PADDING );
|
||||
if ( allowMultiLine )
|
||||
iconRect.moveTop( opt.rect.top() + opt.rect.height() / 2 - iconRect.height() / 2);
|
||||
QPixmap p = index.data( Qt::DecorationRole ).value< QPixmap >();
|
||||
@@ -71,22 +74,24 @@ JobStatusDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
|
||||
if ( !rCol.isEmpty() )
|
||||
{
|
||||
const int w = fm.width( rCol );
|
||||
const QRect rRect( opt.rect.right() - PADDING - w, PADDING + opt.rect.y(), w, opt.rect.height() - 2*PADDING );
|
||||
const QRect rRect( opt.rect.right() - PADDING - w, PADDING + opt.rect.y(), w, opt.rect.height() - 2 * PADDING );
|
||||
painter->drawText( rRect, Qt::AlignCenter, rCol );
|
||||
|
||||
rightEdge = rRect.left();
|
||||
}
|
||||
|
||||
const int mainW = rightEdge - 3*PADDING - iconRect.right();
|
||||
const int mainW = rightEdge - 4 * PADDING - iconRect.right();
|
||||
QString mainText = index.data( Qt::DisplayRole ).toString();
|
||||
QTextOption to( Qt::AlignLeft | Qt::AlignVCenter );
|
||||
if ( !allowMultiLine )
|
||||
mainText = fm.elidedText( mainText, Qt::ElideRight, mainW );
|
||||
mainText = fm.elidedText( mainText, Qt::ElideRight, mainW );
|
||||
else
|
||||
to.setWrapMode( QTextOption::WrapAtWordBoundaryOrAnywhere );
|
||||
painter->drawText( QRect( iconRect.right() + 2*PADDING, PADDING + opt.rect.y(), mainW, opt.rect.height() - 2*PADDING ), mainText, to );
|
||||
|
||||
painter->drawText( QRect( iconRect.right() + 4 * PADDING, PADDING + opt.rect.y(), mainW, opt.rect.height() - 2 * PADDING ), mainText, to );
|
||||
}
|
||||
|
||||
|
||||
QSize
|
||||
JobStatusDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||
{
|
||||
@@ -102,11 +107,11 @@ JobStatusDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelInd
|
||||
initStyleOption( &opt, index );
|
||||
|
||||
const QString text = index.data( Qt::DisplayRole ).toString();
|
||||
const int leftEdge = ICON_PADDING + ROW_HEIGHT + 2*PADDING;
|
||||
const int leftEdge = ICON_PADDING + ROW_HEIGHT + 2 * PADDING;
|
||||
const QRect rect = opt.fontMetrics.boundingRect( leftEdge, opt.rect.top(), m_parentView->width() - leftEdge, 200, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, text );
|
||||
|
||||
m_cachedMultiLineHeights.insert( index, rect.height() + 4*PADDING );
|
||||
m_cachedMultiLineHeights.insert( index, rect.height() + 4 * PADDING );
|
||||
|
||||
return QSize( QStyledItemDelegate::sizeHint ( option, index ).width(), rect.height() + 4*PADDING );
|
||||
return QSize( QStyledItemDelegate::sizeHint ( option, index ).width(), rect.height() + 4 * PADDING );
|
||||
}
|
||||
|
||||
|
@@ -101,13 +101,12 @@ JobStatusView::setModel( JobStatusModel* m )
|
||||
void
|
||||
JobStatusView::customDelegateJobInserted( int row, JobStatusItem* item )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "item is " << item << ", row is " << row;
|
||||
tLog() << Q_FUNC_INFO << "item is" << item << ", row is" << row;
|
||||
if ( !item )
|
||||
return;
|
||||
|
||||
tLog() << Q_FUNC_INFO << "telling item to create delegate";
|
||||
item->createDelegate( m_view );
|
||||
tLog() << Q_FUNC_INFO << "item delegate is " << item->customDelegate();
|
||||
tLog() << Q_FUNC_INFO << "item delegate is" << item->customDelegate();
|
||||
m_view->setItemDelegateForRow( row, item->customDelegate() );
|
||||
AclJobDelegate* delegate = qobject_cast< AclJobDelegate* >( item->customDelegate() );
|
||||
if ( delegate )
|
||||
@@ -127,7 +126,7 @@ JobStatusView::customDelegateJobInserted( int row, JobStatusItem* item )
|
||||
void
|
||||
JobStatusView::customDelegateJobRemoved( int row )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "row is " << row;
|
||||
tLog() << Q_FUNC_INFO << "row is" << row;
|
||||
}
|
||||
|
||||
|
||||
@@ -138,12 +137,12 @@ JobStatusView::refreshDelegates()
|
||||
int count = m_model->rowCount();
|
||||
for ( int i = 0; i < count; i++ )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "checking row " << i;
|
||||
tLog() << Q_FUNC_INFO << "checking row" << i;
|
||||
QModelIndex index = m_model->index( i );
|
||||
QVariant itemVar = index.data( JobStatusModel::JobDataRole );
|
||||
if ( !itemVar.canConvert< JobStatusItem* >() || !itemVar.value< JobStatusItem* >() )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "unable to fetch JobStatusItem* at row " << i;
|
||||
tLog() << Q_FUNC_INFO << "unable to fetch JobStatusItem* at row" << i;
|
||||
continue;
|
||||
}
|
||||
JobStatusItem* item = itemVar.value< JobStatusItem* >();
|
||||
|
@@ -30,7 +30,7 @@ LatchedStatusItem::LatchedStatusItem( const Tomahawk::source_ptr& from, const To
|
||||
, m_to( to )
|
||||
, m_parent( parent )
|
||||
{
|
||||
m_text = tr( "%1 is listening along to you!" ).arg( from->friendlyName() );
|
||||
m_text = tr( "%1 is listening along with you!" ).arg( from->friendlyName() );
|
||||
}
|
||||
|
||||
LatchedStatusItem::~LatchedStatusItem()
|
||||
|
@@ -29,11 +29,14 @@
|
||||
|
||||
QPixmap* PipelineStatusItem::s_pixmap = 0;
|
||||
|
||||
PipelineStatusItem::PipelineStatusItem()
|
||||
PipelineStatusItem::PipelineStatusItem( const Tomahawk::query_ptr& q )
|
||||
: JobStatusItem()
|
||||
{
|
||||
connect( Tomahawk::Pipeline::instance(), SIGNAL( resolving( Tomahawk::query_ptr ) ), this, SLOT( resolving( Tomahawk::query_ptr ) ) );
|
||||
connect( Tomahawk::Pipeline::instance(), SIGNAL( idle() ), this, SLOT( idle() ) );
|
||||
|
||||
if ( !q.isNull() )
|
||||
resolving( q );
|
||||
}
|
||||
|
||||
|
||||
@@ -102,11 +105,10 @@ PipelineStatusManager::PipelineStatusManager( QObject* parent )
|
||||
void
|
||||
PipelineStatusManager::resolving( const Tomahawk::query_ptr& p )
|
||||
{
|
||||
Q_UNUSED( p );
|
||||
if ( m_curItem.isNull() )
|
||||
{
|
||||
// No current query item and we're resolving something, so show it
|
||||
m_curItem = QWeakPointer< PipelineStatusItem >( new PipelineStatusItem );
|
||||
m_curItem = QWeakPointer< PipelineStatusItem >( new PipelineStatusItem( p ) );
|
||||
JobStatusView::instance()->model()->addJob( m_curItem.data() );
|
||||
}
|
||||
}
|
||||
|
@@ -28,7 +28,7 @@ class PipelineStatusItem : public JobStatusItem
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PipelineStatusItem();
|
||||
explicit PipelineStatusItem( const Tomahawk::query_ptr& q );
|
||||
virtual ~PipelineStatusItem();
|
||||
|
||||
virtual QString rightColumnText() const;
|
||||
|
@@ -107,16 +107,17 @@ void
|
||||
DBSyncConnection::check()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << this << m_source->id();
|
||||
if ( m_state != UNKNOWN && m_state != SYNCED )
|
||||
{
|
||||
qDebug() << "Syncing in progress already.";
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_state == SHUTDOWN )
|
||||
{
|
||||
qDebug() << "Aborting sync due to shutdown.";
|
||||
return;
|
||||
}
|
||||
if ( m_state != UNKNOWN && m_state != SYNCED )
|
||||
{
|
||||
qDebug() << "Syncing in progress already.";
|
||||
return;
|
||||
}
|
||||
|
||||
m_uscache.clear();
|
||||
changeState( CHECKING );
|
||||
|
@@ -112,7 +112,7 @@ CustomPlaylistView::tracksGenerated( QList< query_ptr > tracks )
|
||||
return;
|
||||
|
||||
m_model->clear();
|
||||
m_model->append( newTracks );
|
||||
m_model->appendQueries( newTracks );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -56,7 +56,10 @@ GridItemDelegate::GridItemDelegate( QAbstractItemView* parent, PlayableProxyMode
|
||||
if ( m_view && m_view->metaObject()->indexOfSignal( "modelChanged()" ) > -1 )
|
||||
connect( m_view, SIGNAL( modelChanged() ), this, SLOT( modelChanged() ) );
|
||||
|
||||
connect( m_view, SIGNAL( scrolledContents( int, int ) ), SLOT( onScrolled( int, int ) ) );
|
||||
connect( proxy, SIGNAL( rowsAboutToBeInserted( QModelIndex, int, int ) ), SLOT( modelChanged() ) );
|
||||
connect( proxy, SIGNAL( rowsAboutToBeRemoved( QModelIndex, int, int ) ), SLOT( modelChanged() ) );
|
||||
connect( m_view, SIGNAL( scrolledContents( int, int ) ), SLOT( onViewChanged() ) );
|
||||
connect( m_view, SIGNAL( resized() ), SLOT( onViewChanged() ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -116,8 +119,8 @@ GridItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
|
||||
m_covers.insert( index, QSharedPointer< Tomahawk::PixmapDelegateFader >( new Tomahawk::PixmapDelegateFader( item->query(), r.size(), TomahawkUtils::Grid ) ) );
|
||||
}
|
||||
|
||||
_detail::Closure* closure = NewClosure( m_covers[ index ], SIGNAL( repaintRequest() ), const_cast<GridItemDelegate*>(this), SLOT( doUpdateIndex( QPersistentModelIndex ) ), QPersistentModelIndex( index ) );
|
||||
closure->setAutoDelete( false );
|
||||
NewClosure( m_covers[ index ], SIGNAL( repaintRequest() ),
|
||||
const_cast<GridItemDelegate*>(this), SLOT( doUpdateIndex( QPersistentModelIndex ) ), QPersistentModelIndex( index ) )->setAutoDelete( false );
|
||||
}
|
||||
|
||||
QSharedPointer< Tomahawk::PixmapDelegateFader > fader = m_covers[ index ];
|
||||
@@ -237,14 +240,18 @@ GridItemDelegate::onPlayClicked( const QPersistentModelIndex& index )
|
||||
PlayableItem* item = m_model->sourceModel()->itemFromIndex( m_model->mapToSource( index ) );
|
||||
if ( item )
|
||||
{
|
||||
_detail::Closure* closure;
|
||||
NewClosure( AudioEngine::instance(), SIGNAL( loading( Tomahawk::result_ptr ) ),
|
||||
const_cast<GridItemDelegate*>(this), SLOT( onPlaybackStarted( QPersistentModelIndex ) ), QPersistentModelIndex( index ) );
|
||||
|
||||
closure = NewClosure( AudioEngine::instance(), SIGNAL( loading( Tomahawk::result_ptr ) ),
|
||||
const_cast<GridItemDelegate*>(this), SLOT( onPlaybackStarted( QPersistentModelIndex ) ), QPersistentModelIndex( index ) );
|
||||
m_closures.remove( index );
|
||||
|
||||
closure = NewClosure( AudioEngine::instance(), SIGNAL( started( Tomahawk::result_ptr ) ),
|
||||
const_cast<GridItemDelegate*>(this), SLOT( onPlaylistChanged( QPersistentModelIndex ) ), QPersistentModelIndex( index ) );
|
||||
closure->setAutoDelete( false );
|
||||
m_closures.insertMulti( index, NewClosure( AudioEngine::instance(), SIGNAL( started( Tomahawk::result_ptr ) ),
|
||||
const_cast<GridItemDelegate*>(this), SLOT( onPlaylistChanged( QPersistentModelIndex ) ), QPersistentModelIndex( index ) ) );
|
||||
m_closures.insertMulti( index, NewClosure( AudioEngine::instance(), SIGNAL( stopped() ),
|
||||
const_cast<GridItemDelegate*>(this), SLOT( onPlaylistChanged( QPersistentModelIndex ) ), QPersistentModelIndex( index ) ) );
|
||||
|
||||
foreach ( _detail::Closure* closure, m_closures.values( index ) )
|
||||
closure->setAutoDelete( false );
|
||||
|
||||
connect( AudioEngine::instance(), SIGNAL( stopped() ), SLOT( onPlaybackFinished() ) );
|
||||
|
||||
@@ -421,19 +428,22 @@ GridItemDelegate::doUpdateIndex( const QPersistentModelIndex& idx )
|
||||
|
||||
|
||||
void
|
||||
GridItemDelegate::onScrolled( int dx, int dy )
|
||||
GridItemDelegate::onViewChanged()
|
||||
{
|
||||
foreach ( QWidget* widget, m_spinner.values() )
|
||||
foreach ( const QPersistentModelIndex& index, m_spinner.keys() )
|
||||
{
|
||||
widget->move( widget->pos() + QPoint( dx, dy ) );
|
||||
QRect rect = m_view->visualRect( index );
|
||||
m_spinner.value( index )->move( rect.center() - QPoint( 23, 23 ) );
|
||||
}
|
||||
foreach ( ImageButton* button, m_playButton.values() )
|
||||
foreach ( const QPersistentModelIndex& index, m_playButton.keys() )
|
||||
{
|
||||
button->move( button->pos() + QPoint( dx, dy ) );
|
||||
QRect rect = m_view->visualRect( index );
|
||||
m_playButton.value( index )->move( rect.center() - QPoint( 23, 23 ) );
|
||||
}
|
||||
foreach ( ImageButton* button, m_pauseButton.values() )
|
||||
foreach ( const QPersistentModelIndex& index, m_pauseButton.keys() )
|
||||
{
|
||||
button->move( button->pos() + QPoint( dx, dy ) );
|
||||
QRect rect = m_view->visualRect( index );
|
||||
m_pauseButton.value( index )->move( rect.center() - QPoint( 23, 23 ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,11 +483,19 @@ GridItemDelegate::onPlaylistChanged( const QPersistentModelIndex& index )
|
||||
|
||||
if ( finished )
|
||||
{
|
||||
foreach ( _detail::Closure* closure, m_closures.values( index ) )
|
||||
closure->deleteLater();
|
||||
|
||||
if ( m_pauseButton.contains( index ) )
|
||||
{
|
||||
m_pauseButton[ index ]->deleteLater();
|
||||
m_pauseButton.remove( index );
|
||||
}
|
||||
if ( m_spinner.contains( index ) )
|
||||
{
|
||||
m_spinner[ index ]->deleteLater();
|
||||
m_spinner.remove( index );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -29,6 +29,10 @@ namespace Tomahawk {
|
||||
class PixmapDelegateFader;
|
||||
}
|
||||
|
||||
namespace _detail {
|
||||
class Closure;
|
||||
}
|
||||
|
||||
class QEvent;
|
||||
class QTimeLine;
|
||||
class PlayableProxyModel;
|
||||
@@ -55,7 +59,7 @@ private slots:
|
||||
void modelChanged();
|
||||
void doUpdateIndex( const QPersistentModelIndex& idx );
|
||||
|
||||
void onScrolled( int dx, int dy );
|
||||
void onViewChanged();
|
||||
void onPlaybackStarted( const QPersistentModelIndex& index );
|
||||
void onPlaybackFinished();
|
||||
|
||||
@@ -64,6 +68,7 @@ private slots:
|
||||
|
||||
void fadingFrameChanged( const QPersistentModelIndex& );
|
||||
void fadingFrameFinished( const QPersistentModelIndex& );
|
||||
|
||||
private:
|
||||
QTimeLine* createTimeline( QTimeLine::Direction direction );
|
||||
|
||||
@@ -81,8 +86,8 @@ private:
|
||||
mutable QHash< QPersistentModelIndex, QWidget* > m_spinner;
|
||||
mutable QHash< QPersistentModelIndex, ImageButton* > m_playButton;
|
||||
mutable QHash< QPersistentModelIndex, ImageButton* > m_pauseButton;
|
||||
|
||||
mutable QHash< QPersistentModelIndex, QTimeLine* > m_hoverFaders;
|
||||
mutable QHash< QPersistentModelIndex, _detail::Closure* > m_closures;
|
||||
};
|
||||
|
||||
#endif // GRIDITEMDELEGATE_H
|
||||
|
@@ -77,9 +77,6 @@ GridView::GridView( QWidget* parent )
|
||||
setAutoResize( false );
|
||||
setProxyModel( new PlayableProxyModel( this ) );
|
||||
|
||||
/* m_overlay->setText( tr( "After you have scanned your music collection you will find your latest album additions right here." ) );
|
||||
m_overlay->setText( tr( "This collection doesn't have any recent albums." ) );*/
|
||||
|
||||
connect( this, SIGNAL( doubleClicked( QModelIndex ) ), SLOT( onItemActivated( QModelIndex ) ) );
|
||||
connect( this, SIGNAL( customContextMenuRequested( QPoint ) ), SLOT( onCustomContextMenu( QPoint ) ) );
|
||||
|
||||
@@ -208,6 +205,8 @@ GridView::resizeEvent( QResizeEvent* event )
|
||||
{
|
||||
QListView::resizeEvent( event );
|
||||
layoutItems();
|
||||
|
||||
emit resized();
|
||||
}
|
||||
|
||||
|
||||
|
@@ -78,6 +78,7 @@ public slots:
|
||||
signals:
|
||||
void modelChanged();
|
||||
void scrolledContents( int dx, int dy );
|
||||
void resized();
|
||||
|
||||
protected:
|
||||
virtual void startDrag( Qt::DropActions supportedActions );
|
||||
|
@@ -89,12 +89,6 @@ PlayableItem::PlayableItem( const Tomahawk::query_ptr& query, PlayableItem* pare
|
||||
connect( query.data(), SIGNAL( updated() ),
|
||||
SIGNAL( dataChanged() ) );
|
||||
|
||||
connect( query.data(), SIGNAL( resultsAdded( QList<Tomahawk::result_ptr> ) ),
|
||||
SLOT( onResultsChanged() ) );
|
||||
|
||||
connect( query.data(), SIGNAL( resultsRemoved( Tomahawk::result_ptr ) ),
|
||||
SLOT( onResultsChanged() ) );
|
||||
|
||||
connect( query.data(), SIGNAL( resultsChanged() ),
|
||||
SLOT( onResultsChanged() ) );
|
||||
}
|
||||
@@ -113,12 +107,6 @@ PlayableItem::PlayableItem( const Tomahawk::plentry_ptr& entry, PlayableItem* pa
|
||||
connect( m_query.data(), SIGNAL( updated() ),
|
||||
SIGNAL( dataChanged() ) );
|
||||
|
||||
connect( m_query.data(), SIGNAL( resultsAdded( QList<Tomahawk::result_ptr> ) ),
|
||||
SLOT( onResultsChanged() ) );
|
||||
|
||||
connect( m_query.data(), SIGNAL( resultsRemoved( Tomahawk::result_ptr ) ),
|
||||
SLOT( onResultsChanged() ) );
|
||||
|
||||
connect( m_query.data(), SIGNAL( resultsChanged() ),
|
||||
SLOT( onResultsChanged() ) );
|
||||
}
|
||||
@@ -130,7 +118,7 @@ PlayableItem::init( PlayableItem* parent, int row )
|
||||
m_fetchingMore = false;
|
||||
m_isPlaying = false;
|
||||
m_parent = parent;
|
||||
|
||||
|
||||
if ( parent )
|
||||
{
|
||||
if ( row < 0 )
|
||||
@@ -145,7 +133,7 @@ PlayableItem::init( PlayableItem* parent, int row )
|
||||
|
||||
this->model = parent->model;
|
||||
}
|
||||
|
||||
|
||||
if ( !m_query.isNull() )
|
||||
{
|
||||
onResultsChanged();
|
||||
|
@@ -46,7 +46,7 @@ PlayableModel::PlayableModel( QObject* parent, bool loading )
|
||||
{
|
||||
connect( AudioEngine::instance(), SIGNAL( started( Tomahawk::result_ptr ) ), SLOT( onPlaybackStarted( Tomahawk::result_ptr ) ), Qt::DirectConnection );
|
||||
connect( AudioEngine::instance(), SIGNAL( stopped() ), SLOT( onPlaybackStopped() ), Qt::DirectConnection );
|
||||
|
||||
|
||||
m_header << tr( "Artist" ) << tr( "Title" ) << tr( "Composer" ) << tr( "Album" ) << tr( "Track" ) << tr( "Duration" )
|
||||
<< tr( "Bitrate" ) << tr( "Age" ) << tr( "Year" ) << tr( "Size" ) << tr( "Origin" ) << tr( "Score" ) << tr( "Name" );
|
||||
|
||||
@@ -200,11 +200,11 @@ PlayableModel::queryData( const query_ptr& query, int column, int role ) const
|
||||
case Album:
|
||||
return query->album();
|
||||
break;
|
||||
|
||||
|
||||
case Composer:
|
||||
return query->composer();
|
||||
break;
|
||||
|
||||
|
||||
case Duration:
|
||||
return TomahawkUtils::timeToString( query->duration() );
|
||||
break;
|
||||
@@ -223,7 +223,7 @@ PlayableModel::queryData( const query_ptr& query, int column, int role ) const
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -256,7 +256,7 @@ PlayableModel::queryData( const query_ptr& query, int column, int role ) const
|
||||
case Score:
|
||||
return query->results().first()->score();
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -305,7 +305,7 @@ PlayableModel::data( const QModelIndex& index, int role ) const
|
||||
{
|
||||
return albumData( entry->album(), role );
|
||||
}
|
||||
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
@@ -508,6 +508,7 @@ PlayableModel::mimeData( const QModelIndexList &indexes ) const
|
||||
|
||||
// Ok... we have to use mixed
|
||||
resultData.clear();
|
||||
QDataStream mixedStream( &resultData, QIODevice::WriteOnly );
|
||||
foreach ( const QModelIndex& i, indexes )
|
||||
{
|
||||
if ( i.column() > 0 || indexes.contains( i.parent() ) )
|
||||
@@ -520,22 +521,22 @@ PlayableModel::mimeData( const QModelIndexList &indexes ) const
|
||||
if ( !item->artist().isNull() )
|
||||
{
|
||||
const artist_ptr& artist = item->artist();
|
||||
resultStream << QString( "application/tomahawk.metadata.artist" ) << artist->name();
|
||||
mixedStream << 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();
|
||||
mixedStream << 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 );
|
||||
mixedStream << QString( "application/tomahawk.result.list" ) << qlonglong( &result );
|
||||
}
|
||||
else if ( !item->query().isNull() )
|
||||
{
|
||||
const query_ptr& query = item->query();
|
||||
resultStream << QString( "application/tomahawk.query.list" ) << qlonglong( &query );
|
||||
mixedStream << QString( "application/tomahawk.query.list" ) << qlonglong( &query );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -576,20 +577,6 @@ PlayableModel::queries() const
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
PlayableModel::insertInternal( const T& item, int row )
|
||||
{
|
||||
if ( item.isNull() )
|
||||
return;
|
||||
|
||||
QList< T > list;
|
||||
list << item;
|
||||
|
||||
insert( list, row );
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
PlayableModel::insertInternal( const QList< T >& items, int row )
|
||||
@@ -598,7 +585,7 @@ PlayableModel::insertInternal( const QList< T >& items, int row )
|
||||
{
|
||||
emit trackCountChanged( rowCount( QModelIndex() ) );
|
||||
emit itemCountChanged( rowCount( QModelIndex() ) );
|
||||
|
||||
|
||||
finishLoading();
|
||||
return;
|
||||
}
|
||||
@@ -633,12 +620,12 @@ PlayableModel::insertInternal( const QList< T >& items, int row )
|
||||
void
|
||||
PlayableModel::remove( int row, bool moreToCome )
|
||||
{
|
||||
remove( index( row, 0, QModelIndex() ), moreToCome );
|
||||
removeIndex( index( row, 0, QModelIndex() ), moreToCome );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::remove( const QModelIndex& index, bool moreToCome )
|
||||
PlayableModel::removeIndex( const QModelIndex& index, bool moreToCome )
|
||||
{
|
||||
if ( QThread::currentThread() != thread() )
|
||||
{
|
||||
@@ -666,7 +653,7 @@ PlayableModel::remove( const QModelIndex& index, bool moreToCome )
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::remove( const QList<QModelIndex>& indexes )
|
||||
PlayableModel::removeIndexes( const QList<QModelIndex>& indexes )
|
||||
{
|
||||
QList<QPersistentModelIndex> pil;
|
||||
foreach ( const QModelIndex& idx, indexes )
|
||||
@@ -674,12 +661,12 @@ PlayableModel::remove( const QList<QModelIndex>& indexes )
|
||||
pil << idx;
|
||||
}
|
||||
|
||||
remove( pil );
|
||||
removeIndexes( pil );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::remove( const QList<QPersistentModelIndex>& indexes )
|
||||
PlayableModel::removeIndexes( const QList<QPersistentModelIndex>& indexes )
|
||||
{
|
||||
QList<QPersistentModelIndex> finalIndexes;
|
||||
foreach ( const QPersistentModelIndex index, indexes )
|
||||
@@ -691,7 +678,7 @@ PlayableModel::remove( const QList<QPersistentModelIndex>& indexes )
|
||||
|
||||
for ( int i = 0; i < finalIndexes.count(); i++ )
|
||||
{
|
||||
remove( finalIndexes.at( i ), i + 1 != finalIndexes.count() );
|
||||
removeIndex( finalIndexes.at( i ), i + 1 != finalIndexes.count() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -828,84 +815,102 @@ PlayableModel::itemFromIndex( const QModelIndex& index ) const
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::append( const Tomahawk::artist_ptr& artist )
|
||||
PlayableModel::appendArtist( const Tomahawk::artist_ptr& artist )
|
||||
{
|
||||
insert( artist, rowCount( QModelIndex() ) );
|
||||
QList< artist_ptr > artists;
|
||||
artists << artist;
|
||||
|
||||
appendArtists( artists );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::append( const Tomahawk::album_ptr& album )
|
||||
PlayableModel::appendAlbum( const Tomahawk::album_ptr& album )
|
||||
{
|
||||
insert( album, rowCount( QModelIndex() ) );
|
||||
QList< album_ptr > albums;
|
||||
albums << album;
|
||||
|
||||
appendAlbums( albums );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::append( const Tomahawk::query_ptr& query )
|
||||
PlayableModel::appendQuery( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
insert( query, rowCount( QModelIndex() ) );
|
||||
QList< query_ptr > queries;
|
||||
queries << query;
|
||||
|
||||
appendQueries( queries );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::append( const QList< Tomahawk::artist_ptr >& artists )
|
||||
PlayableModel::appendArtists( const QList< Tomahawk::artist_ptr >& artists )
|
||||
{
|
||||
insert( artists, rowCount( QModelIndex() ) );
|
||||
insertArtists( artists, rowCount( QModelIndex() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::append( const QList< Tomahawk::album_ptr >& albums )
|
||||
PlayableModel::appendAlbums( const QList< Tomahawk::album_ptr >& albums )
|
||||
{
|
||||
insert( albums, rowCount( QModelIndex() ) );
|
||||
insertAlbums( albums, rowCount( QModelIndex() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::append( const QList< Tomahawk::query_ptr >& queries )
|
||||
PlayableModel::appendQueries( const QList< Tomahawk::query_ptr >& queries )
|
||||
{
|
||||
insert( queries, rowCount( QModelIndex() ) );
|
||||
insertQueries( queries, rowCount( QModelIndex() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::insert( const Tomahawk::artist_ptr& artist, int row )
|
||||
PlayableModel::insertArtist( const Tomahawk::artist_ptr& artist, int row )
|
||||
{
|
||||
insertInternal( artist, row );
|
||||
QList< artist_ptr > artists;
|
||||
artists << artist;
|
||||
|
||||
insertArtists( artists, row );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::insert( const Tomahawk::album_ptr& album, int row )
|
||||
PlayableModel::insertAlbum( const Tomahawk::album_ptr& album, int row )
|
||||
{
|
||||
insertInternal( album, row );
|
||||
QList< album_ptr > albums;
|
||||
albums << album;
|
||||
|
||||
insertAlbums( albums, row );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::insert( const Tomahawk::query_ptr& query, int row )
|
||||
PlayableModel::insertQuery( const Tomahawk::query_ptr& query, int row )
|
||||
{
|
||||
insertInternal( query, row );
|
||||
QList< query_ptr > queries;
|
||||
queries << query;
|
||||
|
||||
insertQueries( queries, row );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::insert( const QList< Tomahawk::artist_ptr >& artists, int row )
|
||||
PlayableModel::insertArtists( const QList< Tomahawk::artist_ptr >& artists, int row )
|
||||
{
|
||||
insertInternal( artists, row );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::insert( const QList< Tomahawk::album_ptr >& albums, int row )
|
||||
PlayableModel::insertAlbums( const QList< Tomahawk::album_ptr >& albums, int row )
|
||||
{
|
||||
insertInternal( albums, row );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::insert( const QList< Tomahawk::query_ptr >& queries, int row )
|
||||
PlayableModel::insertQueries( const QList< Tomahawk::query_ptr >& queries, int row )
|
||||
{
|
||||
insertInternal( queries, row );
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user