mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-09-06 12:10:47 +02:00
Compare commits
151 Commits
linkparser
...
unify-down
Author | SHA1 | Date | |
---|---|---|---|
|
34448b1b46 | ||
|
4408ba275c | ||
|
dfd71d7010 | ||
|
170e2e1c86 | ||
|
0047763188 | ||
|
85657e40a6 | ||
|
af459afb0b | ||
|
5bbc39e6a5 | ||
|
c88640268a | ||
|
8749a04e23 | ||
|
d45917d14a | ||
|
c87b1390e5 | ||
|
bf28f6856e | ||
|
ceab0f9cf2 | ||
|
a562e75937 | ||
|
81eb226146 | ||
|
ec88cf27f3 | ||
|
931562fbe5 | ||
|
77593e32a7 | ||
|
bac38e4555 | ||
|
980ee97c97 | ||
|
26ad51f4b8 | ||
|
21bdb0bc89 | ||
|
0a560f2f27 | ||
|
9c9f5e4dae | ||
|
fb38735936 | ||
|
c62ae52bfe | ||
|
0341492069 | ||
|
879df894c3 | ||
|
0c9f1be2c8 | ||
|
f7a3d441a1 | ||
|
e9a1135525 | ||
|
bdce4f7636 | ||
|
de65e19cb7 | ||
|
ce3647a4a6 | ||
|
f498570a0e | ||
|
9a741cd2db | ||
|
102c9c6846 | ||
|
1fa35ae827 | ||
|
26c0f35d21 | ||
|
9acbb48659 | ||
|
cc9f287b41 | ||
|
99abd7434b | ||
|
f38f3ca367 | ||
|
773ecea0da | ||
|
620d3fe3fc | ||
|
8679fd5055 | ||
|
d7eccea4c0 | ||
|
2ab9418a9e | ||
|
285333d43b | ||
|
3bcf854a4f | ||
|
61a15cafac | ||
|
2d141ccb5e | ||
|
4c023b7d2f | ||
|
ceb5dc6aa4 | ||
|
13fa9c7c53 | ||
|
4c946b304c | ||
|
5075c9ddbf | ||
|
8b3a916aa6 | ||
|
cd412add8f | ||
|
68851843f5 | ||
|
af8811af30 | ||
|
fa38ed5e91 | ||
|
b7ff630808 | ||
|
196256d77b | ||
|
79cd3a7f0a | ||
|
f0f45673b1 | ||
|
86cd7c1be0 | ||
|
f74c6ae429 | ||
|
015b24479c | ||
|
8b904cf806 | ||
|
175e498c43 | ||
|
65908f9dfa | ||
|
3c9deb6389 | ||
|
978c1e58de | ||
|
0722dd7812 | ||
|
ff34afb4e3 | ||
|
bd607b6c54 | ||
|
81f7e3f8f4 | ||
|
798ca62190 | ||
|
f2631cda74 | ||
|
4813698a9a | ||
|
dc80d19a08 | ||
|
93745b19ef | ||
|
1b7b7ca4b3 | ||
|
3808e230d4 | ||
|
0bdb8061e2 | ||
|
87278456f4 | ||
|
a5693d6663 | ||
|
6416b34e8c | ||
|
f95bd4aab8 | ||
|
996d112ebb | ||
|
fc413ac103 | ||
|
2020aad725 | ||
|
198201aec2 | ||
|
6b84630ba1 | ||
|
205dfca60d | ||
|
ca2da81132 | ||
|
08004ddbd4 | ||
|
4dadbb5acd | ||
|
dee504c997 | ||
|
81dae62349 | ||
|
3c00f36df6 | ||
|
f13ea2f6df | ||
|
2f4eb75745 | ||
|
942eded60d | ||
|
1b2ec05ea3 | ||
|
3875b10bb4 | ||
|
f396f59922 | ||
|
7271a95942 | ||
|
9737b7a8bc | ||
|
d87f966d9e | ||
|
cb3ccd5a76 | ||
|
f81858e28a | ||
|
8fbc0319ba | ||
|
e7d83835d2 | ||
|
6035889b90 | ||
|
2bb0113515 | ||
|
8ee8721dda | ||
|
293b3b1b4f | ||
|
ba0cc1a00c | ||
|
759bfbe63b | ||
|
e3877bf0bf | ||
|
f1cf645f31 | ||
|
62dea3a196 | ||
|
09f68fa2f5 | ||
|
944827c48c | ||
|
771b2f5ae1 | ||
|
d50c16740a | ||
|
a5968b58e5 | ||
|
5f20308177 | ||
|
1710813dc8 | ||
|
7fd306ca07 | ||
|
bdaf1ef2f4 | ||
|
c068d8c9e3 | ||
|
1e6b8b3747 | ||
|
0535d09f08 | ||
|
c93302c563 | ||
|
1192c668b0 | ||
|
53b27d0ea1 | ||
|
9ebe155313 | ||
|
ddf030037e | ||
|
5d950bd139 | ||
|
eab1ccee74 | ||
|
1025e77d3e | ||
|
53de4319b6 | ||
|
4eee01d8bf | ||
|
5bd69fe09c | ||
|
1b0517efc5 | ||
|
e6a8a41c31 | ||
|
193beda2bc |
@@ -179,7 +179,7 @@ if( NOT BUILD_WITH_QT4 )
|
||||
set(HAVE_X11 FALSE)
|
||||
endif()
|
||||
|
||||
message(STATUS "Found Qt5! Be aware that Qt5-support is still experimental and not officially supported!")
|
||||
message(STATUS "Found Qt5!")
|
||||
|
||||
if( UNIX AND NOT APPLE )
|
||||
# We need this to find the paths to qdbusxml2cpp and co
|
||||
@@ -228,6 +228,10 @@ endif()
|
||||
if( NOT Qt5Core_DIR )
|
||||
message(STATUS "Could not find Qt5, searching for Qt4 instead...")
|
||||
|
||||
if(NOT FORCE_QT4)
|
||||
message(FATAL_ERROR "Qt4 support is broken, if you plan to fix it, add -DFORCE_QT4=ON to your cmake arguments otherwise you should compile Tomahawk with Qt5")
|
||||
endif()
|
||||
|
||||
set(NEEDED_QT4_COMPONENTS "QtCore" "QtXml" "QtNetwork")
|
||||
if( BUILD_GUI )
|
||||
list(APPEND NEEDED_QT4_COMPONENTS "QtGui" "QtWebkit" "QtUiTools" "QtSvg")
|
||||
@@ -307,11 +311,10 @@ else()
|
||||
message(STATUS "${CMAKE_CXX_COMPILER} does not support C++11, please use a
|
||||
different compiler")
|
||||
endif()
|
||||
if(LIBCPP_FOUND AND APPLE)
|
||||
if(("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR APPLE) AND LIBCPP_FOUND)
|
||||
tomahawk_add_cxx_flags( "-stdlib=libc++" )
|
||||
endif()
|
||||
|
||||
|
||||
macro_optional_find_package(Echonest 2.3.0)
|
||||
macro_log_feature(ECHONEST_FOUND "Echonest" "Qt library for communicating with The Echo Nest" "http://projects.kde.org/libechonest" TRUE "" "libechonest 2.3.0 is needed for dynamic playlists and the infosystem")
|
||||
|
||||
@@ -404,7 +407,7 @@ if( WIN32 )
|
||||
endif( WIN32 )
|
||||
|
||||
if( WIN32 OR APPLE )
|
||||
macro_optional_find_package(LibsnoreQt5 0.5.70 QUIET)
|
||||
macro_optional_find_package(LibsnoreQt5 0.6.0 QUIET)
|
||||
macro_log_feature(LibsnoreQt5_FOUND "Libsnore" "Library for notifications" "https://projects.kde.org/projects/playground/libs/snorenotify" FALSE "" "")
|
||||
endif()
|
||||
|
||||
|
@@ -18,11 +18,10 @@
|
||||
!ifndef MINGW_ROOT
|
||||
!define MINGW_ROOT "/usr/i686-w64-mingw32/sys-root/mingw"
|
||||
!endif
|
||||
|
||||
!define APPLICATION_NAME "Tomahawk"
|
||||
!define TARGET_NAME "tomahawk"
|
||||
!define APPLICATION_NAME "@CPACK_PACKAGE_NAME@"
|
||||
!define TARGET_NAME "@CPACK_PACKAGE_TARGET_NAME@"
|
||||
;define app id needed for Windows 8 notifications
|
||||
!define AppUserModelId @TOMAHAWK_APPLICATION_PACKAGE_NAME@
|
||||
!define AppUserModelId "@TOMAHAWK_APPLICATION_PACKAGE_NAME@"
|
||||
|
||||
!define MINGW_BIN "${MINGW_ROOT}/bin"
|
||||
!define MINGW_LIB "${MINGW_ROOT}/lib"
|
||||
@@ -347,105 +346,108 @@ Section "${APPLICATION_NAME}" SEC_TOMAHAWK_PLAYER
|
||||
File "${QT_DLL_PATH}\icudata56.dll"
|
||||
File "${QT_DLL_PATH}\icui18n56.dll"
|
||||
|
||||
;SQLite driver
|
||||
SetOutPath "$INSTDIR\sqldrivers"
|
||||
File "${SQLITE_DLL_PATH}\qsqlite.dll"
|
||||
SetOutPath "$INSTDIR"
|
||||
File "${MINGW_BIN}\libsqlite3-0.dll"
|
||||
;SQLite driver
|
||||
SetOutPath "$INSTDIR\sqldrivers"
|
||||
File "${SQLITE_DLL_PATH}\qsqlite.dll"
|
||||
SetOutPath "$INSTDIR"
|
||||
File "${MINGW_BIN}\libsqlite3-0.dll"
|
||||
|
||||
;Qt platform plugins
|
||||
SetOutPath "$INSTDIR\platforms"
|
||||
File "${MINGW_LIB}/qt5/plugins/platforms/qwindows.dll"
|
||||
SetOutPath "$INSTDIR"
|
||||
;Qt platform plugins
|
||||
SetOutPath "$INSTDIR\platforms"
|
||||
File "${MINGW_LIB}/qt5/plugins/platforms/qwindows.dll"
|
||||
SetOutPath "$INSTDIR"
|
||||
|
||||
;Image plugins
|
||||
SetOutPath "$INSTDIR\imageformats"
|
||||
File "${IMAGEFORMATS_DLL_PATH}\qgif.dll"
|
||||
File "${IMAGEFORMATS_DLL_PATH}\qjpeg.dll"
|
||||
File "${IMAGEFORMATS_DLL_PATH}\qsvg.dll"
|
||||
SetOutPath "$INSTDIR"
|
||||
;Image plugins
|
||||
SetOutPath "$INSTDIR\imageformats"
|
||||
File "${IMAGEFORMATS_DLL_PATH}\qgif.dll"
|
||||
File "${IMAGEFORMATS_DLL_PATH}\qjpeg.dll"
|
||||
File "${IMAGEFORMATS_DLL_PATH}\qsvg.dll"
|
||||
SetOutPath "$INSTDIR"
|
||||
|
||||
;Qt qml plugins
|
||||
SetOutPath "$INSTDIR\QtQuick.2"
|
||||
File /r /x *.debug "${QT_QML_PATH}\QtQuick.2\*"
|
||||
SetOutPath "$INSTDIR\QtQuick\Window.2"
|
||||
File /r /x *.debug "${QT_QML_PATH}\QtQuick\Window.2\*"
|
||||
SetOutPath "$INSTDIR"
|
||||
;Qt qml plugins
|
||||
SetOutPath "$INSTDIR\QtQuick.2"
|
||||
File /r /x *.debug "${QT_QML_PATH}\QtQuick.2\*"
|
||||
SetOutPath "$INSTDIR\QtQuick\Window.2"
|
||||
File /r /x *.debug "${QT_QML_PATH}\QtQuick\Window.2\*"
|
||||
SetOutPath "$INSTDIR"
|
||||
|
||||
;Cygwin/c++ stuff
|
||||
File "${MINGW_BIN}\libgcc_s_sjlj-1.dll"
|
||||
File "${MINGW_BIN}\libstdc++-6.dll"
|
||||
;Cygwin/c++ stuff
|
||||
File "${MINGW_BIN}\libgcc_s_sjlj-1.dll"
|
||||
File "${MINGW_BIN}\libstdc++-6.dll"
|
||||
|
||||
;VLC
|
||||
File "${VLC_BIN}\libvlc.dll"
|
||||
File "${VLC_BIN}\libvlccore.dll"
|
||||
SetOutPath "$INSTDIR\plugins"
|
||||
File /r "${VLC_PLUGIN_PATH}\*.dll"
|
||||
SetOutPath "$INSTDIR"
|
||||
;VLC
|
||||
File "${VLC_BIN}\libvlc.dll"
|
||||
File "${VLC_BIN}\libvlccore.dll"
|
||||
SetOutPath "$INSTDIR\plugins"
|
||||
File /r "${VLC_PLUGIN_PATH}\*.dll"
|
||||
SetOutPath "$INSTDIR"
|
||||
|
||||
; Other
|
||||
File "${MINGW_BIN}\libtag.dll"
|
||||
File "${MINGW_BIN}\libpng16-16.dll"
|
||||
File "${MINGW_BIN}\libjpeg-8.dll"
|
||||
File "${MINGW_BIN}\zlib1.dll"
|
||||
File "${MINGW_BIN}\libfreetype-6.dll"
|
||||
File "${MINGW_BIN}\libglib-2.0-0.dll"
|
||||
File "${MINGW_BIN}\libharfbuzz-0.dll"
|
||||
; Other
|
||||
File "${MINGW_BIN}\libtag.dll"
|
||||
File "${MINGW_BIN}\libpng16-16.dll"
|
||||
File "${MINGW_BIN}\libjpeg-8.dll"
|
||||
File "${MINGW_BIN}\zlib1.dll"
|
||||
File "${MINGW_BIN}\libfreetype-6.dll"
|
||||
File "${MINGW_BIN}\libglib-2.0-0.dll"
|
||||
File "${MINGW_BIN}\libharfbuzz-0.dll"
|
||||
|
||||
File "${MINGW_BIN}\libechonest5.dll"
|
||||
File "${MINGW_BIN}\liblastfm5.dll"
|
||||
File "${MINGW_BIN}\libquazip5.dll"
|
||||
File "${MINGW_BIN}\libqt5keychain.dll"
|
||||
; ANGLE
|
||||
File "${MINGW_BIN}\D3DCompiler_43.dll"
|
||||
|
||||
; GnuTLS
|
||||
File "${MINGW_BIN}\libgnutls-28.dll"
|
||||
File "${MINGW_BIN}\libtasn1-6.dll"
|
||||
File "${MINGW_BIN}\libgmp-10.dll"
|
||||
File "${MINGW_BIN}\libhogweed-2-4.dll"
|
||||
File "${MINGW_BIN}\libintl-8.dll"
|
||||
File "${MINGW_BIN}\libnettle-4-6.dll"
|
||||
File "${MINGW_BIN}\libp11-kit-0.dll"
|
||||
File "${MINGW_BIN}\libffi-6.dll"
|
||||
File "${MINGW_BIN}\libechonest5.dll"
|
||||
File "${MINGW_BIN}\liblastfm5.dll"
|
||||
File "${MINGW_BIN}\libquazip5.dll"
|
||||
File "${MINGW_BIN}\libqt5keychain.dll"
|
||||
|
||||
; Snorenotify
|
||||
File "${MINGW_BIN}\SnoreToast.exe"
|
||||
File "${MINGW_BIN}\libsnore-qt5.dll"
|
||||
File "${MINGW_BIN}\libsnoresettings-qt5.dll"
|
||||
File "${MINGW_BIN}\snoresettings.exe"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_backend_growl.dll"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_settings_backend_growl.dll"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_backend_snarl.dll"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_settings_backend_snarl.dll"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_backend_snore.dll"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_settings_backend_snore.dll"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_backend_windowstoast.dll"
|
||||
; GnuTLS
|
||||
File "${MINGW_BIN}\libgnutls-28.dll"
|
||||
File "${MINGW_BIN}\libtasn1-6.dll"
|
||||
File "${MINGW_BIN}\libgmp-10.dll"
|
||||
File "${MINGW_BIN}\libhogweed-4-1.dll"
|
||||
File "${MINGW_BIN}\libintl-8.dll"
|
||||
File "${MINGW_BIN}\libnettle-6-1.dll"
|
||||
File "${MINGW_BIN}\libp11-kit-0.dll"
|
||||
File "${MINGW_BIN}\libffi-6.dll"
|
||||
|
||||
; Snoregrowl
|
||||
File "${MINGW_BIN}\libsnoregrowl++.dll"
|
||||
File "${MINGW_BIN}\libsnoregrowl.dll"
|
||||
; Snorenotify
|
||||
File "${MINGW_BIN}\SnoreToast.exe"
|
||||
File "${MINGW_BIN}\libsnore-qt5.dll"
|
||||
File "${MINGW_BIN}\libsnoresettings-qt5.dll"
|
||||
File "${MINGW_BIN}\snoresettings.exe"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_backend_growl.dll"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_settings_backend_growl.dll"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_backend_snarl.dll"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_settings_backend_snarl.dll"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_backend_snore.dll"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_settings_backend_snore.dll"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_backend_windowstoast.dll"
|
||||
|
||||
; Snoregrowl
|
||||
File "${MINGW_BIN}\libsnoregrowl++.dll"
|
||||
File "${MINGW_BIN}\libsnoregrowl.dll"
|
||||
|
||||
; Jabber
|
||||
File "${MINGW_BIN}\libjreen-qt5.dll"
|
||||
File "${MINGW_BIN}\libidn-11.dll"
|
||||
File "${MINGW_BIN}\libgsasl-7.dll"
|
||||
File "${MINGW_BIN}\libqca-qt5.dll"
|
||||
SetOutPath "$INSTDIR\crypto"
|
||||
File "${MINGW_LIB}\qca-qt5\crypto\libqca-ossl.dll"
|
||||
SetOutPath "$INSTDIR"
|
||||
File "${MINGW_BIN}\libssl-10.dll"
|
||||
File "${MINGW_BIN}\libcrypto-10.dll"
|
||||
File "${MINGW_BIN}\libjreen-qt5.dll"
|
||||
File "${MINGW_BIN}\libidn-11.dll"
|
||||
File "${MINGW_BIN}\libgsasl-7.dll"
|
||||
File "${MINGW_BIN}\libqca-qt5.dll"
|
||||
SetOutPath "$INSTDIR\crypto"
|
||||
File "${MINGW_LIB}\qca-qt5\crypto\libqca-ossl.dll"
|
||||
SetOutPath "$INSTDIR"
|
||||
File "${MINGW_BIN}\libssl-10.dll"
|
||||
File "${MINGW_BIN}\libcrypto-10.dll"
|
||||
|
||||
; LucenePlusPlus
|
||||
File "${MINGW_BIN}\liblucene++.dll"
|
||||
File "${MINGW_BIN}\libboost_system-mt.dll"
|
||||
File "${MINGW_BIN}\libboost_filesystem-mt.dll"
|
||||
File "${MINGW_BIN}\libboost_iostreams-mt.dll"
|
||||
File "${MINGW_BIN}\libboost_regex-mt.dll"
|
||||
File "${MINGW_BIN}\libboost_thread-mt.dll"
|
||||
File "${MINGW_BIN}\libbz2-1.dll"
|
||||
; LucenePlusPlus
|
||||
File "${MINGW_BIN}\liblucene++.dll"
|
||||
File "${MINGW_BIN}\libboost_system-mt.dll"
|
||||
File "${MINGW_BIN}\libboost_filesystem-mt.dll"
|
||||
File "${MINGW_BIN}\libboost_iostreams-mt.dll"
|
||||
File "${MINGW_BIN}\libboost_regex-mt.dll"
|
||||
File "${MINGW_BIN}\libboost_thread-mt.dll"
|
||||
File "${MINGW_BIN}\libbz2-1.dll"
|
||||
|
||||
File "${MINGW_BIN}\libqtsparkle-qt5.dll"
|
||||
File "${MINGW_BIN}\libKF5Attica.dll"
|
||||
File "${MINGW_BIN}\libqtsparkle-qt5.dll"
|
||||
File "${MINGW_BIN}\libKF5Attica.dll"
|
||||
SectionEnd
|
||||
|
||||
SectionGroup "Shortcuts"
|
||||
|
@@ -1,6 +1,7 @@
|
||||
Version 0.9.0:
|
||||
* Resolved various playback issues by switching to a new audio engine.
|
||||
* Fixed collection sorting.
|
||||
* Fixed volume/mute state not being reset correctly on startup.
|
||||
|
||||
Version 0.8.4:
|
||||
* Fixed drag & drop issues on sidebar.
|
||||
|
@@ -2,7 +2,7 @@ INCLUDE( InstallRequiredSystemLibraries )
|
||||
|
||||
SET( CPACK_PACKAGE_CONTACT "Dominik Schmidt <domme@tomahawk-player.org>" )
|
||||
|
||||
SET( CPACK_PACKAGE_FILE_NAME "${TOMAHAWK_APPLICATION_NAME}-${TOMAHAWK_VERSION}" ) # Package file name without extension. Also a directory of installer cmake-2.5.0-Linux-i686
|
||||
SET( CPACK_PACKAGE_FILE_NAME "${TOMAHAWK_TARGET_NAME}-${TOMAHAWK_VERSION}" ) # Package file name without extension. Also a directory of installer cmake-2.5.0-Linux-i686
|
||||
|
||||
# CPACK_GENERATOR CPack generator to be used STGZ;TGZ;TZ
|
||||
# CPACK_INCLUDE_TOPLEVEL_DIRECTORY Controls whether CPack adds a top-level directory, usually of the form ProjectName-Version-OS, to the top of package tree. 0 to disable, 1 to enable
|
||||
@@ -13,7 +13,9 @@ SET( CPACK_PACKAGE_DESCRIPTION_SUMMARY ${TOMAHAWK_DESCRIPTION_SUMMARY} ) # Des
|
||||
SET( CPACK_PACKAGE_INSTALL_DIRECTORY ${TOMAHAWK_APPLICATION_NAME} ) # Installation directory on the target system -> C:\Program Files\fellody
|
||||
SET( CPACK_PACKAGE_INSTALL_REGISTRY_KEY ${TOMAHAWK_APPLICATION_NAME} ) # Registry key used when installing this project CMake 2.5.0
|
||||
SET( CPACK_PACKAGE_NAME ${TOMAHAWK_APPLICATION_NAME} ) # Package name, defaults to the project name
|
||||
SET( CPACK_PACKAGE_TARGET_NAME ${TOMAHAWK_TARGET_NAME} ) # Used to build library and executable names
|
||||
SET( CPACK_PACKAGE_VENDOR ${TOMAHAWK_ORGANIZATION_NAME} ) # Package vendor name
|
||||
SET( TOMAHAWK_APPLICATION_PACKAGE_NAME ${TOMAHAWK_APPLICATION_PACKAGE_NAME} )
|
||||
SET( CPACK_PACKAGE_VERSION_MAJOR ${TOMAHAWK_VERSION_MAJOR} )
|
||||
SET( CPACK_PACKAGE_VERSION_MINOR ${TOMAHAWK_VERSION_MINOR} )
|
||||
SET( CPACK_PACKAGE_VERSION_PATCH ${TOMAHAWK_VERSION_PATCH} )
|
||||
|
@@ -3,8 +3,6 @@
|
||||
set( TOMAHAWK_QT5 @TOMAHAWK_QT5@ )
|
||||
|
||||
if(TOMAHAWK_QT5)
|
||||
message(STATUS "Found Qt5! Be aware that Qt5-support is still experimental and not officially supported!")
|
||||
|
||||
# CMAKE 2.8.13+/3.0.0+ requires these for IMPORTed targets
|
||||
find_package(Qt5Core REQUIRED)
|
||||
find_package(Qt5Concurrent REQUIRED)
|
||||
|
@@ -46,7 +46,7 @@ CERT_SIGNER=$2
|
||||
cd ..
|
||||
if [ -f ~/sign_step.sh ];
|
||||
then
|
||||
~/sign_step.sh "$CERT_SIGNER" "${TARGET_NAME}.app" || true
|
||||
~/sign_step.sh "$CERT_SIGNER" "${TARGET_NAME}.app"
|
||||
fi
|
||||
|
||||
header "Creating DMG"
|
||||
|
@@ -9,19 +9,20 @@ fi
|
||||
|
||||
rm -rvf vlc/
|
||||
|
||||
VLC_TARBALL="vlc.tar.bz2"
|
||||
|
||||
echo "Download phonon archive..."
|
||||
# wget -c "http://downloads.sourceforge.net/project/vlc/1.1.9/win32/vlc-1.1.9-win32.7z?r=http%3A%2F%2Fwww.videolan.org%2Fvlc%2Fdownload-windows.html&ts=1306272584&use_mirror=leaseweb"
|
||||
# wget -c "http://download.tomahawk-player.org/tomahawk-vlc-0.1.zip"
|
||||
# wget -c http://people.videolan.org/~jb/phonon/phonon-vlc-last.7z
|
||||
# wget -c http://people.videolan.org/~jb/phonon/phonon_phonon-vlc_20111128.7z
|
||||
wget -c http://download.tomahawk-player.org/test/vlc.tar.bz2
|
||||
wget -c "http://download.tomahawk-player.org/test/$VLC_TARBALL"
|
||||
|
||||
echo "Extract binary..."
|
||||
# 7z x phonon*.7z
|
||||
# mv -v vlc-*/ vlc/
|
||||
# unzip tomahawk-vlc-0.1.zip
|
||||
tar xvjf vlc.tar.bz2
|
||||
tar xvjf "$VLC_TARBALL"
|
||||
|
||||
# echo "Download phonon_vlc_no_video.dll..."
|
||||
# wget -c http://people.videolan.org/~jb/phonon/phonon_vlc_no_video.dll
|
||||
@@ -72,7 +73,9 @@ rm -rvf \
|
||||
**/libi420* \
|
||||
**/libi422* \
|
||||
mux/ \
|
||||
stream_filter/ \
|
||||
stream_filter/*dash* \
|
||||
stream_filter/*smooth* \
|
||||
stream_filter/*record* \
|
||||
**/libtheora_plugin* \
|
||||
**/liblibbluray_plugin* \
|
||||
**/libdtv_plugin* \
|
||||
|
13
data/images/folder.svg
Normal file
13
data/images/folder.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="86px" height="86px" viewBox="0 0 86 86" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
||||
<title>folder</title>
|
||||
<description>Created with Sketch (http://www.bohemiancoding.com/sketch)</description>
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
||||
<g id="folder" sketch:type="MSLayerGroup" transform="translate(0.000000, 13.000000)" fill="#000000">
|
||||
<g id="Page-1" sketch:type="MSShapeGroup">
|
||||
<path d="M84.1450038,10.4833376 C82.8248024,9.1092149 80.9427764,8.3195294 78.9789985,8.3195294 L72.233622,8.3195294 L34.4730823,8.3195294 L34.4730823,7.0184614 C34.4730823,3.1483061 31.3247762,0 27.4563602,0 L10.1441555,0 C6.27226058,0 3.12569415,3.1500456 3.12569415,7.0184614 L3.12569415,9.4918821 C1.2088801,10.761641 0,12.9237099 0,15.3362515 L0,54.4987445 C0,54.5057021 0,54.5178779 0.0017394,54.5265748 L0,54.5439688 C0,58.3897726 3.14656684,61.5154666 7.0184614,61.5154666 L72.2336242,61.5154666 C72.4736608,61.5154666 72.7102186,61.5050302 72.9432977,61.4789393 C72.9850432,61.4771999 73.028528,61.4650241 73.0702735,61.4615453 C73.2616071,61.4389332 73.4529406,61.4145816 73.6390559,61.3745755 C73.6686257,61.3693573 73.6947166,61.3606604 73.7242863,61.3519634 C73.9225774,61.3119573 74.1208685,61.2597754 74.3139414,61.200636 C74.3243778,61.1954178 74.3348142,61.191939 74.3452506,61.1884602 C76.756053,60.4300837 78.5998126,58.4123847 79.1059765,55.9198305 C79.1077159,55.912873 79.1077159,55.9024366 79.1077159,55.895479 C79.1512008,55.6937091 79.18251,55.4919392 79.2051221,55.2797329 C79.2103403,55.2240723 79.2155585,55.1684116 79.2190373,55.1092721 C79.2277343,55.0136054 79.2433888,54.9266356 79.2451282,54.8309688 L85.9539776,15.7937099 L85.9939837,15.4127822 C86.0705187,13.5587047 85.4147685,11.8086925 84.1450038,10.4833376 C84.1450038,10.4833376 85.4147685,11.8086925 84.1450038,10.4833376 L84.1450038,10.4833376" id="Shape"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
@@ -42,6 +42,8 @@ Tomahawk.apiVersion = "0.2.2";
|
||||
//Statuses considered a success for HTTP request
|
||||
var httpSuccessStatuses = [200, 201];
|
||||
|
||||
Tomahawk.error = console.error;
|
||||
|
||||
// install RSVP error handler for uncaught(!) errors
|
||||
RSVP.on('error', function (reason) {
|
||||
var resolverName = "";
|
||||
@@ -49,9 +51,9 @@ RSVP.on('error', function (reason) {
|
||||
resolverName = Tomahawk.resolver.instance.settings.name + " - ";
|
||||
}
|
||||
if (reason) {
|
||||
console.error(resolverName + 'Uncaught error:', reason);
|
||||
Tomahawk.error(resolverName + 'Uncaught error:', reason);
|
||||
} else {
|
||||
console.error(resolverName + 'Uncaught error: error thrown from RSVP but it was empty');
|
||||
Tomahawk.error(resolverName + 'Uncaught error: error thrown from RSVP but it was empty');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -273,30 +275,42 @@ Tomahawk.Resolver = {
|
||||
getStreamUrl: function (params) {
|
||||
return params;
|
||||
},
|
||||
resolve: function() {
|
||||
},
|
||||
_adapter_resolve: function (params) {
|
||||
return RSVP.Promise.resolve(this.resolve(params)).then(function (results) {
|
||||
return {
|
||||
'tracks': results
|
||||
};
|
||||
if(Array.isArray(results)) {
|
||||
return {
|
||||
'tracks': results
|
||||
};
|
||||
}
|
||||
|
||||
return results;
|
||||
});
|
||||
},
|
||||
|
||||
_adapter_search: function (params) {
|
||||
return RSVP.Promise.resolve(this.search(params)).then(function (results) {
|
||||
return {
|
||||
'tracks': results
|
||||
};
|
||||
if(Array.isArray(results)) {
|
||||
return {
|
||||
'tracks': results
|
||||
};
|
||||
}
|
||||
|
||||
return results;
|
||||
});
|
||||
},
|
||||
|
||||
_adapter_testConfig: function (config) {
|
||||
return RSVP.Promise.resolve(this.testConfig(config)).then(function () {
|
||||
return {result: Tomahawk.ConfigTestResultType.Success};
|
||||
return RSVP.Promise.resolve(this.testConfig(config)).then(function (results) {
|
||||
results = results || Tomahawk.ConfigTestResultType.Success;
|
||||
return results;
|
||||
}, function (error) {
|
||||
return error;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// help functions
|
||||
|
||||
Tomahawk.valueForSubNode = function (node, tag) {
|
||||
@@ -367,48 +381,6 @@ Tomahawk.retrievedMetadata = function (metadataId, metadata, error) {
|
||||
delete Tomahawk.retrieveMetadataCallbacks[metadataId];
|
||||
};
|
||||
|
||||
/**
|
||||
* Internal counter used to identify asyncRequest callback from native code.
|
||||
*/
|
||||
Tomahawk.asyncRequestIdCounter = 0;
|
||||
/**
|
||||
* Internal map used to map asyncRequestIds to the respective javascript
|
||||
* callback functions.
|
||||
*/
|
||||
Tomahawk.asyncRequestCallbacks = {};
|
||||
|
||||
/**
|
||||
* Pass the natively retrieved reply back to the javascript callback
|
||||
* and augment the fake XMLHttpRequest object.
|
||||
*
|
||||
* Internal use only!
|
||||
*/
|
||||
Tomahawk.nativeAsyncRequestDone = function (reqId, xhr) {
|
||||
// Check that we have a matching callback stored.
|
||||
if (!Tomahawk.asyncRequestCallbacks.hasOwnProperty(reqId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Call the real callback
|
||||
if (xhr.readyState == 4 && httpSuccessStatuses.indexOf(xhr.status) != -1) {
|
||||
// Call the real callback
|
||||
if (Tomahawk.asyncRequestCallbacks[reqId].callback) {
|
||||
Tomahawk.asyncRequestCallbacks[reqId].callback(xhr);
|
||||
}
|
||||
} else if (xhr.readyState === 4) {
|
||||
Tomahawk.log("Failed to do nativeAsyncRequest");
|
||||
Tomahawk.log("Status Code was: " + xhr.status);
|
||||
if (Tomahawk.asyncRequestCallbacks[reqId].errorHandler) {
|
||||
Tomahawk.asyncRequestCallbacks[reqId].errorHandler(xhr);
|
||||
}
|
||||
}
|
||||
|
||||
// Callbacks are only used once.
|
||||
delete Tomahawk.asyncRequestCallbacks[reqId];
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This method is externalized from Tomahawk.asyncRequest, so that other clients
|
||||
* (like tomahawk-android) can inject their own logic that determines whether or not to do a request
|
||||
@@ -423,9 +395,9 @@ var shouldDoNativeRequest = function (options) {
|
||||
|| extraHeaders.hasOwnProperty("User-Agent")));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Possible options:
|
||||
* - url: The URL to call
|
||||
* - method: The HTTP request method (default: GET)
|
||||
* - username: The username for HTTP Basic Auth
|
||||
* - password: The password for HTTP Basic Auth
|
||||
@@ -443,7 +415,12 @@ var doRequest = function(options) {
|
||||
return this.responseHeaders;
|
||||
};
|
||||
xhr.getResponseHeader = function (header) {
|
||||
return this.responseHeaders[header];
|
||||
for(key in xhr.responseHeaders) {
|
||||
if(key.toLowerCase() === header.toLowerCase()) {
|
||||
return xhr.responseHeaders[key];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
return xhr;
|
||||
@@ -735,7 +712,6 @@ Tomahawk.base64Encode = function (b) {
|
||||
return window.btoa(b);
|
||||
};
|
||||
|
||||
|
||||
Tomahawk.PluginManager = {
|
||||
wrapperPrefix: '_adapter_',
|
||||
objects: {},
|
||||
@@ -766,8 +742,6 @@ Tomahawk.PluginManager = {
|
||||
methodName = this.wrapperPrefix + methodName;
|
||||
}
|
||||
|
||||
|
||||
var pluginManager = this;
|
||||
if (!this.objects[objectId]) {
|
||||
Tomahawk.log("Object not found! objectId: " + objectId + " methodName: " + methodName);
|
||||
} else {
|
||||
@@ -788,20 +762,21 @@ Tomahawk.PluginManager = {
|
||||
invoke: function (requestId, objectId, methodName, params) {
|
||||
RSVP.Promise.resolve(this.invokeSync(requestId, objectId, methodName, params))
|
||||
.then(function (result) {
|
||||
Tomahawk.reportScriptJobResults({
|
||||
var params = {
|
||||
requestId: requestId,
|
||||
data: result
|
||||
});
|
||||
};
|
||||
Tomahawk.reportScriptJobResults(encodeParamsToNativeFunctions(params));
|
||||
}, function (error) {
|
||||
Tomahawk.reportScriptJobResults({
|
||||
var params = {
|
||||
requestId: requestId,
|
||||
error: error
|
||||
});
|
||||
};
|
||||
Tomahawk.reportScriptJobResults(encodeParamsToNativeFunctions(params));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var encodeParamsToNativeFunctions = function(param) {
|
||||
return param;
|
||||
};
|
||||
@@ -815,7 +790,7 @@ Tomahawk.NativeScriptJobManager = {
|
||||
var requestId = this.idCounter++;
|
||||
var deferred = RSVP.defer();
|
||||
this.deferreds[requestId] = deferred;
|
||||
Tomahawk.invokeNativeScriptJob(requestId, methodName, encodeParamsToNativeFunctions(params));;
|
||||
Tomahawk.invokeNativeScriptJob(requestId, methodName, encodeParamsToNativeFunctions(params));
|
||||
return deferred.promise;
|
||||
},
|
||||
reportNativeScriptJobResult: function(requestId, result) {
|
||||
@@ -1484,9 +1459,7 @@ Tomahawk.Collection = {
|
||||
return new RSVP.Promise(function (resolve, reject) {
|
||||
that.cachedDbs[id].changeVersion(that.cachedDbs[id].version, "", null,
|
||||
function (err) {
|
||||
if (console.error) {
|
||||
console.error("Error!: %o", err);
|
||||
}
|
||||
Tomahawk.error("Error trying to change db version!", err);
|
||||
reject();
|
||||
}, function () {
|
||||
delete that.cachedDbs[id];
|
||||
|
BIN
data/sounds/silence.ogg
Normal file
BIN
data/sounds/silence.ogg
Normal file
Binary file not shown.
@@ -3,6 +3,7 @@
|
||||
<file>data/images/collection_background.png</file>
|
||||
<file>data/images/playlist_background.png</file>
|
||||
<file>data/images/filter.svg</file>
|
||||
<file>data/images/folder.svg</file>
|
||||
<file>data/images/loved.svg</file>
|
||||
<file>data/images/love.svg</file>
|
||||
<file>data/images/not-loved.svg</file>
|
||||
@@ -169,5 +170,6 @@
|
||||
<file>data/images/downloadbutton.svg</file>
|
||||
<file>data/images/nav-back.svg</file>
|
||||
<file>data/images/nav-forward.svg</file>
|
||||
<file>data/sounds/silence.ogg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@@ -24,13 +24,6 @@ include_directories(
|
||||
|
||||
add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
|
||||
|
||||
if(APPLE)
|
||||
# http://stackoverflow.com/questions/7226753/osx-lion-xcode-4-1-how-do-i-setup-a-c0x-project/7236451#7236451
|
||||
add_definitions(-std=c++11 -stdlib=libc++ -U__STRICT_ANSI__)
|
||||
set(PLATFORM_SPECIFIC_LINK_LIBRARIES "/usr/lib/libc++.dylib")
|
||||
else()
|
||||
add_definitions(-std=c++0x)
|
||||
endif()
|
||||
|
||||
tomahawk_add_plugin(hatchet
|
||||
TYPE account
|
||||
|
@@ -69,6 +69,13 @@ Tomahawk::InfoSystem::XmppInfoPlugin::init()
|
||||
}
|
||||
|
||||
|
||||
const QString
|
||||
Tomahawk::InfoSystem::XmppInfoPlugin::friendlyName() const
|
||||
{
|
||||
return "xmpp";
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Tomahawk::InfoSystem::XmppInfoPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
|
||||
{
|
||||
|
@@ -38,6 +38,8 @@ namespace Tomahawk {
|
||||
XmppInfoPlugin(XmppSipPlugin* parent);
|
||||
virtual ~XmppInfoPlugin();
|
||||
|
||||
const QString friendlyName() const override;
|
||||
|
||||
signals:
|
||||
void publishTune( QUrl url, Tomahawk::InfoSystem::InfoStringHash trackInfo );
|
||||
|
||||
|
@@ -194,9 +194,9 @@ InfoSystem::InfoPluginPtr
|
||||
XmppSipPlugin::infoPlugin()
|
||||
{
|
||||
if ( m_infoPlugin.isNull() )
|
||||
m_infoPlugin = QPointer< Tomahawk::InfoSystem::XmppInfoPlugin >( new Tomahawk::InfoSystem::XmppInfoPlugin( this ) );
|
||||
m_infoPlugin = QSharedPointer< Tomahawk::InfoSystem::XmppInfoPlugin >( new Tomahawk::InfoSystem::XmppInfoPlugin( this ) );
|
||||
|
||||
return InfoSystem::InfoPluginPtr( m_infoPlugin.data() );
|
||||
return m_infoPlugin;
|
||||
}
|
||||
|
||||
|
||||
@@ -285,7 +285,7 @@ XmppSipPlugin::onConnect()
|
||||
// load XmppInfoPlugin
|
||||
if ( infoPlugin() && Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() )
|
||||
{
|
||||
infoPlugin().data()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
infoPlugin()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin() );
|
||||
}
|
||||
|
||||
@@ -359,7 +359,6 @@ XmppSipPlugin::onDisconnect( Jreen::Client::DisconnectReason reason )
|
||||
if ( !m_infoPlugin.isNull() )
|
||||
{
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->removeInfoPlugin( infoPlugin() );
|
||||
delete m_infoPlugin;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -128,7 +128,7 @@ private:
|
||||
int m_currentPort;
|
||||
QString m_currentResource;
|
||||
|
||||
QPointer< Tomahawk::InfoSystem::XmppInfoPlugin > m_infoPlugin;
|
||||
QSharedPointer< Tomahawk::InfoSystem::XmppInfoPlugin > m_infoPlugin;
|
||||
Tomahawk::Accounts::Account::ConnectionState m_state;
|
||||
|
||||
// sort out
|
||||
|
@@ -24,6 +24,7 @@ tomahawk_add_library(${TOMAHAWK_PLAYDARAPI_LIBRARY_TARGET}
|
||||
qtcertificateaddon
|
||||
${GNUTLS_LIBRARIES}
|
||||
EXPORT TomahawkLibraryDepends
|
||||
EXPORT_MACRO TOMAHAWK_WIDGETS_EXPORT_PRO
|
||||
VERSION ${TOMAHAWK_VERSION_SHORT}
|
||||
)
|
||||
|
||||
|
@@ -23,7 +23,7 @@
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifndef TOMAHAWK_PLAYDARAPI_EXPORT
|
||||
# if defined (tomahawk_playdarapi_EXPORTS)
|
||||
# if defined (TOMAHAWK_WIDGETS_EXPORT_PRO)
|
||||
# define TOMAHAWK_PLAYDARAPI_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define TOMAHAWK_PLAYDARAPI_EXPORT Q_DECL_IMPORT
|
||||
|
@@ -34,7 +34,7 @@ public:
|
||||
* Creates a Playdar HTTP interface
|
||||
* @param ha Address to listen on
|
||||
* @param port Port to listen on with HTTP
|
||||
* @param sport Pot to listen on with HTTPS
|
||||
* @param sport Port to listen on with HTTPS
|
||||
* @param parent
|
||||
*/
|
||||
explicit PlaydarApi( QHostAddress ha, qint16 port, qint16 sport, QObject *parent = 0 );
|
||||
|
@@ -13,5 +13,6 @@ tomahawk_add_library(${TOMAHAWK_WIDGETS_LIBRARY_TARGET}
|
||||
SOURCES ${${TOMAHAWK_WIDGETS_LIBRARY_TARGET}_SOURCES}
|
||||
UI ${${TOMAHAWK_WIDGETS_LIBRARY_TARGET}_UI}
|
||||
EXPORT TomahawkLibraryDepends
|
||||
EXPORT_MACRO TOMAHAWK_WIDGETS_EXPORT_PRO
|
||||
VERSION ${TOMAHAWK_VERSION_SHORT}
|
||||
)
|
||||
|
@@ -23,7 +23,7 @@
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifndef TOMAHAWK_WIDGETS_EXPORT
|
||||
# if defined (tomahawk_widgets_EXPORTS)
|
||||
# if defined (TOMAHAWK_WIDGETS_EXPORT_PRO)
|
||||
# define TOMAHAWK_WIDGETS_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define TOMAHAWK_WIDGETS_EXPORT Q_DECL_IMPORT
|
||||
|
@@ -33,6 +33,7 @@
|
||||
|
||||
#include <QReadWriteLock>
|
||||
#include <QPixmapCache>
|
||||
#include <QCoreApplication>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
@@ -75,6 +76,7 @@ Album::get( const Tomahawk::artist_ptr& artist, const QString& name, bool autoCr
|
||||
}
|
||||
|
||||
album_ptr album = album_ptr( new Album( name, artist ), &Album::deleteLater );
|
||||
album->moveToThread( QCoreApplication::instance()->thread() );
|
||||
album->setWeakRef( album.toWeakRef() );
|
||||
album->loadId( autoCreate );
|
||||
s_albumsByName.insert( key, album );
|
||||
|
@@ -36,6 +36,7 @@
|
||||
|
||||
#include <QReadWriteLock>
|
||||
#include <QPixmapCache>
|
||||
#include <QCoreApplication>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
@@ -109,6 +110,7 @@ Artist::get( unsigned int id, const QString& name )
|
||||
}
|
||||
|
||||
artist_ptr a = artist_ptr( new Artist( id, name ), &Artist::deleteLater );
|
||||
a->moveToThread( QCoreApplication::instance()->thread() );
|
||||
a->setWeakRef( a.toWeakRef() );
|
||||
s_artistsByName.insert( key, a );
|
||||
|
||||
|
@@ -67,7 +67,7 @@ AtticaManager::AtticaManager( QObject* parent )
|
||||
connect( &m_manager, SIGNAL( providerAdded( Attica::Provider ) ), this, SLOT( providerAdded( Attica::Provider ) ) );
|
||||
|
||||
// resolvers
|
||||
// m_manager.addProviderFile( QUrl( "http://bakery.tomahawk-player.org/resolvers/providers.xml" ) );
|
||||
// m_manager.addProviderFile( QUrl( "http://v09.bakery.tomahawk-player.org/resolvers/providers.xml" ) );
|
||||
|
||||
const QString url = QString( "%1/resolvers/providers.xml?version=%2" ).arg( hostname() ).arg( TomahawkUtils::appFriendlyVersion() );
|
||||
QNetworkReply* reply = Tomahawk::Utils::nam()->get( QNetworkRequest( QUrl( url ) ) );
|
||||
@@ -116,7 +116,7 @@ AtticaManager::fetchMissingIcons()
|
||||
QString
|
||||
AtticaManager::hostname() const
|
||||
{
|
||||
return "http://bakery.tomahawk-player.org";
|
||||
return "http://v09.bakery.tomahawk-player.org";
|
||||
}
|
||||
|
||||
|
||||
|
@@ -37,6 +37,7 @@ set( libGuiSources
|
||||
jobview/ErrorStatusMessage.cpp
|
||||
jobview/IndexingJobItem.cpp
|
||||
jobview/InboxJobItem.cpp
|
||||
jobview/ScriptErrorStatusMessage.cpp
|
||||
|
||||
playlist/InboxModel.cpp
|
||||
playlist/InboxView.cpp
|
||||
@@ -145,6 +146,7 @@ set( libGuiSources
|
||||
widgets/ClickableLabel.cpp
|
||||
widgets/ComboBox.cpp
|
||||
widgets/DropDownButton.cpp
|
||||
widgets/DownloadButton.cpp
|
||||
widgets/ElidedLabel.cpp
|
||||
widgets/FilterHeader.cpp
|
||||
widgets/CaptionLabel.cpp
|
||||
@@ -417,7 +419,7 @@ include_directories(
|
||||
${Boost_INCLUDE_DIR}
|
||||
|
||||
${LIBPORTFWD_INCLUDE_DIR}
|
||||
${QUAZIP_INCLUDE_DIR}
|
||||
${QUAZIP_INCLUDE_DIRS}
|
||||
${QTKEYCHAIN_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
|
@@ -37,6 +37,9 @@
|
||||
#include "utils/ImageRegistry.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
#include <QDesktopServices>
|
||||
#include <QFileInfo>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
@@ -51,7 +54,7 @@ ContextMenu::ContextMenu( QWidget* parent )
|
||||
m_sigmap = new QSignalMapper( this );
|
||||
connect( m_sigmap, SIGNAL( mapped( int ) ), SLOT( onTriggered( int ) ) );
|
||||
|
||||
m_supportedActions = ActionPlay | ActionQueue | ActionPlaylist | ActionCopyLink | ActionLove | ActionStopAfter | ActionPage | ActionEditMetadata | ActionSend;
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +72,7 @@ ContextMenu::clear()
|
||||
m_albums.clear();
|
||||
m_artists.clear();
|
||||
|
||||
m_supportedActions = ActionPlay | ActionQueue | ActionPlaylist | ActionCopyLink | ActionLove | ActionStopAfter | ActionPage | ActionEditMetadata | ActionSend;
|
||||
m_supportedActions = ActionPlay | ActionQueue | ActionPlaylist | ActionCopyLink | ActionLove | ActionStopAfter | ActionPage | ActionEditMetadata | ActionSend | ActionOpenFileManager;
|
||||
}
|
||||
|
||||
|
||||
@@ -216,10 +219,23 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
|
||||
addSeparator();
|
||||
|
||||
if ( m_supportedActions & ActionCopyLink && itemCount() == 1 )
|
||||
{
|
||||
m_sigmap->setMapping( addAction( tr( "&Copy Track Link" ) ), ActionCopyLink );
|
||||
}
|
||||
|
||||
if ( m_supportedActions & ActionOpenFileManager &&
|
||||
queries.length() == 1 &&
|
||||
queries.first()->numResults() &&
|
||||
queries.first()->results().first()->isLocal() )
|
||||
{
|
||||
m_sigmap->setMapping( addAction( ImageRegistry::instance()->icon( RESPATH "images/folder.svg" ),
|
||||
tr( "Open Folder in File Manager..." ) ), ActionOpenFileManager );
|
||||
}
|
||||
|
||||
if ( m_supportedActions & ActionEditMetadata && itemCount() == 1 )
|
||||
{
|
||||
m_sigmap->setMapping( addAction( tr( "Properties..." ) ), ActionEditMetadata );
|
||||
}
|
||||
|
||||
addSeparator();
|
||||
|
||||
@@ -239,6 +255,8 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
|
||||
m_sigmap->setMapping( addAction( tr( "Mark as &Listened" ) ), ActionMarkListened );
|
||||
}
|
||||
|
||||
addSeparator();
|
||||
|
||||
if ( m_supportedActions & ActionDelete )
|
||||
m_sigmap->setMapping( addAction( queries.count() > 1 ? tr( "&Remove Items" ) : tr( "&Remove Item" ) ), ActionDelete );
|
||||
|
||||
@@ -394,6 +412,15 @@ ContextMenu::onTriggered( int action )
|
||||
}
|
||||
break;
|
||||
|
||||
case ActionOpenFileManager:
|
||||
{
|
||||
result_ptr result = m_queries.first()->results().first();
|
||||
QString path = QFileInfo( result->url() ).path();
|
||||
tLog() << Q_FUNC_INFO << "open directory" << path;
|
||||
QDesktopServices::openUrl( path );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
emit triggered( action );
|
||||
}
|
||||
|
@@ -37,21 +37,22 @@ Q_OBJECT
|
||||
public:
|
||||
enum MenuActions
|
||||
{
|
||||
ActionPlay = 1,
|
||||
ActionQueue = 2,
|
||||
ActionDelete = 4,
|
||||
ActionCopyLink = 8,
|
||||
ActionLove = 16,
|
||||
ActionStopAfter = 32,
|
||||
ActionPage = 64,
|
||||
ActionTrackPage = 128,
|
||||
ActionArtistPage = 256,
|
||||
ActionAlbumPage = 512,
|
||||
ActionEditMetadata = 1024,
|
||||
ActionPlaylist = 2048,
|
||||
ActionSend = 4096,
|
||||
ActionMarkListened = 8192,
|
||||
ActionDownload = 16384
|
||||
ActionPlay = 1,
|
||||
ActionQueue = 2,
|
||||
ActionDelete = 4,
|
||||
ActionCopyLink = 8,
|
||||
ActionLove = 16,
|
||||
ActionStopAfter = 32,
|
||||
ActionPage = 64,
|
||||
ActionTrackPage = 128,
|
||||
ActionArtistPage = 256,
|
||||
ActionAlbumPage = 512,
|
||||
ActionEditMetadata = 1024,
|
||||
ActionPlaylist = 2048,
|
||||
ActionSend = 4096,
|
||||
ActionMarkListened = 8192,
|
||||
ActionDownload = 16384,
|
||||
ActionOpenFileManager = 32768
|
||||
};
|
||||
|
||||
explicit ContextMenu( QWidget* parent = 0 );
|
||||
|
@@ -118,7 +118,7 @@ DownloadJob::localFile() const
|
||||
|
||||
|
||||
QString
|
||||
DownloadJob::localPath() const
|
||||
DownloadJob::localPath( const Tomahawk::album_ptr& album )
|
||||
{
|
||||
QDir dir = TomahawkSettings::instance()->downloadsPath();
|
||||
|
||||
@@ -127,7 +127,7 @@ DownloadJob::localPath() const
|
||||
dir.mkpath( "." );
|
||||
}
|
||||
|
||||
QString path = QString( "%1/%2" ).arg( safeEncode( m_track->artist(), true ) ).arg( safeEncode( m_track->album(), true ) );
|
||||
QString path = QString( "%1/%2" ).arg( safeEncode( album->artist()->name(), true ) ).arg( safeEncode( album->name(), true ) );
|
||||
dir.mkpath( path );
|
||||
|
||||
return QString( dir.path() + "/" + path ).replace( "//", "/" );
|
||||
@@ -138,7 +138,7 @@ QUrl
|
||||
DownloadJob::prepareFilename()
|
||||
{
|
||||
QString filename = QString( "%1. %2.%3" ).arg( m_track->albumpos() ).arg( safeEncode( m_track->track() ) ).arg( m_format.extension );
|
||||
QString path = localPath();
|
||||
QString path = localPath( m_track->albumPtr() );
|
||||
QString localFile = QString( path + "/" + filename );
|
||||
|
||||
if ( !m_tryResuming )
|
||||
@@ -444,7 +444,7 @@ DownloadJob::checkForResumedFile()
|
||||
|
||||
|
||||
QString
|
||||
DownloadJob::safeEncode( const QString& filename, bool removeTrailingDots ) const
|
||||
DownloadJob::safeEncode( const QString& filename, bool removeTrailingDots )
|
||||
{
|
||||
//FIXME: make it a regexp
|
||||
QString res = QString( filename ).toLatin1().replace( "/", "_" ).replace( "\\", "_" )
|
||||
|
@@ -58,7 +58,7 @@ public:
|
||||
long receivedSize() const { return m_rcvdSize; }
|
||||
long fileSize() const { return m_fileSize; }
|
||||
|
||||
QString localPath() const;
|
||||
static QString localPath( const Tomahawk::album_ptr& album );
|
||||
QString localFile() const;
|
||||
DownloadFormat format() const;
|
||||
|
||||
@@ -90,7 +90,7 @@ private slots:
|
||||
|
||||
private:
|
||||
void storeState();
|
||||
QString safeEncode( const QString& filename, bool removeTrailingDots = false ) const;
|
||||
static QString safeEncode( const QString& filename, bool removeTrailingDots = false );
|
||||
bool checkForResumedFile();
|
||||
QUrl prepareFilename();
|
||||
|
||||
|
@@ -24,6 +24,8 @@
|
||||
#include "TomahawkSettings.h"
|
||||
#include "infosystem/InfoSystem.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "Result.h"
|
||||
#include "Query.h"
|
||||
|
||||
DownloadManager* DownloadManager::s_instance = 0;
|
||||
|
||||
@@ -85,6 +87,36 @@ DownloadManager::localFileForDownload( const QString& url ) const
|
||||
}
|
||||
|
||||
|
||||
QUrl
|
||||
DownloadManager::localUrlForDownload( const Tomahawk::query_ptr& query ) const
|
||||
{
|
||||
Tomahawk::result_ptr result = query->numResults( true ) ? query->results().first() : Tomahawk::result_ptr();
|
||||
if ( result )
|
||||
{
|
||||
return localUrlForDownload( result );
|
||||
}
|
||||
|
||||
return QUrl();
|
||||
}
|
||||
|
||||
|
||||
QUrl
|
||||
DownloadManager::localUrlForDownload( const Tomahawk::result_ptr& result ) const
|
||||
{
|
||||
if ( result && !result->downloadFormats().isEmpty() &&
|
||||
!localFileForDownload( result->downloadFormats().first().url.toString() ).isEmpty() )
|
||||
{
|
||||
return QUrl::fromLocalFile( QFileInfo( DownloadManager::instance()->localFileForDownload( result->downloadFormats().first().url.toString() ) ).absolutePath() );
|
||||
}
|
||||
else if ( result && result->downloadJob() && result->downloadJob()->state() == DownloadJob::Finished )
|
||||
{
|
||||
return QUrl::fromLocalFile( QFileInfo( result->downloadJob()->localFile() ).absolutePath() );
|
||||
}
|
||||
|
||||
return QUrl();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadManager::storeJobs( const QList<downloadjob_ptr>& jobs )
|
||||
{
|
||||
|
@@ -45,6 +45,8 @@ public:
|
||||
|
||||
void storeJobs( const QList<downloadjob_ptr>& jobs );
|
||||
QString localFileForDownload( const QString& url ) const;
|
||||
QUrl localUrlForDownload( const Tomahawk::result_ptr& result ) const;
|
||||
QUrl localUrlForDownload( const Tomahawk::query_ptr& query ) const;
|
||||
|
||||
public slots:
|
||||
bool addJob( const downloadjob_ptr& job );
|
||||
|
@@ -263,9 +263,14 @@ bool
|
||||
DropJob::validateLocalFiles(const QString &paths, const QString &suffix)
|
||||
{
|
||||
QStringList filePaths = paths.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
|
||||
for ( QStringList::iterator it = filePaths.begin(); it != filePaths.end(); ++it )
|
||||
QStringList::iterator it = filePaths.begin();
|
||||
while ( it != filePaths.end() )
|
||||
{
|
||||
if ( !validateLocalFile( *it, suffix ) )
|
||||
filePaths.erase( it );
|
||||
it = filePaths.erase( it );
|
||||
else
|
||||
++it;
|
||||
}
|
||||
return !filePaths.isEmpty();
|
||||
}
|
||||
|
||||
@@ -975,7 +980,7 @@ DropJob::removeRemoteSources()
|
||||
|
||||
foreach ( const Tomahawk::result_ptr& result, item->results() )
|
||||
{
|
||||
if ( !result->resolvedByCollection().isNull() && !result->resolvedByCollection()->isLocal() )
|
||||
if ( !result->isLocal() )
|
||||
{
|
||||
list.append( item );
|
||||
break;
|
||||
|
@@ -1,14 +1,14 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
|
||||
* Copyright (C) 2011, Jeff Mitchell <jeff@tomahawk-player.org>
|
||||
* Copyright (C) 2011-2014, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright (C) 2013, Uwe L. Korn <uwelk@xhochy.com>
|
||||
* Copyright (C) 2013, Teo Mrnjavac <teo@kde.org>
|
||||
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
|
||||
* Copyright 2011-2016, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2011, Jeff Mitchell <jeff@tomahawk-player.org>
|
||||
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
|
||||
* Copyright 2013, Teo Mrnjavac <teo@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 2 of the License, or
|
||||
* 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,
|
||||
@@ -20,7 +20,6 @@
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "GlobalActionManager.h"
|
||||
|
||||
#include "accounts/AccountManager.h"
|
||||
|
@@ -1,21 +1,21 @@
|
||||
/*
|
||||
Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
|
||||
* Copyright 2011-2016, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GLOBALACTIONMANAGER_H
|
||||
#define GLOBALACTIONMANAGER_H
|
||||
|
@@ -36,7 +36,7 @@
|
||||
#define MAX_CONCURRENT_QUERIES 16
|
||||
#define CLEANUP_TIMEOUT 5 * 60 * 1000
|
||||
#define MINSCORE 0.5
|
||||
#define DEFAULT_RESOLVER_TIMEOUT 5000 //5 seconds
|
||||
#define DEFAULT_RESOLVER_TIMEOUT 5000 // 5 seconds
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
@@ -542,12 +542,12 @@ Pipeline::shuntNext()
|
||||
q->setCurrentResolver( 0 );
|
||||
}
|
||||
|
||||
//Zero-patient, a stub so that query is not resolved until we go through
|
||||
//all resolvers
|
||||
//As query considered as 'finished trying to resolve' when there are no
|
||||
//more qid entries in qidsState we'll put one as sort of 'keep this until
|
||||
//we kick off all our resolvers' entry
|
||||
//once we kick off all resolvers we'll remove this entry
|
||||
// Zero-patient, a stub so that query is not resolved until we go through
|
||||
// all resolvers
|
||||
// As query considered as 'finished trying to resolve' when there are no
|
||||
// more qid entries in qidsState we'll put one as sort of 'keep this until
|
||||
// we kick off all our resolvers' entry
|
||||
// once we kick off all resolvers we'll remove this entry
|
||||
incQIDState( q, nullptr );
|
||||
checkQIDState( q );
|
||||
}
|
||||
@@ -595,8 +595,8 @@ Pipeline::shunt( const query_ptr& q )
|
||||
// we get here if we disable a resolver while a query is resolving
|
||||
// OR we are just out of resolvers while query is still resolving
|
||||
|
||||
//since we seem to at least tried to kick off all of the resolvers,
|
||||
//remove the '.keep' entry
|
||||
// since we seem to at least tried to kick off all of the resolvers,
|
||||
// remove the '.keep' entry
|
||||
decQIDState( q, nullptr );
|
||||
return;
|
||||
}
|
||||
@@ -636,7 +636,7 @@ Pipeline::checkQIDState( const Tomahawk::query_ptr& query )
|
||||
Q_D( Pipeline );
|
||||
QMutexLocker lock( &d->mut );
|
||||
|
||||
tDebug() << Q_FUNC_INFO << " " << query->id() << " " << d->qidsState.count( query->id() );
|
||||
tDebug() << Q_FUNC_INFO << query->id() << d->qidsState.count( query->id() );
|
||||
|
||||
if ( d->qidsState.contains( query->id() ) )
|
||||
{
|
||||
@@ -673,7 +673,7 @@ Pipeline::decQIDState( const Tomahawk::query_ptr& query, Tomahawk::Resolver* r )
|
||||
{
|
||||
{
|
||||
QMutexLocker lock( &d->mut );
|
||||
d->qidsState.remove( query->id(), r );//Removes all matching pairs
|
||||
d->qidsState.remove( query->id(), r ); // Removes all matching pairs
|
||||
}
|
||||
|
||||
checkQIDState( query );
|
||||
|
@@ -33,6 +33,7 @@
|
||||
|
||||
#include <QtAlgorithms>
|
||||
#include <QDebug>
|
||||
#include <QCoreApplication>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
@@ -47,6 +48,7 @@ Query::get( const QString& artist, const QString& track, const QString& album, c
|
||||
autoResolve = false;
|
||||
|
||||
query_ptr q = query_ptr( new Query( Track::get( artist, track, album ), qid, autoResolve ), &QObject::deleteLater );
|
||||
q->moveToThread( QCoreApplication::instance()->thread() );
|
||||
q->setWeakRef( q.toWeakRef() );
|
||||
|
||||
if ( autoResolve )
|
||||
@@ -399,16 +401,21 @@ Query::resultSorter( const result_ptr& left, const result_ptr& right )
|
||||
|
||||
if ( ls == rs )
|
||||
{
|
||||
if ( right->resolvedByCollection() && right->resolvedByCollection()->isLocal() )
|
||||
if ( right->isLocal() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ( !right->isPreview() )
|
||||
if ( left->isPreview() != right->isPreview() )
|
||||
{
|
||||
return false;
|
||||
return !left->isPreview();
|
||||
}
|
||||
|
||||
return true;
|
||||
if ( left->resolvedBy() != nullptr && right->resolvedBy() != nullptr )
|
||||
{
|
||||
return left->resolvedBy()->weight() > right->resolvedBy()->weight();
|
||||
}
|
||||
|
||||
return left->id() > right->id();
|
||||
}
|
||||
|
||||
if ( left->isPreview() != right->isPreview() )
|
||||
@@ -636,6 +643,11 @@ Query::howSimilar( const Tomahawk::result_ptr& r )
|
||||
qTrackname = queryTrack()->trackSortname();
|
||||
}
|
||||
|
||||
//Cleanup symbols for minor naming differences
|
||||
qArtistname.remove(QRegExp(QString::fromUtf8("[-`~!@#$%^&*()_—+=|:;<>«»,.?/{}\'\"\\[\\]\\\\]")));
|
||||
qTrackname.remove(QRegExp(QString::fromUtf8("[-`~!@#$%^&*()_—+=|:;<>«»,.?/{}\'\"\\[\\]\\\\]")));
|
||||
qAlbumname.remove(QRegExp(QString::fromUtf8("[-`~!@#$%^&*()_—+=|:;<>«»,.?/{}\'\"\\[\\]\\\\]")));
|
||||
|
||||
// normal edit distance
|
||||
const int artdist = TomahawkUtils::levenshtein( qArtistname, rArtistname );
|
||||
const int trkdist = TomahawkUtils::levenshtein( qTrackname, rTrackname );
|
||||
|
@@ -35,6 +35,8 @@
|
||||
#include "Track.h"
|
||||
#include "Typedefs.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
static QHash< QString, result_wptr > s_results;
|
||||
@@ -69,6 +71,7 @@ Result::get( const QString& url, const track_ptr& track )
|
||||
}
|
||||
|
||||
result_ptr r = result_ptr( new Result( url, track ), &Result::deleteLater );
|
||||
r->moveToThread( QCoreApplication::instance()->thread() );
|
||||
r->setWeakRef( r.toWeakRef() );
|
||||
s_results.insert( url, r );
|
||||
|
||||
@@ -132,11 +135,19 @@ Result::deleteLater()
|
||||
void
|
||||
Result::onResolverRemoved( Tomahawk::Resolver* resolver )
|
||||
{
|
||||
m_mutex.lock();
|
||||
|
||||
if ( m_resolver.data() == resolver )
|
||||
{
|
||||
m_resolver = 0;
|
||||
m_mutex.unlock();
|
||||
|
||||
emit statusChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -150,6 +161,8 @@ Result::resolvedByCollection() const
|
||||
QString
|
||||
Result::url() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_url;
|
||||
}
|
||||
|
||||
@@ -157,6 +170,8 @@ Result::url() const
|
||||
bool
|
||||
Result::checked() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_checked;
|
||||
}
|
||||
|
||||
@@ -164,6 +179,8 @@ Result::checked() const
|
||||
bool
|
||||
Result::isPreview() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_isPreview;
|
||||
}
|
||||
|
||||
@@ -171,6 +188,8 @@ Result::isPreview() const
|
||||
QString
|
||||
Result::mimetype() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_mimetype;
|
||||
}
|
||||
|
||||
@@ -178,6 +197,8 @@ Result::mimetype() const
|
||||
RID
|
||||
Result::id() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
if ( m_rid.isEmpty() )
|
||||
m_rid = uuid();
|
||||
|
||||
@@ -194,6 +215,8 @@ Result::isOnline() const
|
||||
}
|
||||
else
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return !m_resolver.isNull();
|
||||
}
|
||||
}
|
||||
@@ -211,27 +234,36 @@ Result::playable() const
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Result::isLocal() const
|
||||
{
|
||||
return resolvedByCollection().isNull() ? false : resolvedByCollection()->isLocal();
|
||||
}
|
||||
|
||||
|
||||
QVariant
|
||||
Result::toVariant() const
|
||||
{
|
||||
track_ptr t = track();
|
||||
|
||||
QVariantMap m;
|
||||
m.insert( "artist", m_track->artist() );
|
||||
m.insert( "album", m_track->album() );
|
||||
m.insert( "track", m_track->track() );
|
||||
m.insert( "artist", t->artist() );
|
||||
m.insert( "album", t->album() );
|
||||
m.insert( "track", t->track() );
|
||||
m.insert( "source", friendlySource() );
|
||||
m.insert( "mimetype", mimetype() );
|
||||
m.insert( "size", size() );
|
||||
m.insert( "bitrate", bitrate() );
|
||||
m.insert( "duration", m_track->duration() );
|
||||
m.insert( "duration", t->duration() );
|
||||
// m.insert( "score", score() );
|
||||
m.insert( "sid", id() );
|
||||
m.insert( "discnumber", m_track->discnumber() );
|
||||
m.insert( "albumpos", m_track->albumpos() );
|
||||
m.insert( "discnumber", t->discnumber() );
|
||||
m.insert( "albumpos", t->albumpos() );
|
||||
m.insert( "preview", isPreview() );
|
||||
m.insert( "purchaseUrl", purchaseUrl() );
|
||||
|
||||
if ( !m_track->composer().isEmpty() )
|
||||
m.insert( "composer", m_track->composer() );
|
||||
if ( !t->composer().isEmpty() )
|
||||
m.insert( "composer", t->composer() );
|
||||
|
||||
return m;
|
||||
}
|
||||
@@ -240,20 +272,25 @@ Result::toVariant() const
|
||||
QString
|
||||
Result::toString() const
|
||||
{
|
||||
if ( m_track )
|
||||
m_mutex.lock();
|
||||
track_ptr track = m_track;
|
||||
QString url = m_url;
|
||||
m_mutex.unlock();
|
||||
|
||||
if ( track )
|
||||
{
|
||||
return QString( "Result(%1) %2 - %3%4 (%5)" )
|
||||
.arg( id() )
|
||||
.arg( m_track->artist() )
|
||||
.arg( m_track->track() )
|
||||
.arg( m_track->album().isEmpty() ? QString() : QString( " on %1" ).arg( m_track->album() ) )
|
||||
.arg( m_url );
|
||||
.arg( track->artist() )
|
||||
.arg( track->track() )
|
||||
.arg( track->album().isEmpty() ? QString() : QString( " on %1" ).arg( track->album() ) )
|
||||
.arg( url );
|
||||
}
|
||||
else
|
||||
{
|
||||
return QString( "Result(%1) (%2)" )
|
||||
.arg( id() )
|
||||
.arg( m_url );
|
||||
.arg( url );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,6 +298,8 @@ Result::toString() const
|
||||
Tomahawk::query_ptr
|
||||
Result::toQuery()
|
||||
{
|
||||
QMutexLocker l( &m_mutex );
|
||||
|
||||
if ( m_query.isNull() )
|
||||
{
|
||||
query_ptr query = Tomahawk::Query::get( m_track );
|
||||
@@ -270,12 +309,15 @@ Result::toQuery()
|
||||
m_query = query->weakRef();
|
||||
|
||||
QList<Tomahawk::result_ptr> rl;
|
||||
rl << weakRef().toStrongRef();
|
||||
rl << m_ownRef.toStrongRef();
|
||||
m_mutex.unlock();
|
||||
query->addResults( rl );
|
||||
m_mutex.lock();
|
||||
query->setResolveFinished( true );
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
return m_query.toStrongRef();
|
||||
}
|
||||
|
||||
@@ -295,9 +337,10 @@ Result::onOffline()
|
||||
|
||||
|
||||
void
|
||||
Result::setResolvedByCollection( const Tomahawk::collection_ptr& collection , bool emitOnlineEvents )
|
||||
Result::setResolvedByCollection( const Tomahawk::collection_ptr& collection, bool emitOnlineEvents )
|
||||
{
|
||||
m_collection = collection;
|
||||
|
||||
if ( emitOnlineEvents )
|
||||
{
|
||||
Q_ASSERT( !collection.isNull() );
|
||||
@@ -311,6 +354,8 @@ Result::setResolvedByCollection( const Tomahawk::collection_ptr& collection , bo
|
||||
void
|
||||
Result::setFriendlySource( const QString& s )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_friendlySource = s;
|
||||
}
|
||||
|
||||
@@ -318,6 +363,8 @@ Result::setFriendlySource( const QString& s )
|
||||
void
|
||||
Result::setPreview( bool isPreview )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_isPreview = isPreview;
|
||||
}
|
||||
|
||||
@@ -325,6 +372,8 @@ Result::setPreview( bool isPreview )
|
||||
void
|
||||
Result::setPurchaseUrl( const QString& u )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_purchaseUrl = u;
|
||||
}
|
||||
|
||||
@@ -332,6 +381,8 @@ Result::setPurchaseUrl( const QString& u )
|
||||
void
|
||||
Result::setLinkUrl( const QString& u )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_linkUrl = u;
|
||||
}
|
||||
|
||||
@@ -339,6 +390,8 @@ Result::setLinkUrl( const QString& u )
|
||||
void
|
||||
Result::setChecked( bool checked )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_checked = checked;
|
||||
}
|
||||
|
||||
@@ -346,6 +399,8 @@ Result::setChecked( bool checked )
|
||||
void
|
||||
Result::setMimetype( const QString& mimetype )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_mimetype = mimetype;
|
||||
}
|
||||
|
||||
@@ -353,6 +408,8 @@ Result::setMimetype( const QString& mimetype )
|
||||
void
|
||||
Result::setBitrate( unsigned int bitrate )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_bitrate = bitrate;
|
||||
}
|
||||
|
||||
@@ -360,6 +417,8 @@ Result::setBitrate( unsigned int bitrate )
|
||||
void
|
||||
Result::setSize( unsigned int size )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
@@ -367,6 +426,8 @@ Result::setSize( unsigned int size )
|
||||
void
|
||||
Result::setModificationTime( unsigned int modtime )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_modtime = modtime;
|
||||
}
|
||||
|
||||
@@ -374,6 +435,8 @@ Result::setModificationTime( unsigned int modtime )
|
||||
void
|
||||
Result::setTrack( const track_ptr& track )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_track = track;
|
||||
}
|
||||
|
||||
@@ -381,6 +444,8 @@ Result::setTrack( const track_ptr& track )
|
||||
unsigned int
|
||||
Result::fileId() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_fileId;
|
||||
}
|
||||
|
||||
@@ -390,6 +455,8 @@ Result::friendlySource() const
|
||||
{
|
||||
if ( resolvedByCollection().isNull() )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_friendlySource;
|
||||
}
|
||||
else
|
||||
@@ -400,6 +467,8 @@ Result::friendlySource() const
|
||||
QString
|
||||
Result::purchaseUrl() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_purchaseUrl;
|
||||
}
|
||||
|
||||
@@ -407,6 +476,8 @@ Result::purchaseUrl() const
|
||||
QString
|
||||
Result::linkUrl() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_linkUrl;
|
||||
}
|
||||
|
||||
@@ -416,6 +487,8 @@ Result::sourceIcon( TomahawkUtils::ImageMode style, const QSize& desiredSize ) c
|
||||
{
|
||||
if ( resolvedByCollection().isNull() )
|
||||
{
|
||||
//QMutexLocker lock( &m_mutex );
|
||||
|
||||
const ExternalResolver* resolver = qobject_cast< ExternalResolver* >( m_resolver.data() );
|
||||
if ( !resolver )
|
||||
{
|
||||
@@ -466,6 +539,8 @@ Result::sourceIcon( TomahawkUtils::ImageMode style, const QSize& desiredSize ) c
|
||||
unsigned int
|
||||
Result::bitrate() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_bitrate;
|
||||
}
|
||||
|
||||
@@ -473,6 +548,8 @@ Result::bitrate() const
|
||||
unsigned int
|
||||
Result::size() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_size;
|
||||
}
|
||||
|
||||
@@ -480,6 +557,8 @@ Result::size() const
|
||||
unsigned int
|
||||
Result::modificationTime() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_modtime;
|
||||
}
|
||||
|
||||
@@ -487,6 +566,8 @@ Result::modificationTime() const
|
||||
void
|
||||
Result::setFileId( unsigned int id )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_fileId = id;
|
||||
}
|
||||
|
||||
@@ -494,6 +575,8 @@ Result::setFileId( unsigned int id )
|
||||
Tomahawk::Resolver*
|
||||
Result::resolvedBy() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
if ( !m_collection.isNull() )
|
||||
return m_collection.data();
|
||||
|
||||
@@ -504,12 +587,16 @@ Result::resolvedBy() const
|
||||
void
|
||||
Result::setResolvedByResolver( Tomahawk::Resolver* resolver )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_resolver = QPointer< Tomahawk::Resolver >( resolver );
|
||||
}
|
||||
|
||||
|
||||
QPointer< Resolver > Result::resolvedByResolver() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_resolver;
|
||||
}
|
||||
|
||||
@@ -525,16 +612,29 @@ Result::doneEditing()
|
||||
track_ptr
|
||||
Result::track() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_track;
|
||||
}
|
||||
|
||||
|
||||
QList< DownloadFormat >
|
||||
Result::downloadFormats() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_formats;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Result::setDownloadFormats( const QList<DownloadFormat>& formats )
|
||||
{
|
||||
if ( formats.isEmpty() )
|
||||
return;
|
||||
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_formats.clear();
|
||||
foreach ( const DownloadFormat& format, formats )
|
||||
{
|
||||
@@ -562,7 +662,7 @@ Result::setDownloadFormats( const QList<DownloadFormat>& formats )
|
||||
void
|
||||
Result::onSettingsChanged()
|
||||
{
|
||||
if ( TomahawkSettings::instance()->downloadsPreferredFormat().toLower() != m_formats.first().extension.toLower() )
|
||||
if ( TomahawkSettings::instance()->downloadsPreferredFormat().toLower() != downloadFormats().first().extension.toLower() )
|
||||
{
|
||||
setDownloadFormats( downloadFormats() );
|
||||
emit updated();
|
||||
@@ -599,6 +699,8 @@ Result::onDownloadJobStateChanged( DownloadJob::TrackState newState, DownloadJob
|
||||
QWeakPointer<Result>
|
||||
Result::weakRef()
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_ownRef;
|
||||
}
|
||||
|
||||
@@ -606,5 +708,7 @@ Result::weakRef()
|
||||
void
|
||||
Result::setWeakRef( QWeakPointer<Result> weakRef )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_ownRef = weakRef;
|
||||
}
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include <QPixmap>
|
||||
#include <QPointer>
|
||||
#include <QVariant>
|
||||
#include <QMutex>
|
||||
|
||||
class MetadataEditor;
|
||||
|
||||
@@ -93,6 +94,12 @@ public:
|
||||
bool isOnline() const;
|
||||
bool playable() const;
|
||||
|
||||
/**
|
||||
* @brief whether this result isLocal, i.e. resolved by a local collection
|
||||
* @return isLocal
|
||||
*/
|
||||
bool isLocal() const;
|
||||
|
||||
QString url() const;
|
||||
/**
|
||||
* Has the given url been checked that it is accessible/valid.
|
||||
@@ -131,7 +138,7 @@ public:
|
||||
|
||||
track_ptr track() const;
|
||||
|
||||
QList<DownloadFormat> downloadFormats() const { return m_formats; }
|
||||
QList< DownloadFormat > downloadFormats() const;
|
||||
void setDownloadFormats( const QList<DownloadFormat>& formats );
|
||||
|
||||
downloadjob_ptr downloadJob() const { return m_downloadJob; }
|
||||
@@ -161,6 +168,8 @@ private:
|
||||
explicit Result( const QString& url, const Tomahawk::track_ptr& track );
|
||||
explicit Result();
|
||||
|
||||
mutable QMutex m_mutex;
|
||||
|
||||
mutable RID m_rid;
|
||||
collection_wptr m_collection;
|
||||
QPointer< Tomahawk::Resolver > m_resolver;
|
||||
|
@@ -929,6 +929,20 @@ TomahawkSettings::setVolume( unsigned int volume )
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TomahawkSettings::muted() const
|
||||
{
|
||||
return value( "audio/muted" ).toBool();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TomahawkSettings::setMuted( bool muted )
|
||||
{
|
||||
setValue( "audio/muted", muted );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
TomahawkSettings::proxyHost() const
|
||||
{
|
||||
|
@@ -107,6 +107,9 @@ public:
|
||||
unsigned int volume() const;
|
||||
void setVolume( unsigned int volume );
|
||||
|
||||
bool muted() const;
|
||||
void setMuted( bool muted );
|
||||
|
||||
/// Playlist stuff
|
||||
QByteArray playlistColumnSizes( const QString& playlistid ) const;
|
||||
void setPlaylistColumnSizes( const QString& playlistid, const QByteArray& state );
|
||||
|
@@ -37,6 +37,7 @@
|
||||
#include <QtAlgorithms>
|
||||
#include <QDateTime>
|
||||
#include <QReadWriteLock>
|
||||
#include <QCoreApplication>
|
||||
|
||||
|
||||
using namespace Tomahawk;
|
||||
@@ -92,6 +93,7 @@ Track::get( const QString& artist, const QString& track, const QString& album, c
|
||||
}
|
||||
|
||||
track_ptr t = track_ptr( new Track( artist, track, album, albumArtist, duration, composer, albumpos, discnumber ), &Track::deleteLater );
|
||||
t->moveToThread( QCoreApplication::instance()->thread() );
|
||||
t->setWeakRef( t.toWeakRef() );
|
||||
s_tracksByName.insert( key, t );
|
||||
|
||||
|
@@ -19,8 +19,7 @@
|
||||
|
||||
#include "TrackData.h"
|
||||
|
||||
#include <QtAlgorithms>
|
||||
#include <QReadWriteLock>
|
||||
|
||||
|
||||
#include "audio/AudioEngine.h"
|
||||
#include "collection/Collection.h"
|
||||
@@ -41,6 +40,10 @@
|
||||
#include "PlaylistEntry.h"
|
||||
#include "SourceList.h"
|
||||
|
||||
#include <QtAlgorithms>
|
||||
#include <QReadWriteLock>
|
||||
#include <QCoreApplication>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
QHash< QString, trackdata_wptr > TrackData::s_trackDatasByName = QHash< QString, trackdata_wptr >();
|
||||
@@ -84,6 +87,7 @@ TrackData::get( unsigned int id, const QString& artist, const QString& track )
|
||||
}
|
||||
|
||||
trackdata_ptr t = trackdata_ptr( new TrackData( id, artist, track ), &TrackData::deleteLater );
|
||||
t->moveToThread( QCoreApplication::instance()->thread() );
|
||||
t->setWeakRef( t.toWeakRef() );
|
||||
s_trackDatasByName.insert( key, t );
|
||||
|
||||
|
@@ -253,7 +253,7 @@ namespace Tomahawk
|
||||
typedef QHash< QString, QString > InfoStringHash;
|
||||
typedef QPair< QVariantMap, QVariant > PushInfoPair;
|
||||
|
||||
typedef QPointer< InfoPlugin > InfoPluginPtr;
|
||||
typedef QSharedPointer< InfoPlugin > InfoPluginPtr;
|
||||
}
|
||||
|
||||
namespace Network
|
||||
|
@@ -167,7 +167,7 @@ signals:
|
||||
void connectionStateChanged( Tomahawk::Accounts::Account::ConnectionState state );
|
||||
|
||||
void configurationChanged();
|
||||
void configTestResult( Tomahawk::Accounts::ConfigTestResultType );
|
||||
void configTestResult( int, const QString& = QString() );
|
||||
|
||||
protected:
|
||||
virtual void loadFromConfig( const QString &accountId );
|
||||
|
@@ -68,6 +68,7 @@ DelegateConfigWrapper::DelegateConfigWrapper( Tomahawk::Accounts::Account* accou
|
||||
h->setContentsMargins( m_widget->contentsMargins() );
|
||||
|
||||
m_errorLabel->setAlignment( Qt::AlignCenter );
|
||||
m_errorLabel->setWordWrap( true );
|
||||
v->addWidget( m_errorLabel );
|
||||
|
||||
v->addLayout( h );
|
||||
@@ -81,7 +82,7 @@ DelegateConfigWrapper::DelegateConfigWrapper( Tomahawk::Accounts::Account* accou
|
||||
if ( m_widget->metaObject()->indexOfSignal( "sizeHintChanged()" ) > -1 )
|
||||
connect( m_widget, SIGNAL( sizeHintChanged() ), this, SLOT( updateSizeHint() ) );
|
||||
|
||||
connect( m_account, SIGNAL( configTestResult( Tomahawk::Accounts::ConfigTestResultType ) ), SLOT( onConfigTestResult( Tomahawk::Accounts::ConfigTestResultType ) ) );
|
||||
connect( m_account, SIGNAL( configTestResult( int, const QString& ) ), SLOT( onConfigTestResult( int, const QString& ) ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -192,11 +193,11 @@ DelegateConfigWrapper::aboutClicked( bool )
|
||||
|
||||
|
||||
void
|
||||
DelegateConfigWrapper::onConfigTestResult( Tomahawk::Accounts::ConfigTestResultType result )
|
||||
DelegateConfigWrapper::onConfigTestResult( int code, const QString& message )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << result;
|
||||
tLog() << Q_FUNC_INFO << code << ": " << message;
|
||||
|
||||
if( result == Tomahawk::Accounts::ConfigTestResultSuccess )
|
||||
if( code == Tomahawk::Accounts::ConfigTestResultSuccess )
|
||||
{
|
||||
m_invalidData = QVariantMap();
|
||||
closeDialog( QDialog::Accepted );
|
||||
@@ -226,8 +227,25 @@ DelegateConfigWrapper::onConfigTestResult( Tomahawk::Accounts::ConfigTestResultT
|
||||
|
||||
m_invalidData = m_widget->readData();
|
||||
|
||||
// TODO: generate message based on status code
|
||||
m_errorLabel->setText( QString( "<font color='red'>%1</font>" ).arg( tr( "Your config is invalid." ) ) );
|
||||
QString msg = !message.isEmpty() ? message : getTestConfigMessage( code );
|
||||
m_errorLabel->setText( QString( "<font color='red'>%1</font>" ).arg( msg ) );
|
||||
}
|
||||
}
|
||||
|
||||
QString
|
||||
DelegateConfigWrapper::getTestConfigMessage( int code )
|
||||
{
|
||||
switch(code) {
|
||||
case Tomahawk::Accounts::ConfigTestResultCommunicationError:
|
||||
return tr( "Unable to authenticate. Please check your connection." );
|
||||
case Tomahawk::Accounts::ConfigTestResultInvalidCredentials:
|
||||
return tr( "Username or password incorrect." );
|
||||
case Tomahawk::Accounts::ConfigTestResultInvalidAccount:
|
||||
return tr( "Account rejected by server." );
|
||||
case Tomahawk::Accounts::ConfigTestResultPlayingElsewhere:
|
||||
return tr( "Action not allowed, account is in use elsewhere." );
|
||||
case Tomahawk::Accounts::ConfigTestResultAccountExpired:
|
||||
return tr( "Your account has expired." );
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -60,10 +60,11 @@ protected:
|
||||
|
||||
private slots:
|
||||
void aboutClicked( bool );
|
||||
void onConfigTestResult( Tomahawk::Accounts::ConfigTestResultType );
|
||||
void onConfigTestResult( int, const QString& );
|
||||
|
||||
private:
|
||||
void closeDialog( QDialog::DialogCode code );
|
||||
QString getTestConfigMessage( int code );
|
||||
|
||||
Tomahawk::Accounts::Account* m_account;
|
||||
AccountConfigWidget* m_widget;
|
||||
|
@@ -79,7 +79,7 @@ ResolverAccountFactory::createFromPath( const QString& path )
|
||||
}
|
||||
|
||||
|
||||
Account*
|
||||
ResolverAccount*
|
||||
ResolverAccountFactory::createFromPath( const QString& path, const QString& factory, bool isAttica )
|
||||
{
|
||||
qDebug() << "Creating ResolverAccount from path:" << path << "is attica" << isAttica;
|
||||
@@ -110,57 +110,8 @@ ResolverAccountFactory::createFromPath( const QString& path, const QString& fact
|
||||
|
||||
if ( pathInfo.suffix() == "axe" )
|
||||
{
|
||||
QString uniqueName = uuid();
|
||||
QDir dir( TomahawkUtils::extractScriptPayload( pathInfo.filePath(),
|
||||
uniqueName,
|
||||
MANUALRESOLVERS_DIR ) );
|
||||
if ( !( dir.exists() && dir.isReadable() ) ) //decompression fubar
|
||||
if ( !installAxe( realPath, configuration ) )
|
||||
{
|
||||
displayError( tr( "Resolver installation error: cannot open bundle." ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( !dir.cd( "content" ) ) //more fubar
|
||||
{
|
||||
displayError( tr( "Resolver installation error: incomplete bundle." ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString metadataFilePath = dir.absoluteFilePath( "metadata.json" );
|
||||
configuration = metadataFromJsonFile( metadataFilePath );
|
||||
|
||||
configuration[ "bundleDir" ] = uniqueName;
|
||||
|
||||
if ( !configuration[ "pluginName" ].isNull() && !configuration[ "pluginName" ].toString().isEmpty() )
|
||||
{
|
||||
dir.cdUp();
|
||||
if ( !dir.cdUp() ) //we're in MANUALRESOLVERS_DIR
|
||||
return 0;
|
||||
|
||||
QString name = configuration[ "pluginName" ].toString();
|
||||
|
||||
QString namePath = dir.absoluteFilePath( name );
|
||||
QFileInfo npI( namePath );
|
||||
|
||||
if ( npI.exists() && npI.isDir() )
|
||||
{
|
||||
TomahawkUtils::removeDirectory( namePath );
|
||||
}
|
||||
|
||||
dir.rename( uniqueName, name );
|
||||
|
||||
configuration[ "bundleDir" ] = name;
|
||||
|
||||
if ( !dir.cd( QString( "%1/content" ).arg( name ) ) ) //should work if it worked once
|
||||
return 0;
|
||||
}
|
||||
|
||||
expandPaths( dir, configuration );
|
||||
|
||||
realPath = configuration[ "path" ].toString();
|
||||
if ( realPath.isEmpty() )
|
||||
{
|
||||
displayError( tr( "Resolver installation error: bad metadata in bundle." ) );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -221,6 +172,71 @@ ResolverAccountFactory::createFromPath( const QString& path, const QString& fact
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ResolverAccountFactory::installAxe( QString& realPath, QVariantHash& configuration )
|
||||
{
|
||||
const QFileInfo pathInfo( realPath );
|
||||
QString uniqueName = uuid();
|
||||
QDir dir( TomahawkUtils::extractScriptPayload( pathInfo.filePath(),
|
||||
uniqueName,
|
||||
MANUALRESOLVERS_DIR ) );
|
||||
if ( !( dir.exists() && dir.isReadable() ) ) //decompression fubar
|
||||
{
|
||||
JobStatusView::instance()->model()->addJob( new ErrorStatusMessage(
|
||||
tr( "Resolver installation error: cannot open bundle." ) ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( !dir.cd( "content" ) ) //more fubar
|
||||
{
|
||||
JobStatusView::instance()->model()->addJob( new ErrorStatusMessage(
|
||||
tr( "Resolver installation error: incomplete bundle." ) ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString metadataFilePath = dir.absoluteFilePath( "metadata.json" );
|
||||
configuration = metadataFromJsonFile( metadataFilePath );
|
||||
|
||||
configuration[ "bundleDir" ] = uniqueName;
|
||||
|
||||
if ( !configuration[ "pluginName" ].isNull() && !configuration[ "pluginName" ].toString().isEmpty() )
|
||||
{
|
||||
dir.cdUp();
|
||||
if ( !dir.cdUp() ) //we're in MANUALRESOLVERS_DIR
|
||||
return 0;
|
||||
|
||||
QString name = configuration[ "pluginName" ].toString();
|
||||
|
||||
QString namePath = dir.absoluteFilePath( name );
|
||||
QFileInfo npI( namePath );
|
||||
|
||||
if ( npI.exists() && npI.isDir() )
|
||||
{
|
||||
TomahawkUtils::removeDirectory( namePath );
|
||||
}
|
||||
|
||||
dir.rename( uniqueName, name );
|
||||
|
||||
configuration[ "bundleDir" ] = name;
|
||||
|
||||
if ( !dir.cd( QString( "%1/content" ).arg( name ) ) ) //should work if it worked once
|
||||
return 0;
|
||||
}
|
||||
|
||||
expandPaths( dir, configuration );
|
||||
|
||||
realPath = configuration[ "path" ].toString();
|
||||
if ( realPath.isEmpty() )
|
||||
{
|
||||
JobStatusView::instance()->model()->addJob( new ErrorStatusMessage(
|
||||
tr( "Resolver installation error: bad metadata in bundle." ) ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
QVariantHash
|
||||
ResolverAccountFactory::metadataFromJsonFile( const QString& path )
|
||||
{
|
||||
@@ -517,7 +533,8 @@ ResolverAccount::removeBundle()
|
||||
}
|
||||
|
||||
|
||||
void ResolverAccount::testConfig()
|
||||
void
|
||||
ResolverAccount::testConfig()
|
||||
{
|
||||
// HACK: move to JSAccount once we have that properly
|
||||
JSResolver* resolver = qobject_cast< Tomahawk::JSResolver* >( m_resolver );
|
||||
@@ -525,7 +542,7 @@ void ResolverAccount::testConfig()
|
||||
{
|
||||
QVariantMap data = resolver->loadDataFromWidgets();
|
||||
ScriptJob* job = resolver->scriptObject()->invoke( "testConfig", data );
|
||||
connect( job, SIGNAL( done( QVariantMap ) ), SLOT( onTestConfig( QVariantMap ) ) );
|
||||
connect( job, SIGNAL( done( QVariant ) ), SLOT( onTestConfig( QVariant ) ) );
|
||||
job->start();
|
||||
}
|
||||
else
|
||||
@@ -535,19 +552,25 @@ void ResolverAccount::testConfig()
|
||||
}
|
||||
|
||||
|
||||
ExternalResolverGui*
|
||||
ResolverAccount::resolver() const
|
||||
{
|
||||
return m_resolver;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ResolverAccount::onTestConfig( const QVariantMap& result )
|
||||
ResolverAccount::onTestConfig( const QVariant& result )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << result;
|
||||
|
||||
int resultCode = result[ "result" ].toInt();
|
||||
if ( resultCode == 1 )
|
||||
if ( result.type() == QVariant::String )
|
||||
{
|
||||
emit configTestResult( Accounts::ConfigTestResultSuccess );
|
||||
emit configTestResult( Accounts::ConfigTestResultOther, result.toString() );
|
||||
}
|
||||
else
|
||||
{
|
||||
emit configTestResult( Accounts::ConfigTestResultOther );
|
||||
emit configTestResult( result.toInt() );
|
||||
}
|
||||
|
||||
sender()->deleteLater();
|
||||
@@ -566,6 +589,7 @@ AtticaResolverAccount::AtticaResolverAccount( const QString& accountId )
|
||||
|
||||
}
|
||||
|
||||
|
||||
AtticaResolverAccount::AtticaResolverAccount( const QString& accountId, const QString& path, const QString& atticaId, const QVariantHash& initialConfiguration )
|
||||
: ResolverAccount( accountId, path, initialConfiguration )
|
||||
, m_atticaId( atticaId )
|
||||
@@ -595,8 +619,6 @@ AtticaResolverAccount::init()
|
||||
loadIcon();
|
||||
else
|
||||
connect( AtticaManager::instance(), SIGNAL( resolversLoaded( Attica::Content::List ) ), this, SLOT( loadIcon() ) );
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@@ -33,6 +33,8 @@ class ExternalResolverGui;
|
||||
|
||||
namespace Accounts {
|
||||
|
||||
class ResolverAccount;
|
||||
|
||||
class DLLEXPORT ResolverAccountFactory : public AccountFactory
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -53,7 +55,10 @@ public:
|
||||
Account* createFromPath( const QString& path ) override;
|
||||
|
||||
// Internal use
|
||||
static Account* createFromPath( const QString& path, const QString& factoryId, bool isAttica );
|
||||
static ResolverAccount* createFromPath( const QString& path, const QString& factoryId, bool isAttica );
|
||||
// YES, non const parameters!
|
||||
static bool installAxe( QString& realPath, QVariantHash& configuration );
|
||||
|
||||
|
||||
private:
|
||||
static void displayError( const QString& error );
|
||||
@@ -101,9 +106,11 @@ public:
|
||||
|
||||
void testConfig() override;
|
||||
|
||||
ExternalResolverGui* resolver() const;
|
||||
|
||||
private slots:
|
||||
void resolverChanged();
|
||||
void onTestConfig( const QVariantMap& result );
|
||||
void onTestConfig( const QVariant& result );
|
||||
|
||||
protected:
|
||||
// Created by factory, when user installs a new resolver
|
||||
|
@@ -71,7 +71,7 @@ LastFmAccount::LastFmAccount( const QString& accountId )
|
||||
|
||||
if ( infoPlugin() && Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() )
|
||||
{
|
||||
infoPlugin().data()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
infoPlugin()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin() );
|
||||
}
|
||||
}
|
||||
@@ -82,7 +82,6 @@ LastFmAccount::~LastFmAccount()
|
||||
if ( m_infoPlugin )
|
||||
{
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->removeInfoPlugin( infoPlugin() );
|
||||
delete m_infoPlugin;
|
||||
}
|
||||
|
||||
delete m_resolver.data();
|
||||
@@ -168,9 +167,11 @@ InfoPluginPtr
|
||||
LastFmAccount::infoPlugin()
|
||||
{
|
||||
if ( m_infoPlugin.isNull() )
|
||||
m_infoPlugin = QPointer< LastFmInfoPlugin >( new LastFmInfoPlugin( this ) );
|
||||
{
|
||||
m_infoPlugin = QSharedPointer< LastFmInfoPlugin>( new LastFmInfoPlugin( this ) );
|
||||
}
|
||||
|
||||
return InfoPluginPtr( m_infoPlugin.data() );
|
||||
return m_infoPlugin;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@@ -105,7 +105,7 @@ private:
|
||||
void hookupResolver();
|
||||
|
||||
QPointer<Tomahawk::ExternalResolverGui> m_resolver;
|
||||
QPointer<Tomahawk::InfoSystem::LastFmInfoPlugin> m_infoPlugin;
|
||||
QSharedPointer<Tomahawk::InfoSystem::LastFmInfoPlugin> m_infoPlugin;
|
||||
QPointer<LastFmConfig> m_configWidget;
|
||||
};
|
||||
|
||||
|
@@ -116,6 +116,12 @@ SpotifyAccount::~SpotifyAccount()
|
||||
{
|
||||
clearUser();
|
||||
|
||||
if ( m_infoPlugin )
|
||||
{
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->removeInfoPlugin( infoPlugin() );
|
||||
}
|
||||
|
||||
|
||||
if ( m_spotifyResolver.isNull() )
|
||||
return;
|
||||
|
||||
@@ -135,7 +141,7 @@ SpotifyAccount::init()
|
||||
|
||||
if ( infoPlugin() && Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() )
|
||||
{
|
||||
infoPlugin().data()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
infoPlugin()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin() );
|
||||
}
|
||||
|
||||
@@ -366,10 +372,10 @@ SpotifyAccount::infoPlugin()
|
||||
{
|
||||
if ( m_infoPlugin.isNull() )
|
||||
{
|
||||
m_infoPlugin = QPointer< InfoSystem::SpotifyInfoPlugin >( new InfoSystem::SpotifyInfoPlugin( this ) );
|
||||
m_infoPlugin = QSharedPointer< InfoSystem::SpotifyInfoPlugin >( new InfoSystem::SpotifyInfoPlugin( this ) );
|
||||
}
|
||||
|
||||
return InfoSystem::InfoPluginPtr( m_infoPlugin.data() );
|
||||
return m_infoPlugin;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -170,7 +170,7 @@ private:
|
||||
QPointer<SpotifyAccountConfig> m_configWidget;
|
||||
QPointer<QWidget> m_aboutWidget;
|
||||
QPointer<ScriptResolver> m_spotifyResolver;
|
||||
QPointer< InfoSystem::SpotifyInfoPlugin > m_infoPlugin;
|
||||
QSharedPointer< InfoSystem::SpotifyInfoPlugin > m_infoPlugin;
|
||||
|
||||
QMap<QString, QPair<QObject*, QString> > m_qidToSlotMap;
|
||||
QMap<QString, QVariant > m_qidToExtraData;
|
||||
|
@@ -277,7 +277,7 @@ SpotifyAccountConfig::showLoggedIn()
|
||||
m_ui->verticalLayout->insertWidget( 1, m_loggedInUser, 0, Qt::AlignCenter );
|
||||
}
|
||||
|
||||
qDebug() << "Showing logged in withuserame:" << m_verifiedUsername;
|
||||
qDebug() << "Showing logged in with username:" << m_verifiedUsername;
|
||||
m_loggedInUser->show();
|
||||
m_loggedInUser->setText( tr( "Logged in as %1" ).arg( m_verifiedUsername ) );
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2015, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2016, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
|
||||
* Copyright 2013, Teo Mrnjavac <teo@kde.org>
|
||||
*
|
||||
@@ -165,12 +165,19 @@ AudioEngine::AudioEngine()
|
||||
d->s_instance = this;
|
||||
tDebug() << "Init AudioEngine";
|
||||
|
||||
d->audioOutput = new AudioOutput(this);
|
||||
d->audioOutput = new AudioOutput( this );
|
||||
|
||||
connect( d->audioOutput, SIGNAL( initialized() ), this, SIGNAL( initialized() ) );
|
||||
connect( d->audioOutput, SIGNAL( stateChanged( AudioOutput::AudioState, AudioOutput::AudioState ) ), d_func(), SLOT( onStateChanged( AudioOutput::AudioState, AudioOutput::AudioState ) ) );
|
||||
connect( d->audioOutput, SIGNAL( tick( qint64 ) ), SLOT( timerTriggered( qint64 ) ) );
|
||||
connect( d->audioOutput, SIGNAL( positionChanged( float ) ), SLOT( onPositionChanged( float ) ) );
|
||||
connect( d->audioOutput, SIGNAL( volumeChanged( qreal ) ), SLOT( onVolumeChanged( qreal ) ) );
|
||||
connect( d->audioOutput, SIGNAL( mutedChanged( bool ) ), SIGNAL( mutedChanged( bool ) ) );
|
||||
|
||||
if ( TomahawkSettings::instance()->muted() )
|
||||
{
|
||||
mute();
|
||||
}
|
||||
setVolume( TomahawkSettings::instance()->volume() );
|
||||
|
||||
qRegisterMetaType< AudioErrorCode >("AudioErrorCode");
|
||||
@@ -183,6 +190,7 @@ AudioEngine::~AudioEngine()
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
|
||||
TomahawkSettings::instance()->setVolume( volume() );
|
||||
TomahawkSettings::instance()->setMuted( isMuted() );
|
||||
|
||||
delete d_ptr;
|
||||
}
|
||||
@@ -289,8 +297,11 @@ AudioEngine::stop( AudioErrorCode errorCode )
|
||||
if ( d->waitingOnNewTrack )
|
||||
sendWaitingNotification();
|
||||
|
||||
Tomahawk::InfoSystem::InfoPushData pushData( s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNowStopped, QVariant(), Tomahawk::InfoSystem::PushNoFlag );
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( pushData );
|
||||
if ( d->audioOutput->isInitialized() )
|
||||
{
|
||||
Tomahawk::InfoSystem::InfoPushData pushData( s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNowStopped, QVariant(), Tomahawk::InfoSystem::PushNoFlag );
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( pushData );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -455,6 +466,8 @@ AudioEngine::mute()
|
||||
{
|
||||
Q_D( AudioEngine );
|
||||
d->audioOutput->setMuted( true );
|
||||
|
||||
emit volumeChanged( volume() );
|
||||
}
|
||||
|
||||
|
||||
@@ -463,6 +476,8 @@ AudioEngine::toggleMute()
|
||||
{
|
||||
Q_D( AudioEngine );
|
||||
d->audioOutput->setMuted( !d->audioOutput->isMuted() );
|
||||
|
||||
emit volumeChanged( volume() );
|
||||
}
|
||||
|
||||
|
||||
@@ -562,6 +577,12 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
|
||||
Q_D( AudioEngine );
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : result->url() );
|
||||
|
||||
|
||||
if ( !d->audioOutput->isInitialized() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !result )
|
||||
{
|
||||
stop();
|
||||
@@ -583,6 +604,7 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
|
||||
job->start();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::gotStreamUrl( const QVariantMap& data )
|
||||
{
|
||||
@@ -590,14 +612,17 @@ AudioEngine::gotStreamUrl( const QVariantMap& data )
|
||||
QVariantMap headers = data[ "headers" ].toMap();
|
||||
Tomahawk::result_ptr result = sender()->property( "result" ).value<result_ptr>();
|
||||
|
||||
if ( streamUrl.isEmpty() || !( TomahawkUtils::isHttpResult( streamUrl ) || TomahawkUtils::isHttpsResult( streamUrl ) || TomahawkUtils::isRtmpResult( streamUrl ) ) )
|
||||
if ( streamUrl.isEmpty() || headers.isEmpty() ||
|
||||
!( TomahawkUtils::isHttpResult( streamUrl ) || TomahawkUtils::isHttpsResult( streamUrl ) ) )
|
||||
{
|
||||
// Not an http(s) or RTMP URL, get IO device
|
||||
// We can't supply custom headers to VLC - but prefer using its HTTP streaming due to improved seeking ability
|
||||
// Not an RTMP or HTTP-with-headers URL, get IO device
|
||||
QSharedPointer< QIODevice > sp;
|
||||
performLoadIODevice( result, streamUrl );
|
||||
}
|
||||
else
|
||||
{
|
||||
// We need our own QIODevice for streaming
|
||||
// TODO: just make this part of the http(s) IoDeviceFactory (?)
|
||||
QUrl url = QUrl::fromEncoded( streamUrl.toUtf8() );
|
||||
QNetworkRequest req( url );
|
||||
@@ -619,12 +644,13 @@ AudioEngine::gotStreamUrl( const QVariantMap& data )
|
||||
|
||||
tDebug() << "Creating a QNetworkReply with url:" << req.url().toString();
|
||||
NetworkReply* reply = new NetworkReply( Tomahawk::Utils::nam()->get( req ) );
|
||||
NewClosure( reply, SIGNAL( finalUrlReached() ), this, SLOT( gotRedirectedStreamUrl( Tomahawk::result_ptr, NetworkReply* )), result, reply );
|
||||
NewClosure( reply, SIGNAL( finalUrlReached() ), this, SLOT( gotRedirectedStreamUrl( Tomahawk::result_ptr, NetworkReply* ) ), result, reply );
|
||||
}
|
||||
|
||||
sender()->deleteLater();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::gotRedirectedStreamUrl( const Tomahawk::result_ptr& result, NetworkReply* reply )
|
||||
{
|
||||
@@ -669,7 +695,7 @@ AudioEngine::performLoadIODevice( const result_ptr& result, const QString& url )
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString url, QSharedPointer< QIODevice > io )
|
||||
AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString& url, QSharedPointer< QIODevice > io )
|
||||
{
|
||||
if ( QThread::currentThread() != thread() )
|
||||
{
|
||||
@@ -951,9 +977,9 @@ AudioEngine::playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk:
|
||||
void
|
||||
AudioEngine::playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk::query_ptr& query )
|
||||
{
|
||||
if ( query->resolvingFinished() )
|
||||
if ( query->resolvingFinished() || query->numResults( true ) )
|
||||
{
|
||||
if ( query->numResults() && query->results().first()->isOnline() )
|
||||
if ( query->numResults( true ) )
|
||||
{
|
||||
playItem( playlist, query->results().first(), query );
|
||||
return;
|
||||
@@ -969,7 +995,7 @@ AudioEngine::playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk:
|
||||
{
|
||||
Pipeline::instance()->resolve( query );
|
||||
|
||||
NewClosure( query.data(), SIGNAL( resolvingFinished( bool ) ),
|
||||
NewClosure( query.data(), SIGNAL( resultsChanged() ),
|
||||
const_cast<AudioEngine*>(this), SLOT( playItem( Tomahawk::playlistinterface_ptr, Tomahawk::query_ptr ) ), playlist, query );
|
||||
}
|
||||
}
|
||||
|
@@ -149,6 +149,8 @@ public slots:
|
||||
void setShuffled( bool enabled );
|
||||
|
||||
signals:
|
||||
void initialized();
|
||||
|
||||
void loading( const Tomahawk::result_ptr track );
|
||||
void started( const Tomahawk::result_ptr track );
|
||||
void finished( const Tomahawk::result_ptr track );
|
||||
@@ -186,7 +188,7 @@ private slots:
|
||||
|
||||
|
||||
void performLoadIODevice( const Tomahawk::result_ptr& result, const QString& url ); //only call from loadTrack kthxbi
|
||||
void performLoadTrack( const Tomahawk::result_ptr result, const QString url, QSharedPointer< QIODevice > io ); //only call from loadTrack or performLoadIODevice kthxbi
|
||||
void performLoadTrack( const Tomahawk::result_ptr result, const QString& url, QSharedPointer< QIODevice > io ); //only call from loadTrack or performLoadIODevice kthxbi
|
||||
void loadPreviousTrack();
|
||||
void loadNextTrack();
|
||||
|
||||
|
@@ -25,11 +25,13 @@
|
||||
|
||||
#include "audio/MediaStream.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/TomahawkUtils.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QVarLengthArray>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QTimer>
|
||||
|
||||
#include <vlc/libvlc.h>
|
||||
#include <vlc/libvlc_media.h>
|
||||
@@ -58,6 +60,7 @@ AudioOutput::AudioOutput( QObject* parent )
|
||||
, m_currentTime( 0 )
|
||||
, m_totalTime( 0 )
|
||||
, m_justSeeked( false )
|
||||
, m_initialized( false )
|
||||
, dspPluginCallback( nullptr )
|
||||
, m_vlcInstance( nullptr )
|
||||
, m_vlcPlayer( nullptr )
|
||||
@@ -95,8 +98,8 @@ AudioOutput::AudioOutput( QObject* parent )
|
||||
TOMAHAWK_APPLICATION_NAME "/" TOMAHAWK_VERSION );
|
||||
// FIXME: icon is named tomahawk, so we need the lowercase application name
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 1, 0, 0))
|
||||
libvlc_set_app_id( m_vlcInstance, "org.tomahawk-player.desktop",
|
||||
TOMAHAWK_VERSION, "tomahawk" );
|
||||
libvlc_set_app_id( m_vlcInstance, TOMAHAWK_APPLICATION_PACKAGE_NAME,
|
||||
TOMAHAWK_VERSION, TOMAHAWK_TARGET_NAME );
|
||||
#endif
|
||||
|
||||
m_vlcPlayer = libvlc_media_player_new( m_vlcInstance );
|
||||
@@ -120,6 +123,11 @@ AudioOutput::AudioOutput( QObject* parent )
|
||||
libvlc_MediaPlayerTitleChanged,
|
||||
libvlc_MediaPlayerSnapshotTaken,
|
||||
//libvlc_MediaPlayerLengthChanged,
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 2, 2, 0))
|
||||
libvlc_MediaPlayerAudioVolume,
|
||||
libvlc_MediaPlayerMuted,
|
||||
libvlc_MediaPlayerUnmuted,
|
||||
#endif
|
||||
libvlc_MediaPlayerVout
|
||||
};
|
||||
const int eventCount = sizeof(events) / sizeof( *events );
|
||||
@@ -128,7 +136,24 @@ AudioOutput::AudioOutput( QObject* parent )
|
||||
libvlc_event_attach( manager, events[ i ], &AudioOutput::vlcEventCallback, this );
|
||||
}
|
||||
|
||||
tDebug() << Q_FUNC_INFO << "Init OK";
|
||||
// HACK: play silent ogg file and set volume on that to workaround vlc not allowing to set volume before a file is played
|
||||
m_silenceFile.setFileName( RESPATH "sounds/silence.ogg" );
|
||||
Q_ASSERT( m_silenceFile.exists() );
|
||||
Q_ASSERT( m_silenceFile.open( QIODevice::ReadOnly ) );
|
||||
|
||||
setCurrentSource( new MediaStream( &m_silenceFile, true ) );
|
||||
libvlc_media_player_play( m_vlcPlayer );
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,4,0)
|
||||
// if the silence file did not play for 15 secs, we pretend the AudioOutput is initialized, to allow proper error reporting
|
||||
QTimer::singleShot( 15000, [&]()
|
||||
{
|
||||
if ( !m_initialized ) {
|
||||
m_initialized = true;
|
||||
emit initialized();
|
||||
}
|
||||
} );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -154,6 +179,28 @@ AudioOutput::~AudioOutput()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioOutput::onInitVlcEvent( const libvlc_event_t* event )
|
||||
{
|
||||
switch ( event->type )
|
||||
{
|
||||
case libvlc_MediaPlayerTimeChanged:
|
||||
setVolume( volume() );
|
||||
setMuted( isMuted() );
|
||||
|
||||
m_initialized = true;
|
||||
m_silenceFile.close();
|
||||
|
||||
tDebug() << Q_FUNC_INFO << "Init OK";
|
||||
emit initialized();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioOutput::setAutoDelete( bool ad )
|
||||
{
|
||||
@@ -302,6 +349,13 @@ AudioOutput::setCurrentSource( MediaStream* stream )
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
AudioOutput::isInitialized() const
|
||||
{
|
||||
return m_initialized;
|
||||
}
|
||||
|
||||
|
||||
AudioOutput::AudioState
|
||||
AudioOutput::state() const
|
||||
{
|
||||
@@ -427,16 +481,19 @@ AudioOutput::seek( qint64 milliseconds )
|
||||
return;
|
||||
}
|
||||
|
||||
qint64 duration = AudioEngine::instance()->currentTrackTotalTime();
|
||||
// for some tracks, seeking to an end seems not to work correctly with libvlc
|
||||
// (tracks enter a random and infinite loop) - this is a temporary fix for that
|
||||
if (duration == milliseconds)
|
||||
milliseconds -= 1;
|
||||
|
||||
if ( m_seekable )
|
||||
{
|
||||
|
||||
// tDebug() << Q_FUNC_INFO << "AudioOutput:: seeking" << milliseconds << "msec";
|
||||
libvlc_media_player_set_time( m_vlcPlayer, milliseconds );
|
||||
setCurrentTime( milliseconds );
|
||||
}
|
||||
else
|
||||
{
|
||||
qint64 duration = AudioEngine::instance()->currentTrackTotalTime();
|
||||
float position = float(float(milliseconds) / duration);
|
||||
libvlc_media_player_set_position(m_vlcPlayer, position);
|
||||
tDebug() << Q_FUNC_INFO << "AudioOutput:: seeking via position" << position << "pos";
|
||||
@@ -466,11 +523,9 @@ AudioOutput::setMuted( bool m )
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
|
||||
m_muted = m;
|
||||
if ( m_muted )
|
||||
{
|
||||
libvlc_audio_set_volume( m_vlcPlayer, 0 );
|
||||
}
|
||||
else
|
||||
libvlc_audio_set_mute( m_vlcPlayer, m );
|
||||
|
||||
if ( !m_muted )
|
||||
{
|
||||
libvlc_audio_set_volume( m_vlcPlayer, m_volume * 100.0 );
|
||||
}
|
||||
@@ -487,7 +542,7 @@ AudioOutput::volume() const
|
||||
void
|
||||
AudioOutput::setVolume( qreal vol )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
tDebug() << Q_FUNC_INFO << vol << m_muted;
|
||||
|
||||
m_volume = vol;
|
||||
if ( !m_muted )
|
||||
@@ -531,6 +586,20 @@ AudioOutput::onVlcEvent( const libvlc_event_t* event )
|
||||
// Don't call stop() here - it will deadlock libvlc
|
||||
setState( Error );
|
||||
break;
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 2, 2, 0))
|
||||
case libvlc_MediaPlayerAudioVolume:
|
||||
m_volume = event->u.media_player_audio_volume.volume;
|
||||
emit volumeChanged( volume() );
|
||||
break;
|
||||
case libvlc_MediaPlayerMuted:
|
||||
m_muted = true;
|
||||
emit mutedChanged( true );
|
||||
break;
|
||||
case libvlc_MediaPlayerUnmuted:
|
||||
m_muted = false;
|
||||
emit mutedChanged( false );
|
||||
break;
|
||||
#endif
|
||||
case libvlc_MediaPlayerNothingSpecial:
|
||||
case libvlc_MediaPlayerOpening:
|
||||
case libvlc_MediaPlayerBuffering:
|
||||
@@ -556,7 +625,14 @@ AudioOutput::vlcEventCallback( const libvlc_event_t* event, void* opaque )
|
||||
AudioOutput* that = reinterpret_cast < AudioOutput * > ( opaque );
|
||||
Q_ASSERT( that );
|
||||
|
||||
that->onVlcEvent( event );
|
||||
if ( !that->isInitialized() )
|
||||
{
|
||||
that->onInitVlcEvent( event );
|
||||
}
|
||||
else
|
||||
{
|
||||
that->onVlcEvent( event );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -25,6 +25,8 @@
|
||||
#include "DllMacro.h"
|
||||
#include "Typedefs.h"
|
||||
|
||||
#include <QFile>
|
||||
|
||||
#include <functional>
|
||||
|
||||
struct libvlc_instance_t;
|
||||
@@ -44,6 +46,7 @@ public:
|
||||
explicit AudioOutput( QObject* parent = nullptr );
|
||||
~AudioOutput();
|
||||
|
||||
bool isInitialized() const;
|
||||
AudioState state() const;
|
||||
|
||||
void setCurrentSource( const QUrl& stream );
|
||||
@@ -72,11 +75,16 @@ public:
|
||||
public slots:
|
||||
|
||||
signals:
|
||||
void initialized();
|
||||
void stateChanged( AudioOutput::AudioState, AudioOutput::AudioState );
|
||||
void tick( qint64 );
|
||||
void positionChanged( float );
|
||||
void volumeChanged( qreal volume );
|
||||
void mutedChanged( bool );
|
||||
|
||||
private:
|
||||
void onInitVlcEvent( const libvlc_event_t* event );
|
||||
|
||||
void setState( AudioState state );
|
||||
void setCurrentTime( qint64 time );
|
||||
void setCurrentPosition( float position );
|
||||
@@ -99,6 +107,9 @@ private:
|
||||
qint64 m_totalTime;
|
||||
bool m_justSeeked;
|
||||
|
||||
bool m_initialized;
|
||||
QFile m_silenceFile;
|
||||
|
||||
std::function< void( int state, int frameNumber, float* samples, int nb_channels, int nb_samples ) > dspPluginCallback;
|
||||
|
||||
libvlc_instance_t* m_vlcInstance;
|
||||
|
@@ -41,12 +41,16 @@ MediaStream::MediaStream( const QUrl &url )
|
||||
}
|
||||
|
||||
|
||||
MediaStream::MediaStream( QIODevice* device )
|
||||
MediaStream::MediaStream( QIODevice* device, bool bufferingFinished )
|
||||
: QObject( nullptr )
|
||||
, m_type( IODevice )
|
||||
, m_ioDevice ( device )
|
||||
, m_bufferingFinished( bufferingFinished )
|
||||
{
|
||||
QObject::connect( m_ioDevice, SIGNAL( readChannelFinished() ), this, SLOT( bufferingFinished() ) );
|
||||
if ( !bufferingFinished )
|
||||
{
|
||||
QObject::connect( m_ioDevice, SIGNAL( readChannelFinished() ), this, SLOT( bufferingFinished() ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -42,7 +42,7 @@ public:
|
||||
|
||||
MediaStream( QObject* parent = nullptr );
|
||||
explicit MediaStream( const QUrl &url );
|
||||
explicit MediaStream( QIODevice* device );
|
||||
explicit MediaStream( QIODevice* device, bool bufferingFinished = false );
|
||||
virtual ~MediaStream();
|
||||
|
||||
MediaType type() const;
|
||||
|
@@ -1,21 +1,20 @@
|
||||
/*
|
||||
Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "LocalCollection.h"
|
||||
|
||||
|
@@ -1,21 +1,20 @@
|
||||
/*
|
||||
Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
|
||||
|
||||
This program 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 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOCALCOLLECTION_H
|
||||
#define LOCALCOLLECTION_H
|
||||
|
@@ -240,7 +240,7 @@ MetadataEditor::loadResult( const Tomahawk::result_ptr& result )
|
||||
return;
|
||||
|
||||
m_result = result;
|
||||
setEditable( result->resolvedByCollection() && result->resolvedByCollection()->isLocal() );
|
||||
setEditable( result->isLocal() );
|
||||
|
||||
setTitle( result->track()->track() );
|
||||
setArtist( result->track()->artist() );
|
||||
@@ -250,7 +250,7 @@ MetadataEditor::loadResult( const Tomahawk::result_ptr& result )
|
||||
setYear( result->track()->year() );
|
||||
setBitrate( result->bitrate() );
|
||||
|
||||
if ( result->resolvedByCollection() && result->resolvedByCollection()->isLocal() )
|
||||
if ( result->isLocal() )
|
||||
{
|
||||
QString furl = m_result->url();
|
||||
if ( furl.startsWith( "file://" ) )
|
||||
|
@@ -277,8 +277,8 @@ InfoSystem::addInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin )
|
||||
|
||||
if ( plugin.data()->thread() != m_infoSystemWorkerThreadController->worker()->thread() )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "The object must be moved to the worker thread first, see InfoSystem::workerThread(): " << plugin->friendlyName();
|
||||
Q_ASSERT( false );
|
||||
tDebug() << Q_FUNC_INFO << "The object must be moved to the worker thread first, see InfoSystem::workerThread()";
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -58,13 +58,7 @@ InfoSystemWorker::InfoSystemWorker()
|
||||
|
||||
InfoSystemWorker::~InfoSystemWorker()
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO << " beginning";
|
||||
Q_FOREACH( InfoPluginPtr plugin, m_plugins )
|
||||
{
|
||||
if( plugin )
|
||||
delete plugin.data();
|
||||
}
|
||||
tDebug() << Q_FUNC_INFO << " finished";
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
|
||||
@@ -136,29 +130,6 @@ InfoSystemWorker::addInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin )
|
||||
|
||||
emit updatedSupportedGetTypes( QSet< InfoType >::fromList( m_infoGetMap.keys() ) );
|
||||
emit updatedSupportedPushTypes( QSet< InfoType >::fromList( m_infoPushMap.keys() ) );
|
||||
|
||||
connect( plugin.data(), SIGNAL( destroyed( QObject* ) ), SLOT( onInfoPluginDeleted() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoSystemWorker::onInfoPluginDeleted()
|
||||
{
|
||||
foreach( const InfoPluginPtr& plugin, m_plugins )
|
||||
{
|
||||
if ( plugin.isNull() )
|
||||
{
|
||||
m_plugins.removeOne( plugin );
|
||||
foreach( InfoType type, m_infoGetMap.keys() )
|
||||
{
|
||||
m_infoGetMap[type].removeOne( plugin );
|
||||
}
|
||||
foreach( InfoType type, m_infoPushMap.keys() )
|
||||
{
|
||||
m_infoPushMap[type].removeOne( plugin );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -72,7 +72,6 @@ public slots:
|
||||
|
||||
private slots:
|
||||
void checkTimeoutsTimerFired();
|
||||
void onInfoPluginDeleted();
|
||||
|
||||
private:
|
||||
void registerInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType > &getTypes, const QSet< InfoType > &pushTypes );
|
||||
|
@@ -33,6 +33,12 @@ JobStatusItem::~JobStatusItem()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JobStatusItem::activated()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
JobStatusItem::allowMultiLine() const
|
||||
{
|
||||
|
@@ -53,6 +53,8 @@ public:
|
||||
virtual QString mainText() const = 0;
|
||||
virtual QString rightColumnText() const { return QString(); };
|
||||
|
||||
virtual void activated();
|
||||
|
||||
/**
|
||||
* If collapse item is true, sending multiple items of the same type will "collapse" them into one
|
||||
* instead of showing each individually. In this case, the right column from the item will be ignored
|
||||
|
@@ -118,6 +118,7 @@ JobStatusView::setModel( JobStatusSortModel* m )
|
||||
connect( m_view->model(), SIGNAL( customDelegateJobInserted( int, JobStatusItem* ) ), this, SLOT( customDelegateJobInserted( int, JobStatusItem* ) ) );
|
||||
connect( m_view->model(), SIGNAL( customDelegateJobRemoved( int ) ), this, SLOT( customDelegateJobRemoved( int ) ) );
|
||||
connect( m_view->model(), SIGNAL( refreshDelegates() ), this, SLOT( refreshDelegates() ) );
|
||||
connect( m_view, SIGNAL( activated( QModelIndex ) ), this, SLOT( onItemActivated( QModelIndex ) ) );
|
||||
|
||||
foreach ( const QPointer<JobStatusItem> item, s_jobItems )
|
||||
{
|
||||
@@ -184,6 +185,21 @@ JobStatusView::refreshDelegates()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JobStatusView::onItemActivated( const QModelIndex& index )
|
||||
{
|
||||
QVariant itemVar = index.data( JobStatusModel::JobDataRole );
|
||||
if ( !itemVar.canConvert< JobStatusItem* >() || !itemVar.value< JobStatusItem* >() )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "unable to fetch JobStatusItem*";
|
||||
return;
|
||||
}
|
||||
|
||||
JobStatusItem* item = itemVar.value< JobStatusItem* >();
|
||||
item->activated();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JobStatusView::checkCount()
|
||||
{
|
||||
|
@@ -59,6 +59,7 @@ private slots:
|
||||
void customDelegateJobInserted( int row, JobStatusItem* item );
|
||||
void customDelegateJobRemoved( int row );
|
||||
void refreshDelegates();
|
||||
void onItemActivated( const QModelIndex& index );
|
||||
|
||||
private:
|
||||
QListView* m_view;
|
||||
|
37
src/libtomahawk/jobview/ScriptErrorStatusMessage.cpp
Normal file
37
src/libtomahawk/jobview/ScriptErrorStatusMessage.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2016, Dominik Schmidt <domme@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ScriptErrorStatusMessage.h"
|
||||
#include "../utils/Logger.h"
|
||||
|
||||
ScriptErrorStatusMessage::ScriptErrorStatusMessage( const QString& message, Tomahawk::ScriptAccount* account )
|
||||
: ErrorStatusMessage( tr( "Script Error: %1" ).arg( message ) )
|
||||
, m_account( account )
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ScriptErrorStatusMessage::activated()
|
||||
{
|
||||
if ( m_account.isNull() )
|
||||
return;
|
||||
|
||||
tDebug() << "ScriptErrorStatusMessage clicked: " << mainText() << m_account->name();
|
||||
m_account->showDebugger();
|
||||
}
|
||||
|
39
src/libtomahawk/jobview/ScriptErrorStatusMessage.h
Normal file
39
src/libtomahawk/jobview/ScriptErrorStatusMessage.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2016, Dominik Schmidt <domme@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SCRIPTERRORSTATUSMESSAGE_H
|
||||
#define SCRIPTERRORSTATUSMESSAGE_H
|
||||
|
||||
#include "ErrorStatusMessage.h"
|
||||
#include "../resolvers/ScriptAccount.h"
|
||||
|
||||
#include "DllMacro.h"
|
||||
|
||||
class DLLEXPORT ScriptErrorStatusMessage : public ErrorStatusMessage
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ScriptErrorStatusMessage( const QString& scriptErrorMessage, Tomahawk::ScriptAccount* );
|
||||
|
||||
void activated() override;
|
||||
|
||||
private:
|
||||
QPointer< Tomahawk::ScriptAccount > m_account;
|
||||
};
|
||||
|
||||
#endif // SCRIPTERRORSTATUSMESSAGE_H
|
@@ -1371,8 +1371,7 @@ Servent::isIPWhitelisted( QHostAddress ip )
|
||||
}
|
||||
}
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 5, 0, 0 )
|
||||
// Qt4 cannot cope correctly with IPv4 addresses mapped into the IPv6
|
||||
// Qt cannot cope correctly with IPv4 addresses mapped into the IPv6
|
||||
// address space
|
||||
if ( ip.protocol() == QAbstractSocket::IPv6Protocol )
|
||||
{
|
||||
@@ -1397,7 +1396,6 @@ Servent::isIPWhitelisted( QHostAddress ip )
|
||||
return isIPWhitelisted( addr );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "failure";
|
||||
return false;
|
||||
|
@@ -118,6 +118,10 @@ ColumnView::setModel( QAbstractItemModel* model )
|
||||
void
|
||||
ColumnView::setTreeModel( TreeModel* model )
|
||||
{
|
||||
// HACK: without setting a new preview widget, the old preview widget is shown in the first column while loading the artists.
|
||||
m_previewWidget = new ColumnViewPreviewWidget( this );
|
||||
setPreviewWidget( m_previewWidget );
|
||||
|
||||
m_model = model;
|
||||
|
||||
if ( m_proxyModel )
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include "utils/TomahawkUtilsGui.h"
|
||||
#include "utils/DpiScaler.h"
|
||||
#include "ViewManager.h"
|
||||
#include "widgets/DownloadButton.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
@@ -164,6 +165,10 @@ ColumnViewPreviewWidget::ColumnViewPreviewWidget( ColumnView* parent )
|
||||
m_ageValue->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
|
||||
gridLayout->addWidget( m_ageValue, 4, 1 );
|
||||
|
||||
|
||||
m_downloadButton = new DownloadButton( this );
|
||||
mainLayout->addWidget( m_downloadButton );
|
||||
|
||||
mainLayout->addStretch();
|
||||
|
||||
TomahawkUtils::unmarginLayout( mainLayout );
|
||||
@@ -217,6 +222,7 @@ ColumnViewPreviewWidget::setQuery( const Tomahawk::query_ptr& query )
|
||||
m_bitrateValue->setText( tr( "%1 kbps" ).arg( query->results().first()->bitrate() ) );
|
||||
m_durationValue->setText( TomahawkUtils::timeToString( query->track()->duration() ) );
|
||||
m_ageValue->setText( TomahawkUtils::ageToString( QDateTime::fromTime_t( query->results().first()->modificationTime() ) ) );
|
||||
m_downloadButton->setQuery( query );
|
||||
|
||||
m_yearValue->setVisible( query->track()->year() > 0 );
|
||||
m_yearLabel->setVisible( query->track()->year() > 0 );
|
||||
@@ -226,6 +232,7 @@ ColumnViewPreviewWidget::setQuery( const Tomahawk::query_ptr& query )
|
||||
m_durationValue->setVisible( query->track()->duration() > 0 );
|
||||
m_ageLabel->setVisible( query->results().first()->modificationTime() > 0 );
|
||||
m_ageValue->setVisible( query->results().first()->modificationTime() > 0 );
|
||||
m_downloadButton->setVisible( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -237,6 +244,7 @@ ColumnViewPreviewWidget::setQuery( const Tomahawk::query_ptr& query )
|
||||
m_durationValue->setVisible( false );
|
||||
m_ageLabel->setVisible( false );
|
||||
m_ageValue->setVisible( false );
|
||||
m_downloadButton->setVisible( false );
|
||||
}
|
||||
|
||||
setMinimumHeight( sizeHint().height() );
|
||||
|
@@ -30,6 +30,7 @@ class QueryLabel;
|
||||
class PlayableCover;
|
||||
class QLabel;
|
||||
class ScrollingLabel;
|
||||
class DownloadButton;
|
||||
|
||||
class DLLEXPORT ColumnViewPreviewWidget : public QWidget
|
||||
{
|
||||
@@ -71,6 +72,8 @@ private:
|
||||
ScrollingLabel* m_trackLabel;
|
||||
|
||||
QueryLabel* m_artistLabel;
|
||||
|
||||
DownloadButton* m_downloadButton;
|
||||
};
|
||||
|
||||
#endif // COLUMNVIEWPREVIEWWIDGET_H
|
||||
|
@@ -96,8 +96,10 @@ ContextView::ContextView( QWidget* parent, const QString& caption )
|
||||
|
||||
connect( m_captionLabel, SIGNAL( clicked() ), SIGNAL( closeClicked() ) );
|
||||
connect( m_trackView, SIGNAL( querySelected( Tomahawk::query_ptr ) ), SLOT( onQuerySelected( Tomahawk::query_ptr ) ) );
|
||||
connect( m_trackView, SIGNAL( querySelected( Tomahawk::query_ptr ) ), m_detailView, SLOT( setQuery( Tomahawk::query_ptr ) ) );
|
||||
connect( m_trackView, SIGNAL( modelChanged() ), SLOT( onModelChanged() ) );
|
||||
connect( m_trackView, SIGNAL( querySelected( Tomahawk::query_ptr ) ), m_detailView, SLOT( setQuery( Tomahawk::query_ptr ) ) );
|
||||
connect( m_detailView, SIGNAL( downloadAll() ), SLOT( onDownloadAll() ) );
|
||||
connect( m_detailView, SIGNAL( downloadCancel() ), SLOT( onDownloadCancel() ) );
|
||||
|
||||
TomahawkUtils::fixMargins( this );
|
||||
}
|
||||
|
@@ -19,12 +19,6 @@
|
||||
|
||||
#include "GridItemDelegate.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QPainter>
|
||||
#include <QAbstractItemView>
|
||||
#include <QMouseEvent>
|
||||
#include <QTimeLine>
|
||||
|
||||
#include "Artist.h"
|
||||
#include "Query.h"
|
||||
#include "Result.h"
|
||||
@@ -35,6 +29,7 @@
|
||||
#include "playlist/PlayableItem.h"
|
||||
#include "playlist/PlayableProxyModel.h"
|
||||
#include "widgets/HoverControls.h"
|
||||
#include "widgets/DownloadButton.h"
|
||||
#include "widgets/ImageButton.h"
|
||||
#include "utils/TomahawkStyle.h"
|
||||
#include "utils/TomahawkUtilsGui.h"
|
||||
@@ -44,6 +39,12 @@
|
||||
#include "utils/DpiScaler.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QPainter>
|
||||
#include <QAbstractItemView>
|
||||
#include <QMouseEvent>
|
||||
#include <QTimeLine>
|
||||
|
||||
namespace {
|
||||
static const int FADE_DURATION = 400;
|
||||
};
|
||||
@@ -55,6 +56,7 @@ GridItemDelegate::GridItemDelegate( QAbstractItemView* parent, PlayableProxyMode
|
||||
, m_model( proxy )
|
||||
, m_itemWidth( 0 )
|
||||
, m_showPosition( false )
|
||||
, m_showBuyButtons( false )
|
||||
, m_wordWrapping( false )
|
||||
, m_margin( TomahawkUtils::DpiScaler::scaledY( parent, 32 ) )
|
||||
{
|
||||
@@ -93,7 +95,8 @@ GridItemDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelInde
|
||||
if ( !m_wordWrapping )
|
||||
return QSize( m_itemWidth, m_itemWidth + fm.height() + m_margin * 0.8 );
|
||||
|
||||
return QSize( m_itemWidth, m_itemWidth + fm.height() + fms.height() + m_margin * 0.8 );
|
||||
const int buyButtonHeight = m_showBuyButtons ? 40 : 0;
|
||||
return QSize( m_itemWidth, m_itemWidth + fm.height() + fms.height() + buyButtonHeight + m_margin * 0.8 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,6 +278,11 @@ GridItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
|
||||
painter->setFont( f );
|
||||
}
|
||||
|
||||
if ( m_showBuyButtons && !item->query().isNull() )
|
||||
{
|
||||
textRect.adjust( 0, 0, 0, -40 );
|
||||
}
|
||||
|
||||
to.setAlignment( Qt::AlignLeft | Qt::AlignTop );
|
||||
text = painter->fontMetrics().elidedText( top, Qt::ElideRight, textRect.width() - m_margin / 4 );
|
||||
painter->drawText( textRect, text, to );
|
||||
@@ -286,6 +294,7 @@ GridItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
|
||||
}
|
||||
painter->restore();
|
||||
|
||||
painter->save();
|
||||
painter->setOpacity( 0.6 );
|
||||
painter->setFont( m_smallFont );
|
||||
|
||||
@@ -304,6 +313,19 @@ GridItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
|
||||
|
||||
// Calculate rect of artist on-hover button click area
|
||||
m_artistNameRects[ index ] = painter->fontMetrics().boundingRect( textRect, Qt::AlignLeft | Qt::AlignBottom, text );
|
||||
painter->restore();
|
||||
|
||||
if ( m_showBuyButtons && !item->query().isNull() )
|
||||
{
|
||||
QRect r = textRect;
|
||||
r.setY( textRect.y() + textRect.height() + 8 );
|
||||
r.setHeight( 32 );
|
||||
|
||||
if( DownloadButton::drawPrimitive(painter, r, item->query(), m_hoveringOverBuyButton == index ) )
|
||||
{
|
||||
m_buyButtonRects[ index ] = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
@@ -362,6 +384,7 @@ GridItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, const Q
|
||||
const QMouseEvent* ev = static_cast< QMouseEvent* >( event );
|
||||
bool hoveringArtist = false;
|
||||
bool hoveringAlbum = false;
|
||||
bool hoveringBuyButton = false;
|
||||
if ( m_artistNameRects.contains( index ) )
|
||||
{
|
||||
const QRect artistNameRect = m_artistNameRects[ index ];
|
||||
@@ -372,6 +395,11 @@ GridItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, const Q
|
||||
const QRect albumNameRect = m_albumNameRects[ index ];
|
||||
hoveringAlbum = albumNameRect.contains( ev->pos() );
|
||||
}
|
||||
if ( m_buyButtonRects.contains( index ) )
|
||||
{
|
||||
const QRect buyButtonRect = m_buyButtonRects[ index ];
|
||||
hoveringBuyButton = buyButtonRect.contains( ev->pos() );
|
||||
}
|
||||
|
||||
QRect coverRect = m_view->visualRect( index );
|
||||
coverRect.setHeight( coverRect.width() );
|
||||
@@ -379,7 +407,7 @@ GridItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, const Q
|
||||
|
||||
if ( event->type() == QEvent::MouseMove )
|
||||
{
|
||||
if ( hoveringArtist || hoveringAlbum )
|
||||
if ( hoveringArtist || hoveringAlbum || hoveringBuyButton )
|
||||
m_view->setCursor( Qt::PointingHandCursor );
|
||||
else
|
||||
m_view->setCursor( Qt::ArrowCursor );
|
||||
@@ -435,6 +463,17 @@ GridItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, const Q
|
||||
|
||||
emit updateIndex( index );
|
||||
}
|
||||
if ( m_hoveringOverBuyButton != index || ( !hoveringBuyButton && m_hoveringOverBuyButton.isValid() ) )
|
||||
{
|
||||
emit updateIndex( m_hoveringOverBuyButton );
|
||||
|
||||
if ( hoveringBuyButton )
|
||||
m_hoveringOverBuyButton = index;
|
||||
else
|
||||
m_hoveringOverBuyButton = QPersistentModelIndex();
|
||||
|
||||
emit updateIndex( index );
|
||||
}
|
||||
|
||||
if ( m_hoverIndex != index || !hoveringCover )
|
||||
{
|
||||
@@ -544,6 +583,11 @@ GridItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, const Q
|
||||
}
|
||||
}
|
||||
|
||||
if ( hoveringBuyButton )
|
||||
{
|
||||
return DownloadButton::handleEditorEvent( event, m_view, m_model, index );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -555,6 +599,7 @@ GridItemDelegate::modelChanged()
|
||||
m_albumNameRects.clear();
|
||||
m_hoveringOverArtist = QPersistentModelIndex();
|
||||
m_hoveringOverAlbum = QPersistentModelIndex();
|
||||
m_hoveringOverBuyButton = QPersistentModelIndex();
|
||||
m_hoverIndex = QPersistentModelIndex();
|
||||
|
||||
clearButtons();
|
||||
@@ -687,6 +732,10 @@ GridItemDelegate::resetHoverIndex()
|
||||
idx = m_hoveringOverAlbum;
|
||||
m_hoveringOverAlbum = QPersistentModelIndex();
|
||||
doUpdateIndex( idx );
|
||||
|
||||
idx = m_hoveringOverBuyButton;
|
||||
m_hoveringOverBuyButton = QPersistentModelIndex();
|
||||
doUpdateIndex( idx );
|
||||
}
|
||||
|
||||
|
||||
@@ -758,3 +807,41 @@ GridItemDelegate::eventFilter( QObject* obj, QEvent* event )
|
||||
else
|
||||
return QObject::eventFilter( obj, event );
|
||||
}
|
||||
|
||||
|
||||
QWidget*
|
||||
GridItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||
{
|
||||
PlayableItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) );
|
||||
Q_ASSERT( item );
|
||||
|
||||
return DownloadButton::handleCreateEditor( parent, item->query(), m_view, index );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GridItemDelegate::updateEditorGeometry( QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||
{
|
||||
QStyledItemDelegate::updateEditorGeometry( editor, option, index );
|
||||
|
||||
DownloadButton* comboBox = static_cast<DownloadButton*>(editor);
|
||||
comboBox->resize( option.rect.size() - QSize( 8, 0 ) );
|
||||
comboBox->move( option.rect.x() + 4, option.rect.y() );
|
||||
|
||||
if ( m_buyButtonRects.contains( index ) )
|
||||
{
|
||||
editor->setGeometry( m_buyButtonRects.value( index ) );
|
||||
}
|
||||
|
||||
if ( !comboBox->property( "shownPopup" ).toBool() )
|
||||
{
|
||||
comboBox->showPopup();
|
||||
comboBox->setProperty( "shownPopup", true );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GridItemDelegate::setModelData( QWidget* editor, QAbstractItemModel* model, const QModelIndex& index ) const
|
||||
{
|
||||
}
|
||||
|
@@ -48,6 +48,7 @@ public:
|
||||
|
||||
QSize itemSize() const;
|
||||
void setItemWidth( int width ) { m_itemWidth = width; }
|
||||
void setShowBuyButtons( bool enabled ) { m_showBuyButtons = enabled; }
|
||||
|
||||
public slots:
|
||||
void resetHoverIndex();
|
||||
@@ -61,6 +62,10 @@ protected:
|
||||
bool editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index );
|
||||
bool eventFilter( QObject* obj, QEvent* event );
|
||||
|
||||
QWidget* createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
|
||||
void updateEditorGeometry( QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
|
||||
void setModelData( QWidget* editor, QAbstractItemModel* model, const QModelIndex& index ) const;
|
||||
|
||||
signals:
|
||||
void updateIndex( const QModelIndex& idx );
|
||||
|
||||
@@ -90,15 +95,18 @@ private:
|
||||
PlayableProxyModel* m_model;
|
||||
int m_itemWidth;
|
||||
bool m_showPosition;
|
||||
bool m_showBuyButtons;
|
||||
bool m_wordWrapping;
|
||||
|
||||
mutable QHash< QPersistentModelIndex, QRect > m_artistNameRects;
|
||||
mutable QHash< QPersistentModelIndex, QRect > m_albumNameRects;
|
||||
mutable QHash< QPersistentModelIndex, QRect > m_buyButtonRects;
|
||||
mutable QHash< QPersistentModelIndex, QSharedPointer< Tomahawk::PixmapDelegateFader > > m_covers;
|
||||
|
||||
QPersistentModelIndex m_hoverIndex;
|
||||
QPersistentModelIndex m_hoveringOverArtist;
|
||||
QPersistentModelIndex m_hoveringOverAlbum;
|
||||
QPersistentModelIndex m_hoveringOverBuyButton;
|
||||
|
||||
mutable QHash< QPersistentModelIndex, QWidget* > m_spinner;
|
||||
mutable QHash< QPersistentModelIndex, HoverControls* > m_hoverControls;
|
||||
|
@@ -255,6 +255,8 @@ void GridView::wheelEvent( QWheelEvent* e )
|
||||
// ^ scroll step is 1/8 of the estimated row height
|
||||
|
||||
QListView::wheelEvent( e );
|
||||
|
||||
m_delegate->resetHoverIndex();
|
||||
}
|
||||
|
||||
|
||||
|
@@ -119,8 +119,9 @@ int
|
||||
PlayableModel::columnCount( const QModelIndex& parent ) const
|
||||
{
|
||||
Q_UNUSED( parent );
|
||||
Q_D( const PlayableModel );
|
||||
|
||||
return 13;
|
||||
return d->header.length();
|
||||
}
|
||||
|
||||
|
||||
@@ -444,14 +445,21 @@ PlayableModel::flags( const QModelIndex& index ) const
|
||||
|
||||
if ( index.isValid() )
|
||||
{
|
||||
Qt::ItemFlags returnFlags = defaultFlags;
|
||||
if ( index.column() == 0 )
|
||||
{
|
||||
return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
|
||||
returnFlags |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
|
||||
}
|
||||
else if ( index.column() == PlayableModel::Download )
|
||||
{
|
||||
return Qt::ItemIsEditable | defaultFlags;
|
||||
returnFlags |= Qt::ItemIsEditable | defaultFlags;
|
||||
}
|
||||
|
||||
if ( areAllColumnsEditable() ) {
|
||||
returnFlags |= Qt::ItemIsEditable;
|
||||
}
|
||||
|
||||
return returnFlags;
|
||||
}
|
||||
|
||||
return Qt::ItemIsDropEnabled | defaultFlags;
|
||||
@@ -1019,7 +1027,7 @@ PlayableModel::appendAlbums( const QList< Tomahawk::album_ptr >& albums )
|
||||
void
|
||||
PlayableModel::appendAlbums( const Tomahawk::collection_ptr& collection )
|
||||
{
|
||||
emit loadingStarted();
|
||||
startLoading();
|
||||
insertAlbums( collection, rowCount( QModelIndex() ) );
|
||||
}
|
||||
|
||||
@@ -1034,7 +1042,7 @@ PlayableModel::appendQueries( const QList< Tomahawk::query_ptr >& queries )
|
||||
void
|
||||
PlayableModel::appendTracks( const QList< Tomahawk::track_ptr >& tracks, const QList< Tomahawk::PlaybackLog >& logs )
|
||||
{
|
||||
emit loadingStarted();
|
||||
startLoading();
|
||||
QList< Tomahawk::query_ptr > queries;
|
||||
foreach ( const track_ptr& track, tracks )
|
||||
{
|
||||
@@ -1048,7 +1056,7 @@ PlayableModel::appendTracks( const QList< Tomahawk::track_ptr >& tracks, const Q
|
||||
void
|
||||
PlayableModel::appendTracks( const Tomahawk::collection_ptr& collection )
|
||||
{
|
||||
emit loadingStarted();
|
||||
startLoading();
|
||||
insertTracks( collection, rowCount( QModelIndex() ) );
|
||||
}
|
||||
|
||||
@@ -1171,6 +1179,22 @@ PlayableModel::setIcon( const QPixmap& pixmap )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::setAllColumnsEditable( bool editable )
|
||||
{
|
||||
Q_D( PlayableModel );
|
||||
d->areAllColumnsEditable = editable;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PlayableModel::areAllColumnsEditable() const
|
||||
{
|
||||
Q_D( const PlayableModel );
|
||||
return d->areAllColumnsEditable;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
PlayableModel::trackCount() const
|
||||
{
|
||||
|
@@ -96,6 +96,11 @@ public:
|
||||
virtual QPixmap icon() const;
|
||||
virtual void setIcon( const QPixmap& pixmap );
|
||||
|
||||
|
||||
// HACK: we need to set column 0 editable for DropDownButton in TrackView
|
||||
void setAllColumnsEditable( bool editable );
|
||||
bool areAllColumnsEditable() const;
|
||||
|
||||
virtual int trackCount() const;
|
||||
virtual int itemCount() const;
|
||||
|
||||
|
@@ -38,6 +38,7 @@ public:
|
||||
, rootItem( new PlayableItem( 0 ) )
|
||||
, readOnly( true )
|
||||
, loading( _loading )
|
||||
, areAllColumnsEditable( false )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -58,6 +59,7 @@ private:
|
||||
QStringList header;
|
||||
|
||||
bool loading;
|
||||
bool areAllColumnsEditable;
|
||||
};
|
||||
|
||||
#endif // PLAYABLEMODEL_P_H
|
||||
|
@@ -607,25 +607,7 @@ PlayableProxyModel::columnCount( const QModelIndex& parent ) const
|
||||
{
|
||||
Q_UNUSED( parent );
|
||||
|
||||
switch ( m_style )
|
||||
{
|
||||
case SingleColumn:
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case Collection:
|
||||
return 10;
|
||||
break;
|
||||
|
||||
case Locker:
|
||||
return 11;
|
||||
break;
|
||||
|
||||
case Detailed:
|
||||
default:
|
||||
return 12;
|
||||
break;
|
||||
}
|
||||
return m_headerStyle[ m_style ].length();
|
||||
}
|
||||
|
||||
|
||||
@@ -733,6 +715,13 @@ PlayableProxyModel::setFilter( const QString& pattern )
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
PlayableProxyModel::mapSourceColumnToColumn( PlayableModel::Columns column )
|
||||
{
|
||||
return m_headerStyle[ m_style ].indexOf( column );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableProxyModel::setCurrentIndex( const QModelIndex& index )
|
||||
{
|
||||
|
@@ -98,6 +98,8 @@ public:
|
||||
virtual void setFilter( const QString& pattern );
|
||||
virtual void updateDetailedInfo( const QModelIndex& index );
|
||||
|
||||
int mapSourceColumnToColumn( PlayableModel::Columns column );
|
||||
|
||||
signals:
|
||||
void filterChanged( const QString& filter );
|
||||
|
||||
|
@@ -20,14 +20,6 @@
|
||||
|
||||
#include "PlaylistItemDelegate.h"
|
||||
|
||||
#include <QAbstractTextDocumentLayout>
|
||||
#include <QApplication>
|
||||
#include <QDateTime>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QDesktopServices>
|
||||
#include <QToolTip>
|
||||
|
||||
#include "Query.h"
|
||||
#include "Result.h"
|
||||
#include "Artist.h"
|
||||
@@ -35,8 +27,6 @@
|
||||
#include "Source.h"
|
||||
#include "SourceList.h"
|
||||
|
||||
#include "DownloadManager.h"
|
||||
#include "DownloadJob.h"
|
||||
#include "PlayableModel.h"
|
||||
#include "PlayableItem.h"
|
||||
#include "PlayableProxyModel.h"
|
||||
@@ -44,7 +34,7 @@
|
||||
#include "ViewHeader.h"
|
||||
#include "ViewManager.h"
|
||||
|
||||
#include "widgets/DropDownButton.h"
|
||||
#include "widgets/DownloadButton.h"
|
||||
#include "audio/AudioEngine.h"
|
||||
#include "utils/ImageRegistry.h"
|
||||
#include "utils/PixmapDelegateFader.h"
|
||||
@@ -53,6 +43,13 @@
|
||||
#include "utils/TomahawkUtilsGui.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
#include <QAbstractTextDocumentLayout>
|
||||
#include <QApplication>
|
||||
#include <QDateTime>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QToolTip>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
@@ -123,63 +120,7 @@ PlaylistItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem&
|
||||
PlayableItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) );
|
||||
Q_ASSERT( item );
|
||||
|
||||
if ( index.column() == PlayableModel::Download && item->result() && !item->result()->downloadFormats().isEmpty() &&
|
||||
!DownloadManager::instance()->localFileForDownload( item->result()->downloadFormats().first().url.toString() ).isEmpty() )
|
||||
{
|
||||
QDesktopServices::openUrl( QUrl::fromLocalFile( QFileInfo( DownloadManager::instance()->localFileForDownload( item->result()->downloadFormats().first().url.toString() ) ).absolutePath() ) );
|
||||
}
|
||||
else if ( index.column() == PlayableModel::Download && item->result() && item->result()->downloadJob() && item->result()->downloadJob()->state() == DownloadJob::Finished )
|
||||
{
|
||||
QDesktopServices::openUrl( QUrl::fromLocalFile( QFileInfo( item->result()->downloadJob()->localFile() ).absolutePath() ) );
|
||||
}
|
||||
else if ( index.column() == PlayableModel::Download && item->result() &&
|
||||
!item->result()->downloadFormats().isEmpty() && !item->result()->downloadJob() )
|
||||
{
|
||||
QStringList formats;
|
||||
foreach ( const DownloadFormat& format, item->result()->downloadFormats() )
|
||||
{
|
||||
formats << tr( "Download %1" ).arg( format.extension );
|
||||
}
|
||||
|
||||
DropDownButton* editor = new DropDownButton( parent );
|
||||
editor->addItems( formats );
|
||||
|
||||
NewClosure( editor, SIGNAL( clicked() ),
|
||||
const_cast<PlaylistItemDelegate*>(this), SLOT( addDownloadJob( const QModelIndex&, QWidget* ) ), index, (QWidget*)editor );
|
||||
|
||||
NewClosure( editor, SIGNAL( activated( int ) ),
|
||||
const_cast<PlaylistItemDelegate*>(this), SLOT( addDownloadJob( const QModelIndex&, QWidget* ) ), index, (QWidget*)editor );
|
||||
return editor;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistItemDelegate::addDownloadJob( const QModelIndex& index, QWidget* editor )
|
||||
{
|
||||
PlayableItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) );
|
||||
Q_ASSERT( item );
|
||||
|
||||
m_view->closePersistentEditor( index );
|
||||
|
||||
DropDownButton* cb = static_cast< DropDownButton* >(editor);
|
||||
if ( !item->result()->downloadFormats().isEmpty() )
|
||||
DownloadManager::instance()->addJob( item->result()->toDownloadJob( item->result()->downloadFormats().at( cb->currentIndex() ) ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistItemDelegate::closeEditor( const QModelIndex& index, QWidget* editor )
|
||||
{
|
||||
PlayableItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) );
|
||||
Q_ASSERT( item );
|
||||
|
||||
m_view->closePersistentEditor( index );
|
||||
|
||||
DropDownButton* cb = static_cast< DropDownButton* >(editor);
|
||||
editor->deleteLater();
|
||||
return DownloadButton::handleCreateEditor( parent, item->query(), m_view, index );
|
||||
}
|
||||
|
||||
|
||||
@@ -188,13 +129,18 @@ PlaylistItemDelegate::updateEditorGeometry( QWidget* editor, const QStyleOptionV
|
||||
{
|
||||
QStyledItemDelegate::updateEditorGeometry( editor, option, index );
|
||||
|
||||
DropDownButton* comboBox = static_cast<DropDownButton*>(editor);
|
||||
DownloadButton* comboBox = static_cast<DownloadButton*>(editor);
|
||||
comboBox->resize( option.rect.size() - QSize( 8, 0 ) );
|
||||
comboBox->move( option.rect.x() + 4, option.rect.y() );
|
||||
|
||||
if ( m_downloadDropDownRects.contains( index ) )
|
||||
{
|
||||
editor->setGeometry( m_downloadDropDownRects.value( index ) );
|
||||
}
|
||||
|
||||
if ( !comboBox->property( "shownPopup" ).toBool() )
|
||||
{
|
||||
// comboBox->showPopup();
|
||||
comboBox->showPopup();
|
||||
comboBox->setProperty( "shownPopup", true );
|
||||
}
|
||||
}
|
||||
@@ -270,68 +216,7 @@ PlaylistItemDelegate::paintDetailed( QPainter* painter, const QStyleOptionViewIt
|
||||
else */
|
||||
if ( m_view->proxyModel()->style() == PlayableProxyModel::Locker && index.column() == PlayableModel::Download )
|
||||
{
|
||||
if ( item->result() && !item->result()->downloadFormats().isEmpty() )
|
||||
{
|
||||
QStyleOptionComboBox optc;
|
||||
optc.rect = opt.rect.adjusted( 4, 0, -4, 0 );
|
||||
optc.editable = false;
|
||||
optc.currentText = tr( "Download %1" ).arg( item->result()->downloadFormats().first().extension );
|
||||
optc.palette = m_view->palette();
|
||||
|
||||
if ( option.state & QStyle::State_Selected && option.state & QStyle::State_Active )
|
||||
optc.state = QStyle::State_Active | QStyle::State_Selected | QStyle::State_Enabled;
|
||||
else
|
||||
optc.state = QStyle::State_Active | QStyle::State_Enabled;
|
||||
|
||||
if ( !DownloadManager::instance()->localFileForDownload( item->result()->downloadFormats().first().url.toString() ).isEmpty() )
|
||||
{
|
||||
painter->setPen( opt.palette.text().color() );
|
||||
const QString text = painter->fontMetrics().elidedText( tr( "View in Finder" ), Qt::ElideRight, opt.rect.width() - 3 );
|
||||
painter->drawText( opt.rect, text, textOption );
|
||||
}
|
||||
else if ( !item->result()->downloadJob() )
|
||||
{
|
||||
DropDownButton::drawPrimitive( painter, optc.rect, optc.currentText );
|
||||
/* QApplication::style()->drawComplexControl( QStyle::CC_ComboBox, &optc, painter, 0 );
|
||||
optc.rect.adjust( 4, 0, 0, 0 );
|
||||
QApplication::style()->drawControl( QStyle::CE_ComboBoxLabel, &optc, painter, 0 );*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( item->result()->downloadJob()->state() == DownloadJob::Finished )
|
||||
{
|
||||
painter->setPen( opt.palette.text().color() );
|
||||
const QString text = painter->fontMetrics().elidedText( tr( "View in Finder" ), Qt::ElideRight, opt.rect.width() - 3 );
|
||||
painter->drawText( opt.rect, text, textOption );
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setPen( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND.darker() );
|
||||
painter->setBrush( TomahawkStyle::PLAYLIST_PROGRESS_BACKGROUND );
|
||||
painter->drawRect( optc.rect.adjusted( 2, 2, -2, -2 ) );
|
||||
painter->setPen( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND );
|
||||
painter->setBrush( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND );
|
||||
QRect fillp = optc.rect.adjusted( 3, 3, -3, -3 );
|
||||
fillp.setWidth( float(fillp.width()) * ( float(item->result()->downloadJob()->progressPercentage()) / 100.0 ) );
|
||||
painter->drawRect( fillp );
|
||||
|
||||
/* QStyleOptionProgressBarV2 optp;
|
||||
optp.rect = optc.rect;
|
||||
optp.minimum = 0;
|
||||
optp.maximum = 100;
|
||||
optp.progress = item->result()->downloadJob()->progressPercentage();
|
||||
optp.palette = m_view->palette();
|
||||
optp.palette.setColor( QPalette::Highlight, QColor( "#E61878" ) );
|
||||
|
||||
if ( option.state & QStyle::State_Selected && option.state & QStyle::State_Active )
|
||||
optp.state = QStyle::State_Active | QStyle::State_Selected | QStyle::State_Enabled;
|
||||
else
|
||||
optp.state = QStyle::State_Active | QStyle::State_Enabled;
|
||||
|
||||
QApplication::style()->drawControl( QStyle::CE_ProgressBar, &optp, painter, 0 );*/
|
||||
}
|
||||
}
|
||||
}
|
||||
DownloadButton::drawPrimitive( painter, opt.rect.adjusted( 4, 0, -4, 0 ), item->query(), hoveringOver() == index );
|
||||
}
|
||||
else if ( item->isPlaying() )
|
||||
{
|
||||
@@ -604,6 +489,7 @@ QRect
|
||||
PlaylistItemDelegate::drawTrack( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index, const QRect& rect, PlayableItem* item ) const
|
||||
{
|
||||
const track_ptr track = item->query()->track();
|
||||
const bool hasOnlineResults = ( item->query()->numResults( true ) > 0 );
|
||||
|
||||
painter->save();
|
||||
painter->setRenderHint( QPainter::TextAntialiasing );
|
||||
@@ -630,21 +516,34 @@ PlaylistItemDelegate::drawTrack( QPainter* painter, const QStyleOptionViewItem&
|
||||
|
||||
QRect numberRect = QRect( r.x(), r.y(), numberWidth, r.height() );
|
||||
QRect extraRect = QRect( r.x() + r.width() - durationWidth, r.y(), durationWidth, r.height() );
|
||||
QRect stateRect;
|
||||
if ( option.state & QStyle::State_Selected || hoveringOver() == index )
|
||||
QRect stateRect = extraRect.adjusted( 0, 0, 0, 0 );
|
||||
|
||||
if ( option.state & QStyle::State_Selected || hoveringOver() == index )
|
||||
{
|
||||
int h = extraRect.height() / 3;
|
||||
|
||||
if ( track->loved() )
|
||||
{
|
||||
painter->save();
|
||||
painter->setOpacity( 0.5 );
|
||||
int h = extraRect.height() / 3;
|
||||
stateRect = extraRect.adjusted( -16, extraRect.height() / 2 - h / 2, 0, 0 );
|
||||
stateRect.setHeight( h );
|
||||
stateRect.setWidth( stateRect.height() );
|
||||
painter->drawPixmap( stateRect, ImageRegistry::instance()->pixmap( RESPATH "images/love.svg", stateRect.size() ) );
|
||||
QRect r = stateRect.adjusted( -16, extraRect.height() / 2 - h / 2, 0, 0 );
|
||||
r.setHeight( h );
|
||||
r.setWidth( r.height() );
|
||||
painter->drawPixmap( r, ImageRegistry::instance()->pixmap( RESPATH "images/love.svg", r.size() ) );
|
||||
painter->restore();
|
||||
|
||||
stateWidth = stateRect.width() + 16;
|
||||
stateWidth += r.width() + 16;
|
||||
}
|
||||
}
|
||||
|
||||
QRect downloadButtonRect = stateRect.adjusted( -stateWidth -144, 6, 0, -6 );
|
||||
downloadButtonRect.setWidth( 144 );
|
||||
stateWidth += downloadButtonRect.width() + 16;
|
||||
if ( DownloadButton::drawPrimitive( painter, downloadButtonRect, item->query(), m_hoveringOverDownloadButton == index ) )
|
||||
{
|
||||
m_downloadDropDownRects[ index ] = downloadButtonRect;
|
||||
}
|
||||
|
||||
const int remWidth = r.width() - numberWidth - durationWidth;
|
||||
|
||||
QRect titleRect = QRect( numberRect.x() + numberRect.width(), r.y(), (double)remWidth * 0.5, r.height() );
|
||||
@@ -708,6 +607,7 @@ PlaylistItemDelegate::drawTrack( QPainter* painter, const QStyleOptionViewItem&
|
||||
|
||||
int h = extraRect.height() / 2;
|
||||
QRect playIconRect = extraRect.adjusted( extraRect.width() - h - 8, h / 2, -8, -h / 2 );
|
||||
playIconRect.setWidth( playIconRect.height() );
|
||||
painter->drawPixmap( playIconRect, ImageRegistry::instance()->pixmap( RESPATH "images/play.svg", playIconRect.size() ) );
|
||||
|
||||
double duration = (double)AudioEngine::instance()->currentTrackTotalTime();
|
||||
@@ -759,8 +659,10 @@ PlaylistItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, con
|
||||
bool hoveringArtist = false;
|
||||
bool hoveringInfo = false;
|
||||
bool hoveringLove = false;
|
||||
bool hoveringDownloadDropDown = false;
|
||||
Tomahawk::source_ptr hoveredAvatar;
|
||||
QRect hoveredAvatarRect;
|
||||
|
||||
if ( m_infoButtonRects.contains( index ) )
|
||||
{
|
||||
const QRect infoRect = m_infoButtonRects[ index ];
|
||||
@@ -779,6 +681,12 @@ PlaylistItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, con
|
||||
const QMouseEvent* ev = static_cast< QMouseEvent* >( event );
|
||||
hoveringLove = loveRect.contains( ev->pos() );
|
||||
}
|
||||
if ( m_downloadDropDownRects.contains( index ) )
|
||||
{
|
||||
const QRect downloadDropDownRect = m_downloadDropDownRects[ index ];
|
||||
const QMouseEvent* ev = static_cast< QMouseEvent* >( event );
|
||||
hoveringDownloadDropDown = downloadDropDownRect.contains( ev->pos() );
|
||||
}
|
||||
if ( m_avatarBoxRects.contains( index ) )
|
||||
{
|
||||
const QMouseEvent* ev = static_cast< QMouseEvent* >( event );
|
||||
@@ -796,7 +704,7 @@ PlaylistItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, con
|
||||
|
||||
if ( event->type() == QEvent::MouseMove )
|
||||
{
|
||||
if ( hoveringInfo || hoveringLove || hoveringArtist )
|
||||
if ( hoveringInfo || hoveringLove || hoveringArtist || hoveringDownloadDropDown )
|
||||
m_view->setCursor( Qt::PointingHandCursor );
|
||||
else
|
||||
m_view->setCursor( Qt::ArrowCursor );
|
||||
@@ -820,6 +728,23 @@ PlaylistItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, con
|
||||
emit updateIndex( m_hoveringOverArtist );
|
||||
m_hoveringOverArtist = QModelIndex();
|
||||
}
|
||||
if ( hoveringDownloadDropDown && m_hoveringOverDownloadButton != index )
|
||||
{
|
||||
QPersistentModelIndex ti = m_hoveringOverDownloadButton;
|
||||
m_hoveringOverDownloadButton = index;
|
||||
|
||||
PlayableItem* item = m_model->sourceModel()->itemFromIndex( m_model->mapToSource( ti ) );
|
||||
item->requestRepaint();
|
||||
emit updateIndex( m_hoveringOverDownloadButton );
|
||||
}
|
||||
if ( !hoveringDownloadDropDown && m_hoveringOverDownloadButton.isValid() )
|
||||
{
|
||||
QPersistentModelIndex ti = m_hoveringOverDownloadButton;
|
||||
m_hoveringOverDownloadButton = QModelIndex();
|
||||
|
||||
PlayableItem* item = m_model->sourceModel()->itemFromIndex( m_model->mapToSource( ti ) );
|
||||
item->requestRepaint();
|
||||
}
|
||||
|
||||
if ( m_hoveringOver != index )
|
||||
{
|
||||
@@ -849,6 +774,11 @@ PlaylistItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, con
|
||||
{
|
||||
item->query()->queryTrack()->setLoved( !item->query()->queryTrack()->loved() );
|
||||
}
|
||||
else if ( hoveringDownloadDropDown || ( m_view->proxyModel()->style() == PlayableProxyModel::Locker && index.column() == PlayableModel::Download ) )
|
||||
{
|
||||
if ( DownloadButton::handleEditorEvent( event , m_view, m_model, index ) )
|
||||
return true;
|
||||
}
|
||||
else if ( hoveringInfo )
|
||||
{
|
||||
if ( m_model->style() == PlayableProxyModel::SingleColumn )
|
||||
@@ -883,11 +813,6 @@ PlaylistItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, con
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( m_view->proxyModel()->style() == PlayableProxyModel::Locker && index.column() == PlayableModel::Download )
|
||||
{
|
||||
m_view->edit( index );
|
||||
return true;
|
||||
}
|
||||
|
||||
event->accept();
|
||||
return true;
|
||||
@@ -900,13 +825,14 @@ PlaylistItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, con
|
||||
void
|
||||
PlaylistItemDelegate::resetHoverIndex()
|
||||
{
|
||||
if ( !m_model )
|
||||
if ( !m_model || !m_hoveringOver.isValid() )
|
||||
return;
|
||||
|
||||
QPersistentModelIndex idx = m_hoveringOver;
|
||||
|
||||
m_hoveringOver = QModelIndex();
|
||||
m_hoveringOverArtist = QModelIndex();
|
||||
m_hoveringOverDownloadButton = QModelIndex();
|
||||
m_infoButtonRects.clear();
|
||||
m_loveButtonRects.clear();
|
||||
m_artistNameRects.clear();
|
||||
@@ -920,7 +846,6 @@ PlaylistItemDelegate::resetHoverIndex()
|
||||
}
|
||||
|
||||
emit updateIndex( idx );
|
||||
m_view->repaint();
|
||||
}
|
||||
|
||||
|
||||
|
@@ -57,8 +57,6 @@ signals:
|
||||
|
||||
private slots:
|
||||
void doUpdateIndex( const QPersistentModelIndex& index );
|
||||
void closeEditor( const QModelIndex& index, QWidget* editor );
|
||||
void addDownloadJob( const QModelIndex& index, QWidget* editor );
|
||||
|
||||
protected:
|
||||
void prepareStyleOption( QStyleOptionViewItemV4* option, const QModelIndex& index, PlayableItem* item ) const;
|
||||
@@ -116,10 +114,12 @@ private:
|
||||
mutable QHash< QPersistentModelIndex, QSharedPointer< Tomahawk::PixmapDelegateFader > > m_pixmaps;
|
||||
mutable QHash< QPersistentModelIndex, QRect > m_infoButtonRects;
|
||||
mutable QHash< QPersistentModelIndex, QRect > m_loveButtonRects;
|
||||
mutable QHash< QPersistentModelIndex, QRect > m_downloadDropDownRects;
|
||||
mutable QHash< QPersistentModelIndex, QRect > m_artistNameRects;
|
||||
mutable QHash< QPersistentModelIndex, QHash< Tomahawk::source_ptr, QRect > > m_avatarBoxRects;
|
||||
QPersistentModelIndex m_hoveringOver;
|
||||
QPersistentModelIndex m_hoveringOverArtist;
|
||||
QPersistentModelIndex m_hoveringOverDownloadButton;
|
||||
mutable QPersistentModelIndex m_nowPlaying;
|
||||
|
||||
TrackView* m_view;
|
||||
|
@@ -18,11 +18,6 @@
|
||||
|
||||
#include "TrackDetailView.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QScrollArea>
|
||||
#include <QSizePolicy>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "Album.h"
|
||||
#include "Track.h"
|
||||
#include "audio/AudioEngine.h"
|
||||
@@ -35,13 +30,22 @@
|
||||
#include "utils/ImageRegistry.h"
|
||||
#include "utils/TomahawkUtilsGui.h"
|
||||
#include "utils/Closure.h"
|
||||
#include "utils/WebPopup.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QScrollArea>
|
||||
#include <QSizePolicy>
|
||||
#include <QVBoxLayout>
|
||||
#include <QDesktopServices>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
TrackDetailView::TrackDetailView( QWidget* parent )
|
||||
: QWidget( parent )
|
||||
, DpiScaler( this )
|
||||
, m_buyButtonVisible( false )
|
||||
{
|
||||
setFixedWidth( scaledX( 200 ) );
|
||||
setContentsMargins( 0, 0, 0, 0 );
|
||||
@@ -118,11 +122,21 @@ TrackDetailView::TrackDetailView( QWidget* parent )
|
||||
TomahawkStyle::styleScrollBar( m_resultsScrollArea->verticalScrollBar() );
|
||||
m_resultsScrollArea->hide();
|
||||
|
||||
m_buyButton = new QPushButton;
|
||||
m_buyButton->setStyleSheet( "QPushButton:hover { font-size: 12px; color: #ffffff; background: #000000; border-style: solid; border-radius: 0px; border-width: 2px; border-color: #2b2b2b; }"
|
||||
"QPushButton { font-size: 12px; color: #ffffff; background-color: #000000; border-style: solid; border-radius: 0px; border-width: 0px; }" );
|
||||
m_buyButton->setMinimumHeight( 30 );
|
||||
m_buyButton->setText( tr( "Buy Album" ) );
|
||||
m_buyButton->setVisible( false );
|
||||
connect( m_buyButton, SIGNAL( clicked() ), SLOT( onBuyButtonClicked() ) );
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout;
|
||||
TomahawkUtils::unmarginLayout( layout );
|
||||
layout->addWidget( m_playableCover );
|
||||
layout->addSpacerItem( new QSpacerItem( 0, 8, QSizePolicy::Minimum, QSizePolicy::Fixed ) );
|
||||
layout->addWidget( m_nameLabel );
|
||||
layout->addSpacerItem( new QSpacerItem( 0, 4, QSizePolicy::Minimum, QSizePolicy::Fixed ) );
|
||||
layout->addWidget( m_buyButton );
|
||||
layout->addWidget( m_dateLabel );
|
||||
layout->addWidget( m_infoBox );
|
||||
layout->addSpacerItem( new QSpacerItem( 0, 32, QSizePolicy::Minimum, QSizePolicy::Fixed ) );
|
||||
@@ -134,6 +148,9 @@ TrackDetailView::TrackDetailView( QWidget* parent )
|
||||
|
||||
setLayout( layout );
|
||||
setQuery( query_ptr() );
|
||||
|
||||
connect( DownloadManager::instance(), SIGNAL( stateChanged( DownloadManager::DownloadManagerState, DownloadManager::DownloadManagerState ) ),
|
||||
SLOT( onDownloadManagerStateChanged( DownloadManager::DownloadManagerState, DownloadManager::DownloadManagerState ) ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -154,6 +171,10 @@ TrackDetailView::setQuery( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
if ( m_query )
|
||||
{
|
||||
if ( m_query->track()->albumPtr() && !m_query->track()->albumPtr()->name().isEmpty() )
|
||||
{
|
||||
disconnect( m_query->track()->albumPtr().data(), SIGNAL( updated() ), this, SLOT( onAlbumUpdated() ) );
|
||||
}
|
||||
disconnect( m_query->track().data(), SIGNAL( updated() ), this, SLOT( onCoverUpdated() ) );
|
||||
disconnect( m_query->track().data(), SIGNAL( socialActionsLoaded() ), this, SLOT( onSocialActionsLoaded() ) );
|
||||
disconnect( m_query.data(), SIGNAL( resultsChanged() ), this, SLOT( onResultsChanged() ) );
|
||||
@@ -164,6 +185,7 @@ TrackDetailView::setQuery( const Tomahawk::query_ptr& query )
|
||||
onResultsChanged();
|
||||
setSocialActions();
|
||||
onCoverUpdated();
|
||||
onAlbumUpdated();
|
||||
|
||||
if ( !query )
|
||||
{
|
||||
@@ -174,20 +196,128 @@ TrackDetailView::setQuery( const Tomahawk::query_ptr& query )
|
||||
|
||||
m_dateLabel->setText( tr( "Unknown Release-Date" ) );
|
||||
|
||||
connect( m_query->track().data(), SIGNAL( updated() ), SLOT( onCoverUpdated() ) );
|
||||
connect( m_query->track().data(), SIGNAL( socialActionsLoaded() ), SLOT( onSocialActionsLoaded() ) );
|
||||
connect( m_query.data(), SIGNAL( resultsChanged() ), SLOT( onResultsChanged() ) );
|
||||
connect( m_query.data(), SIGNAL( resultsChanged() ), SLOT( onAlbumUpdated() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrackDetailView::onAlbumUpdated()
|
||||
{
|
||||
if ( !m_query )
|
||||
return;
|
||||
|
||||
if ( m_query->track()->albumPtr() && !m_query->track()->albumPtr()->name().isEmpty() )
|
||||
{
|
||||
m_nameLabel->setType( QueryLabel::Album );
|
||||
m_nameLabel->setAlbum( m_query->track()->albumPtr() );
|
||||
|
||||
connect( m_query->track()->albumPtr().data(), SIGNAL( updated() ), SLOT( onAlbumUpdated() ), Qt::UniqueConnection );
|
||||
|
||||
if ( m_buyButtonVisible )
|
||||
{
|
||||
if ( m_query->track()->albumPtr()->purchased() )
|
||||
{
|
||||
m_allTracksAvailableLocally = true;
|
||||
foreach( const query_ptr& currentQuery, m_playlistInterface->tracks() )
|
||||
{
|
||||
if ( currentQuery->results().isEmpty() )
|
||||
{
|
||||
m_allTracksAvailableLocally = false;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_allTracksAvailableLocally = false;
|
||||
foreach ( const result_ptr& currentResult, currentQuery->results() )
|
||||
{
|
||||
QList< DownloadFormat > formats = currentResult->downloadFormats();
|
||||
bool isDownloaded = formats.isEmpty() ? false : !DownloadManager::instance()->localFileForDownload( currentResult->downloadFormats().first().url.toString() ).isEmpty();
|
||||
if ( currentResult->isLocal() || isDownloaded )
|
||||
{
|
||||
m_allTracksAvailableLocally = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !m_allTracksAvailableLocally )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_allTracksAvailableLocally )
|
||||
{
|
||||
m_buyButton->setText( tr( "View in Folder" ) );
|
||||
m_buyButton->setVisible( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_buyButton->setText( tr( "Download Album" ) );
|
||||
m_buyButton->setVisible( true );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_buyButton->setText( tr( "Buy Album" ) );
|
||||
m_buyButton->setVisible( !m_query->track()->albumPtr()->purchaseUrl().isEmpty() );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_nameLabel->setType( QueryLabel::Artist );
|
||||
m_nameLabel->setArtist( m_query->track()->artistPtr() );
|
||||
m_buyButton->setVisible( false );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrackDetailView::onBuyButtonClicked()
|
||||
{
|
||||
if ( DownloadManager::instance()->state() == DownloadManager::Running )
|
||||
{
|
||||
emit downloadCancel();
|
||||
return;
|
||||
}
|
||||
|
||||
connect( m_query->track().data(), SIGNAL( updated() ), SLOT( onCoverUpdated() ) );
|
||||
connect( m_query->track().data(), SIGNAL( socialActionsLoaded() ), SLOT( onSocialActionsLoaded() ) );
|
||||
connect( m_query.data(), SIGNAL( resultsChanged() ), SLOT( onResultsChanged() ) );
|
||||
if ( m_query && m_query->track()->albumPtr() )
|
||||
{
|
||||
if ( m_query->track()->albumPtr()->purchased() )
|
||||
{
|
||||
if ( m_allTracksAvailableLocally )
|
||||
{
|
||||
QDesktopServices::openUrl( QUrl::fromLocalFile( DownloadJob::localPath( m_query->track()->albumPtr() ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
emit downloadAll();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WebPopup* popup = new WebPopup( m_query->track()->albumPtr()->purchaseUrl(), QSize( 400, 800 ) );
|
||||
connect( m_query->track()->albumPtr().data(), SIGNAL( destroyed() ), popup, SLOT( close() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrackDetailView::onDownloadManagerStateChanged( DownloadManager::DownloadManagerState newState, DownloadManager::DownloadManagerState oldState )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
if ( newState == DownloadManager::Running )
|
||||
{
|
||||
m_buyButton->setText( tr( "Cancel Download" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
onAlbumUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -304,3 +434,10 @@ TrackDetailView::onResultsChanged()
|
||||
m_resultsScrollArea->hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrackDetailView::setBuyButtonVisible( bool visible )
|
||||
{
|
||||
m_buyButtonVisible = visible;
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "Query.h"
|
||||
#include "utils/DpiScaler.h"
|
||||
#include "DownloadManager.h"
|
||||
#include "DllMacro.h"
|
||||
|
||||
class QLabel;
|
||||
@@ -30,6 +31,7 @@ class CaptionLabel;
|
||||
class PlayableCover;
|
||||
class QueryLabel;
|
||||
class QScrollArea;
|
||||
class QPushButton;
|
||||
|
||||
class DLLEXPORT TrackDetailView : public QWidget, private TomahawkUtils::DpiScaler
|
||||
{
|
||||
@@ -39,21 +41,29 @@ public:
|
||||
explicit TrackDetailView( QWidget* parent = 0 );
|
||||
~TrackDetailView();
|
||||
|
||||
void setBuyButtonVisible( bool visible );
|
||||
|
||||
public slots:
|
||||
virtual void setQuery( const Tomahawk::query_ptr& query );
|
||||
void setPlaylistInterface( const Tomahawk::playlistinterface_ptr& playlistInterface );
|
||||
|
||||
signals:
|
||||
void downloadAll();
|
||||
void downloadCancel();
|
||||
|
||||
protected:
|
||||
|
||||
protected slots:
|
||||
|
||||
private slots:
|
||||
void onAlbumUpdated();
|
||||
void onCoverUpdated();
|
||||
void onSocialActionsLoaded();
|
||||
void onResultsChanged();
|
||||
|
||||
void onBuyButtonClicked();
|
||||
void onDownloadManagerStateChanged( DownloadManager::DownloadManagerState newState, DownloadManager::DownloadManagerState oldState );
|
||||
|
||||
private:
|
||||
void setSocialActions();
|
||||
|
||||
@@ -65,6 +75,9 @@ private:
|
||||
QLabel* m_lovedIcon;
|
||||
QLabel* m_lovedLabel;
|
||||
CaptionLabel* m_resultsBoxLabel;
|
||||
QPushButton* m_buyButton;
|
||||
bool m_buyButtonVisible;
|
||||
bool m_allTracksAvailableLocally;
|
||||
|
||||
QWidget* m_infoBox;
|
||||
QWidget* m_resultsBox;
|
||||
|
@@ -23,7 +23,9 @@
|
||||
#include "PlayableModel.h"
|
||||
#include "PlayableProxyModel.h"
|
||||
#include "PlayableItem.h"
|
||||
#include "DownloadManager.h"
|
||||
#include "DropJob.h"
|
||||
#include "Result.h"
|
||||
#include "Source.h"
|
||||
#include "TomahawkSettings.h"
|
||||
#include "audio/AudioEngine.h"
|
||||
@@ -45,6 +47,9 @@
|
||||
#include <QScrollBar>
|
||||
#include <QDrag>
|
||||
|
||||
// HACK
|
||||
#include <QTableView>
|
||||
|
||||
#define SCROLL_TIMEOUT 280
|
||||
|
||||
using namespace Tomahawk;
|
||||
@@ -83,6 +88,13 @@ TrackView::TrackView( QWidget* parent )
|
||||
setEditTriggers( NoEditTriggers );
|
||||
|
||||
setHeader( m_header );
|
||||
|
||||
// HACK: enable moving of first column: QTBUG-33974 / https://github.com/qtproject/qtbase/commit/e0fc088c0c8bc61dbcaf5928b24986cd61a22777
|
||||
QTableView unused;
|
||||
unused.setVerticalHeader( header() );
|
||||
header()->setParent( this );
|
||||
unused.setVerticalHeader( new QHeaderView( Qt::Horizontal, &unused ) );
|
||||
|
||||
setSortingEnabled( true );
|
||||
sortByColumn( -1 );
|
||||
setContextMenuPolicy( Qt::CustomContextMenu );
|
||||
@@ -677,7 +689,6 @@ TrackView::wheelEvent( QWheelEvent* event )
|
||||
QTreeView::wheelEvent( event );
|
||||
|
||||
m_delegate->resetHoverIndex();
|
||||
repaint();
|
||||
}
|
||||
|
||||
|
||||
@@ -764,6 +775,44 @@ TrackView::onCustomContextMenu( const QPoint& pos )
|
||||
m_contextMenu->setSupportedActions( m_contextMenu->supportedActions() | ContextMenu::ActionMarkListened
|
||||
| ContextMenu::ActionDelete );
|
||||
|
||||
if ( proxyModel()->style() != PlayableProxyModel::Collection )
|
||||
{
|
||||
bool allDownloaded = true;
|
||||
bool noneDownloadable = true;
|
||||
bool downloadable = false;
|
||||
foreach ( const QModelIndex& index, selectedIndexes() )
|
||||
{
|
||||
if ( index.column() )
|
||||
continue;
|
||||
|
||||
PlayableItem* item = proxyModel()->itemFromIndex( proxyModel()->mapToSource( index ) );
|
||||
|
||||
if( item->query()->results().isEmpty() )
|
||||
continue;
|
||||
|
||||
downloadable = !item->query()->results().first()->downloadFormats().isEmpty();
|
||||
if ( downloadable )
|
||||
{
|
||||
noneDownloadable = false;
|
||||
}
|
||||
|
||||
if ( downloadable && DownloadManager::instance()->localFileForDownload( item->query()->results().first()->downloadFormats().first().url.toString() ).isEmpty() )
|
||||
{
|
||||
allDownloaded = false;
|
||||
}
|
||||
|
||||
if ( !allDownloaded || !noneDownloadable )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !allDownloaded || !noneDownloadable )
|
||||
{
|
||||
m_contextMenu->setSupportedActions( m_contextMenu->supportedActions() | ContextMenu::ActionDownload );
|
||||
}
|
||||
}
|
||||
|
||||
QList<query_ptr> queries;
|
||||
foreach ( const QModelIndex& index, selectedIndexes() )
|
||||
{
|
||||
@@ -795,6 +844,10 @@ TrackView::onMenuTriggered( int action )
|
||||
deleteSelectedItems();
|
||||
break;
|
||||
|
||||
case ContextMenu::ActionDownload:
|
||||
downloadSelectedItems();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -870,6 +923,30 @@ TrackView::deleteSelectedItems()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrackView::downloadSelectedItems()
|
||||
{
|
||||
foreach ( const QModelIndex& index, selectedIndexes() )
|
||||
{
|
||||
if ( index.column() )
|
||||
continue;
|
||||
|
||||
PlayableItem* item = proxyModel()->itemFromIndex( proxyModel()->mapToSource( index ) );
|
||||
|
||||
if ( !item )
|
||||
continue;
|
||||
|
||||
if ( item->query()->results().isEmpty() || item->query()->results().first()->downloadFormats().isEmpty() )
|
||||
continue;
|
||||
|
||||
if ( !DownloadManager::instance()->localFileForDownload( item->query()->results().first()->downloadFormats().first().url.toString() ).isEmpty() )
|
||||
continue;
|
||||
|
||||
DownloadManager::instance()->addJob( item->result()->toDownloadJob( item->result()->downloadFormats().first() ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrackView::verifySize()
|
||||
{
|
||||
|
@@ -89,6 +89,7 @@ public:
|
||||
public slots:
|
||||
virtual void onItemActivated( const QModelIndex& index );
|
||||
|
||||
virtual void downloadSelectedItems();
|
||||
virtual void deleteSelectedItems();
|
||||
|
||||
void playItem();
|
||||
|
@@ -247,8 +247,8 @@ TreeProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent
|
||||
if ( !item->result()->isOnline() && ti->result()->isOnline() )
|
||||
return false;
|
||||
|
||||
if ( ( item->result()->resolvedByCollection().isNull() || !item->result()->resolvedByCollection()->isLocal() ) &&
|
||||
!ti->result()->resolvedByCollection().isNull() && ti->result()->resolvedByCollection()->isLocal() )
|
||||
if ( ( !item->result()->isLocal() ) &&
|
||||
!ti->result()->isLocal() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@@ -156,6 +156,7 @@ XspfUpdater::setAutoUpdate( bool autoUpdate )
|
||||
emit changed();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XspfUpdater::setInterval( int intervalMsecs )
|
||||
{
|
||||
|
@@ -67,6 +67,14 @@ JSAccount::scriptPluginFactory( const QString& type, const scriptobject_ptr& obj
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSAccount::showDebugger()
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << name() << "Show debugger";
|
||||
m_engine->showWebInspector();
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
JSAccount::serializeQVariantMap( const QVariantMap& map )
|
||||
{
|
||||
|
@@ -69,6 +69,8 @@ public:
|
||||
void setResolver( JSResolver* resolver );
|
||||
void scriptPluginFactory( const QString& type, const scriptobject_ptr& object ) override;
|
||||
|
||||
void showDebugger() override;
|
||||
|
||||
static QString serializeQVariantMap(const QVariantMap& map);
|
||||
|
||||
void reportNativeScriptJobResult( int resultId, const QVariantMap& result ) override;
|
||||
|
@@ -541,7 +541,6 @@ void
|
||||
JSResolver::resolve( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
ScriptJob* job = scriptAccount()->resolve( scriptObject(), query, "resolver" );
|
||||
|
||||
connect( job, SIGNAL( done( QVariantMap ) ), SLOT( onResolveRequestDone( QVariantMap ) ) );
|
||||
|
||||
job->start();
|
||||
@@ -563,15 +562,24 @@ JSResolver::onResolveRequestDone( const QVariantMap& data )
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !data.value( "artists" ).isNull() )
|
||||
{
|
||||
QList< artist_ptr > artists = scriptAccount()->parseArtistVariantList( data.value( "artists" ).toList() );
|
||||
Tomahawk::Pipeline::instance()->reportArtists( qid, artists );
|
||||
}
|
||||
|
||||
if ( !data.value( "albums" ).isNull() )
|
||||
{
|
||||
QList< album_ptr > albums = scriptAccount()->parseAlbumVariantList( data.value( "albums" ).toList() );
|
||||
Tomahawk::Pipeline::instance()->reportAlbums( qid, albums );
|
||||
}
|
||||
|
||||
QList< Tomahawk::result_ptr > results = scriptAccount()->parseResultVariantList( data.value( "tracks" ).toList() );
|
||||
|
||||
foreach( const result_ptr& result, results )
|
||||
{
|
||||
result->setResolvedByResolver( this );
|
||||
result->setFriendlySource( name() );
|
||||
}
|
||||
|
||||
Tomahawk::Pipeline::instance()->reportResults( qid, this, results );
|
||||
}
|
||||
|
||||
|
@@ -1,12 +1,12 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
|
||||
* Copyright (C) 2014 Dominik Schmidt <domme@tomahawk-player.org>
|
||||
* Copyright (C) 2015, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
|
||||
* Copyright 2014, Dominik Schmidt <domme@tomahawk-player.org>
|
||||
* Copyright 2015-2016, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* 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,
|
||||
@@ -17,6 +17,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ScriptAccount.h"
|
||||
|
||||
#include "ScriptObject.h"
|
||||
@@ -31,9 +32,11 @@
|
||||
#include "ScriptLinkGeneratorPlugin.h"
|
||||
#include "ScriptInfoPlugin.h"
|
||||
|
||||
// TODO:
|
||||
#include "../Artist.h"
|
||||
#include "../Album.h"
|
||||
#include "../Result.h"
|
||||
#include "../Track.h"
|
||||
|
||||
#include <QTime>
|
||||
|
||||
|
||||
@@ -153,11 +156,17 @@ ScriptAccount::reportScriptJobResult( const QVariantMap& result )
|
||||
Q_ASSERT( job );
|
||||
|
||||
// got a successful job result
|
||||
if ( result[ "error"].isNull() )
|
||||
if ( result[ "error" ].isNull() )
|
||||
{
|
||||
const QVariantMap data = result[ "data" ].toMap();
|
||||
|
||||
job->reportResults( data );
|
||||
if ( result[ "data" ].type() == QVariant::Map )
|
||||
{
|
||||
const QVariantMap data = result[ "data" ].toMap();
|
||||
job->reportResultsMap( data );
|
||||
}
|
||||
else
|
||||
{
|
||||
job->reportResults( result[ "data" ] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -201,6 +210,10 @@ ScriptAccount::unregisterScriptPlugin( const QString& type, const QString& objec
|
||||
{
|
||||
m_infoPluginFactory->unregisterPlugin( object );
|
||||
}
|
||||
else if( type == "linkParser" )
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
else
|
||||
{
|
||||
tLog() << "This plugin type is not handled by Tomahawk or simply cannot be removed yet";
|
||||
@@ -231,6 +244,10 @@ ScriptAccount::scriptPluginFactory( const QString& type, const scriptobject_ptr&
|
||||
ScriptLinkGeneratorPlugin* lgp = new ScriptLinkGeneratorPlugin( object );
|
||||
Utils::LinkGenerator::instance()->addPlugin( lgp );
|
||||
}
|
||||
else if( type == "linkParser" )
|
||||
{
|
||||
tLog() << "Plugin registered linkParser, which is not implemented yet. UrlLookup won't work";
|
||||
}
|
||||
else if ( type == "infoPlugin" )
|
||||
{
|
||||
m_infoPluginFactory->registerPlugin( object, this );
|
||||
@@ -247,6 +264,12 @@ ScriptAccount::scriptPluginFactory( const QString& type, const scriptobject_ptr&
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptAccount::showDebugger()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptAccount::onJobDeleted( const QString& jobId )
|
||||
{
|
||||
@@ -254,15 +277,67 @@ ScriptAccount::onJobDeleted( const QString& jobId )
|
||||
}
|
||||
|
||||
|
||||
QList< Tomahawk::artist_ptr >
|
||||
ScriptAccount::parseArtistVariantList( const QVariantList& artistList )
|
||||
{
|
||||
QList< Tomahawk::artist_ptr > artists;
|
||||
|
||||
QString artist;
|
||||
foreach( const QVariant& a, artistList )
|
||||
{
|
||||
artist = a.toString().trimmed();
|
||||
if ( artist.isEmpty() )
|
||||
continue;
|
||||
|
||||
artists << Tomahawk::Artist::get( artist );
|
||||
}
|
||||
|
||||
return artists;
|
||||
}
|
||||
|
||||
|
||||
QList< Tomahawk::album_ptr >
|
||||
ScriptAccount::parseAlbumVariantList( const QVariantList& albumList )
|
||||
{
|
||||
QList< Tomahawk::album_ptr > albums;
|
||||
|
||||
QString artistString;
|
||||
QString albumString;
|
||||
foreach( const QVariant& av, albumList )
|
||||
{
|
||||
QVariantMap m = av.toMap();
|
||||
|
||||
artistString = m.value( "artist" ).toString().trimmed();
|
||||
albumString = m.value( "album" ).toString().trimmed();
|
||||
if ( artistString.isEmpty() || albumString.isEmpty() )
|
||||
continue;
|
||||
|
||||
albums << Tomahawk::Album::get( Tomahawk::Artist::get( artistString ), albumString );
|
||||
}
|
||||
|
||||
return albums;
|
||||
}
|
||||
|
||||
|
||||
QList< Tomahawk::result_ptr >
|
||||
ScriptAccount::parseResultVariantList( const QVariantList& reslist )
|
||||
{
|
||||
QList< Tomahawk::result_ptr > results;
|
||||
|
||||
|
||||
foreach( const QVariant& rv, reslist )
|
||||
{
|
||||
QVariantMap m = rv.toMap();
|
||||
|
||||
const QString artistString = m.value("artist").toString().trimmed();
|
||||
const QString trackString = m.value("track").toString().trimmed();
|
||||
|
||||
if ( artistString.isEmpty() || trackString.isEmpty() )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "Could not parse Track" << m;
|
||||
continue;
|
||||
}
|
||||
|
||||
int duration = m.value( "duration", 0 ).toInt();
|
||||
if ( duration <= 0 && m.contains( "durationString" ) )
|
||||
{
|
||||
@@ -270,8 +345,8 @@ ScriptAccount::parseResultVariantList( const QVariantList& reslist )
|
||||
duration = time.secsTo( QTime( 0, 0 ) ) * -1;
|
||||
}
|
||||
|
||||
Tomahawk::track_ptr track = Tomahawk::Track::get( m.value( "artist" ).toString(),
|
||||
m.value( "track" ).toString(),
|
||||
Tomahawk::track_ptr track = Tomahawk::Track::get( artistString,
|
||||
trackString,
|
||||
m.value( "album" ).toString(),
|
||||
m.value( "albumArtist" ).toString(),
|
||||
duration,
|
||||
@@ -302,11 +377,17 @@ ScriptAccount::parseResultVariantList( const QVariantList& reslist )
|
||||
// rp->track()->setAttributes( attr );
|
||||
}
|
||||
|
||||
rp->setMimetype( m.value( "mimetype" ).toString() );
|
||||
if ( rp->mimetype().isEmpty() )
|
||||
|
||||
QString mimetype = m.value( "mimetype" ).toString();
|
||||
if ( mimetype.isEmpty() )
|
||||
{
|
||||
rp->setMimetype( TomahawkUtils::extensionToMimetype( m.value( "extension" ).toString() ) );
|
||||
Q_ASSERT( !rp->mimetype().isEmpty() );
|
||||
mimetype = TomahawkUtils::extensionToMimetype( m.value( "extension" ).toString() );
|
||||
}
|
||||
Q_ASSERT( !mimetype.isEmpty() );
|
||||
|
||||
if ( !mimetype.isEmpty() )
|
||||
{
|
||||
rp->setMimetype( mimetype );
|
||||
}
|
||||
|
||||
rp->setFriendlySource( name() );
|
||||
|
@@ -1,12 +1,12 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
|
||||
* Copyright (C) 2014 Dominik Schmidt <domme@tomahawk-player.org>
|
||||
* Copyright (C) 2015, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
|
||||
* Copyright 2014, Dominik Schmidt <domme@tomahawk-player.org>
|
||||
* Copyright 2015-2016, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* 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,
|
||||
@@ -76,7 +76,11 @@ public:
|
||||
|
||||
virtual void scriptPluginFactory( const QString& type, const scriptobject_ptr& object );
|
||||
|
||||
virtual void showDebugger();
|
||||
|
||||
// helpers
|
||||
QList< Tomahawk::artist_ptr > parseArtistVariantList( const QVariantList& artistList );
|
||||
QList< Tomahawk::album_ptr > parseAlbumVariantList( const QVariantList& albumList );
|
||||
QList< Tomahawk::result_ptr > parseResultVariantList( const QVariantList& reslist );
|
||||
ScriptJob* resolve( const scriptobject_ptr& scriptObject, const query_ptr& query, const QString& resolveType );
|
||||
|
||||
|
@@ -28,6 +28,8 @@
|
||||
#include "utils/Logger.h"
|
||||
#include "../Result.h"
|
||||
|
||||
#include <QtConcurrentRun>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
ScriptCommand_AllTracks::ScriptCommand_AllTracks( const Tomahawk::collection_ptr& collection,
|
||||
@@ -117,20 +119,22 @@ ScriptCommand_AllTracks::onTracksJobDone( const QVariantMap& result )
|
||||
QSharedPointer< ScriptCollection > collection = m_collection.objectCast< ScriptCollection >();
|
||||
Q_ASSERT( !collection.isNull() );
|
||||
|
||||
QList< Tomahawk::result_ptr > t = collection->scriptAccount()->parseResultVariantList( result[ "tracks" ].toList() );
|
||||
|
||||
|
||||
QList< Tomahawk::query_ptr > queries;
|
||||
foreach ( const Tomahawk::result_ptr& result, t )
|
||||
QtConcurrent::run( [] ( ScriptCommand_AllTracks* t, ScriptJob* job, const QVariantMap& result, const QSharedPointer< ScriptCollection >& collection )
|
||||
{
|
||||
result->setResolvedByCollection( m_collection );
|
||||
queries.append( result->toQuery() );
|
||||
}
|
||||
QList< Tomahawk::result_ptr > results = collection->scriptAccount()->parseResultVariantList( result[ "tracks" ].toList() );
|
||||
|
||||
tDebug() << Q_FUNC_INFO << "about to push" << queries.count() << "tracks";
|
||||
QList< Tomahawk::query_ptr > queries;
|
||||
foreach ( const Tomahawk::result_ptr& result, results )
|
||||
{
|
||||
result->setResolvedByCollection( collection );
|
||||
queries.append( result->toQuery() );
|
||||
}
|
||||
|
||||
emit tracks( queries );
|
||||
emit done();
|
||||
tDebug() << Q_FUNC_INFO << "about to push" << queries.count() << "tracks";
|
||||
|
||||
job->deleteLater();
|
||||
emit t->tracks( queries );
|
||||
emit t->done();
|
||||
|
||||
job->deleteLater();
|
||||
}, this, job, result, collection );
|
||||
}
|
||||
|
@@ -21,7 +21,7 @@
|
||||
|
||||
#include "ScriptEngine.h"
|
||||
|
||||
#include "jobview/ErrorStatusMessage.h"
|
||||
#include "jobview/ScriptErrorStatusMessage.h"
|
||||
#include "jobview/JobStatusModel.h"
|
||||
#include "jobview/JobStatusView.h"
|
||||
#include "utils/Logger.h"
|
||||
@@ -51,13 +51,13 @@ ScriptEngine::ScriptEngine( JSAccount* parent )
|
||||
settings()->setAttribute( QWebSettings::LocalContentCanAccessRemoteUrls, true );
|
||||
settings()->setOfflineStorageDefaultQuota(100 * 1024 * 1024 /* 100 Mb */);
|
||||
settings()->setOfflineWebApplicationCacheQuota(100 * 1024 * 1024 /* 100 Mb */);
|
||||
settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled, true );
|
||||
|
||||
// HACK
|
||||
QStringList cmdArgs = QCoreApplication::instance()->arguments();
|
||||
int position = cmdArgs.indexOf( "--show-inspector" ) + 1;
|
||||
if ( position > 0 && !cmdArgs.at( position ).isEmpty() && parent->name().contains( cmdArgs.at( position ), Qt::CaseInsensitive ) ) {
|
||||
settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled, true );
|
||||
QMetaObject::invokeMethod( this, "initWebInspector", Qt::QueuedConnection );
|
||||
QMetaObject::invokeMethod( this, "showWebInspector", Qt::QueuedConnection );
|
||||
}
|
||||
|
||||
// Tomahawk is not a user agent
|
||||
@@ -74,24 +74,13 @@ ScriptEngine::ScriptEngine( JSAccount* parent )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptEngine::initWebInspector()
|
||||
{
|
||||
m_webInspector.reset( new QWebInspector() );
|
||||
m_webInspector->setPage( this );
|
||||
m_webInspector->setMinimumWidth( 800 );
|
||||
m_webInspector->setMinimumHeight( 600 );
|
||||
m_webInspector->show();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptEngine::javaScriptConsoleMessage( const QString& message, int lineNumber, const QString& sourceID )
|
||||
{
|
||||
tLog() << "JAVASCRIPT:" << QString( "%1:%2" ).arg( m_scriptPath ).arg( lineNumber ) << message << sourceID;
|
||||
#ifdef QT_DEBUG
|
||||
QFileInfo scriptPath( m_scriptPath );
|
||||
JobStatusView::instance()->model()->addJob( new ErrorStatusMessage( tr( "Resolver Error: %1:%2 %3" ).arg( scriptPath.fileName() ).arg( lineNumber ).arg( message ) ) );
|
||||
JobStatusView::instance()->model()->addJob( new ScriptErrorStatusMessage( tr( "%1:%2 %3" ).arg( scriptPath.fileName() ).arg( lineNumber ).arg( message ), m_parent ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -110,7 +99,7 @@ ScriptEngine::sslErrorHandler( QNetworkReply* qnr, const QList<QSslError>& errli
|
||||
|
||||
QMessageBox question( TomahawkUtils::tomahawkWindow() );
|
||||
question.setWindowTitle( tr( "SSL Error" ) );
|
||||
question.setText( tr( "You have asked Tomahawk to connect securely to <b>%1</b>, but we can't confirm that your connection is secure:<br><br>"
|
||||
question.setText( tr( "You have asked %applicationName to connect securely to <b>%1</b>, but we can't confirm that your connection is secure:<br><br>"
|
||||
"<b>%2</b><br><br>"
|
||||
"Do you want to trust this connection?" )
|
||||
.arg( qnr->url().host() )
|
||||
@@ -148,6 +137,21 @@ ScriptEngine::setScriptPath( const QString& scriptPath )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptEngine::showWebInspector()
|
||||
{
|
||||
if ( m_webInspector.isNull() )
|
||||
{
|
||||
m_webInspector.reset( new QWebInspector() );
|
||||
m_webInspector->setPage( this );
|
||||
m_webInspector->setMinimumWidth( 800 );
|
||||
m_webInspector->setMinimumHeight( 600 );
|
||||
}
|
||||
|
||||
m_webInspector->show();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ScriptEngine::shouldInterruptJavaScript()
|
||||
{
|
||||
|
@@ -49,13 +49,13 @@ public:
|
||||
|
||||
public slots:
|
||||
bool shouldInterruptJavaScript();
|
||||
void showWebInspector();
|
||||
|
||||
protected:
|
||||
virtual void javaScriptConsoleMessage( const QString& message, int lineNumber, const QString& sourceID );
|
||||
|
||||
private slots:
|
||||
void sslErrorHandler( QNetworkReply* qnr, const QList<QSslError>& errlist );
|
||||
void initWebInspector();
|
||||
|
||||
private:
|
||||
JSAccount* m_parent;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user