1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-16 19:14:06 +02:00

Merge branch 'master' into gfw

Conflicts:
	src/libtomahawk/CMakeLists.txt
This commit is contained in:
Jeff Mitchell
2011-07-07 11:58:17 -04:00
153 changed files with 4647 additions and 1052 deletions

3
.gitignore vendored
View File

@@ -12,3 +12,6 @@ moc_*
thirdparty/qtweetlib/WARNING-twitter-api-keys
.kdev4
tomahawk.kdev4
clang/
win/
gcc/

View File

@@ -1,5 +1,6 @@
PROJECT( tomahawk )
CMAKE_MINIMUM_REQUIRED( VERSION 2.8 )
SET( CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_SOURCE_DIR}/CMakeModules" )
IF( ${CMAKE_VERSION} VERSION_GREATER 2.8.3 )
CMAKE_POLICY(SET CMP0017 NEW)
@@ -11,15 +12,43 @@ ENDIF( ${CMAKE_VERSION} VERSION_GREATER 2.8.3 )
SET( TOMAHAWK_ORGANIZATION_NAME "Tomahawk" )
SET( TOMAHAWK_ORGANIZATION_DOMAIN "tomahawk-player.org" )
SET( TOMAHAWK_APPLICATION_NAME "Tomahawk" )
SET( TOMAHAWK_VERSION "0.1.0" )
SET( TOMAHAWK_DESCRIPTION_SUMMARY "The social media player" )
SET( TOMAHAWK_VERSION_MAJOR 0 )
SET( TOMAHAWK_VERSION_MINOR 1 )
SET( TOMAHAWK_VERSION_PATCH 0 )
# SET( TOMAHAWK_VERSION_RC 0 )
IF( NOT CMAKE_BUILD_TYPE STREQUAL "Release" )
# Use the date as the tweak level.
INCLUDE( ${CMAKE_MODULE_PATH}/kwsysDateStamp.cmake )
SET( TOMAHAWK_VERSION_TWEAK "${KWSYS_DATE_STAMP_YEAR}${KWSYS_DATE_STAMP_MONTH}${KWSYS_DATE_STAMP_DAY}" )
INCLUDE( ${CMAKE_MODULE_PATH}/CMakeVersionSource.cmake )
ENDIF()
SET( TOMAHAWK_VERSION ${TOMAHAWK_VERSION_MAJOR}.${TOMAHAWK_VERSION_MINOR}.${TOMAHAWK_VERSION_PATCH} )
IF( ${TOMAHAWK_VERSION_TWEAK} GREATER 0)
SET( TOMAHAWK_VERSION ${TOMAHAWK_VERSION}.${TOMAHAWK_VERSION_TWEAK} )
ENDIF()
IF( TOMAHAWK_VERSION_RC )
SET( CMake_VERSION ${TOMAHAWK_VERSION}-rc${TOMAHAWK_VERSION_RC} )
ENDIF()
IF( CMAKE_VERSION_SOURCE )
SET( TOMAHAWK_VERSION ${TOMAHAWK_VERSION}-${CMAKE_VERSION_SOURCE} )
ENDIF()
# set paths
SET( CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_SOURCE_DIR}/CMakeModules" )
SET( THIRDPARTY_DIR ${CMAKE_SOURCE_DIR}/thirdparty )
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}")
SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" )
SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" )
SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" )
# installer creation
INCLUDE( CPack.cmake )
# Check if we need qtgui:
IF( "${gui}" STREQUAL "no" )

View File

@@ -0,0 +1,37 @@
# Try to identify the current development source version.
set(CMAKE_VERSION_SOURCE "")
if(EXISTS ${CMAKE_SOURCE_DIR}/.git/HEAD)
find_program(GIT_EXECUTABLE NAMES git git.cmd)
mark_as_advanced(GIT_EXECUTABLE)
if(GIT_EXECUTABLE)
execute_process(
COMMAND ${GIT_EXECUTABLE} rev-parse --verify -q --short=4 HEAD
OUTPUT_VARIABLE head
OUTPUT_STRIP_TRAILING_WHITESPACE
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
if(head)
set(CMAKE_VERSION_SOURCE "g${head}")
execute_process(
COMMAND ${GIT_EXECUTABLE} update-index -q --refresh
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
execute_process(
COMMAND ${GIT_EXECUTABLE} diff-index --name-only HEAD --
OUTPUT_VARIABLE dirty
OUTPUT_STRIP_TRAILING_WHITESPACE
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
if(dirty)
set(CMAKE_VERSION_SOURCE "${CMAKE_VERSION_SOURCE}-dirty")
endif()
endif()
endif()
elseif(EXISTS ${CMAKE_SOURCE_DIR}/CVS/Repository)
file(READ ${CMAKE_SOURCE_DIR}/CVS/Repository repo)
set(branch "")
if("${repo}" MATCHES "\\.git/")
string(REGEX REPLACE ".*\\.git/([^\r\n]*).*" "-\\1" branch "${repo}")
endif()
set(CMAKE_VERSION_SOURCE "cvs${branch}")
endif()

View File

@@ -0,0 +1,24 @@
[Settings]
NumFields=3
[Field 1]
Type=Label
Left=0
Right=-1
Top=0
Bottom=24
[Field 2]
Type=RadioButton
Left=30
Right=-1
Top=50
Bottom=58
State=1
[Field 3]
Type=RadioButton
Left=30
Right=-1
Top=70
Bottom=78

View File

@@ -0,0 +1,665 @@
;Tomahawk installer script.
;-----------------------------------------------------------------------------
; Some installer script options (comment-out options not required)
;-----------------------------------------------------------------------------
;!define OPTION_LICENSE_AGREEMENT
!define OPTION_UAC_PLUGIN_ENHANCED
!define OPTION_SECTION_SC_START_MENU
!define OPTION_SECTION_SC_DESKTOP
!define OPTION_SECTION_SC_QUICK_LAUNCH
!define OPTION_FINISHPAGE
!define OPTION_FINISHPAGE_LAUNCHER
!define OPTION_FINISHPAGE_RELEASE_NOTES
;-----------------------------------------------------------------------------
; Some paths.
;-----------------------------------------------------------------------------
!ifndef MING_PATH
!define MING_PATH "/usr/i686-w64-mingw32/sys-root/mingw"
!endif
!define MING_BIN "${MING_PATH}/bin"
!define MING_LIB "${MING_PATH}/lib"
!define BUILD_PATH "@CMAKE_BINARY_DIR@"
!define QT_DLL_PATH "${MING_BIN}"
!define SQLITE_DLL_PATH "${MING_LIB}/qt4/plugins/sqldrivers"
!define IMAGEFORMATS_DLL_PATH "${MING_LIB}/qt4/plugins/imageformats"
!define VLC_PLUGIN_PATH "${MING_LIB}\vlc\plugins"
!define NSI_PATH "@CMAKE_SOURCE_DIR@/admin/win/nsi"
;-----------------------------------------------------------------------------
; Increment installer revision number as part of this script.
;-----------------------------------------------------------------------------
!define /file REVISION_LAST ${NSI_PATH}/revision.txt
!define /math REVISION ${REVISION_LAST} + 1
!delfile revision.txt
!appendfile revision.txt ${REVISION}
!define VER_MAJOR "@CPACK_PACKAGE_VERSION_MAJOR@"
!define VER_MINOR "@CPACK_PACKAGE_VERSION_MINOR@"
!define VER_BUILD "@CPACK_PACKAGE_VERSION_PATCH@"
!define VERSION "@CPACK_PACKAGE_VERSION@"
;-----------------------------------------------------------------------------
; Installer build timestamp.
;-----------------------------------------------------------------------------
!define /date BUILD_TIME "built on %Y/%m/%d at %I:%M %p (rev. ${REVISION})"
;-----------------------------------------------------------------------------
; Initial installer setup and definitions.
;-----------------------------------------------------------------------------
Name "@CPACK_NSIS_PACKAGE_NAME@"
Caption "Tomahawk Installer"
BrandingText "Tomahawk ${VERSION} -- ${BUILD_TIME}"
OutFile "@CPACK_TOPLEVEL_DIRECTORY@/@CPACK_OUTPUT_FILE_NAME@"
InstallDir "$PROGRAMFILES\@CPACK_PACKAGE_INSTALL_DIRECTORY@"
InstallDirRegKey HKCU "Software\Tomahawk" ""
InstType Standard
InstType Full
InstType Minimal
CRCCheck On
SetCompressor @CPACK_NSIS_COMPRESSOR@
RequestExecutionLevel user ;Now using the UAC plugin.
ReserveFile NSIS.InstallOptions.ini
ReserveFile "${NSISDIR}\Plugins\InstallOptions.dll"
@CPACK_NSIS_SECTION_SELECTED_VARS@
;-----------------------------------------------------------------------------
; Include some required header files.
;-----------------------------------------------------------------------------
!include LogicLib.nsh ;Used by APPDATA uninstaller.
!include nsDialogs.nsh ;Used by APPDATA uninstaller.
!include MUI2.nsh ;Used by APPDATA uninstaller.
!include InstallOptions.nsh ;Required by MUI2 to support old MUI_INSTALLOPTIONS.
!include Memento.nsh ;Remember user selections.
!include WinVer.nsh ;Windows version detection.
!include WordFunc.nsh ;Used by VersionCompare macro function.
!include UAC.nsh ;Used by the UAC elevation to install as user or admin.
;-----------------------------------------------------------------------------
; Memento selections stored in registry.
;-----------------------------------------------------------------------------
!define MEMENTO_REGISTRY_ROOT HKLM
!define MEMENTO_REGISTRY_KEY Software\Microsoft\Windows\CurrentVersion\Uninstall\Tomahawk
;-----------------------------------------------------------------------------
; Modern User Interface (MUI) defintions and setup.
;-----------------------------------------------------------------------------
!define MUI_ABORTWARNING
!define MUI_ICON ${NSI_PATH}\installer.ico
!define MUI_UNICON ${NSI_PATH}\installer.ico
!define MUI_WELCOMEFINISHPAGE_BITMAP ${NSI_PATH}\welcome.bmp
!define MUI_WELCOMEPAGE_TITLE "@CPACK_PACKAGE_NAME@ ${VERSION} Setup$\r$\nInstaller Build Revision ${REVISION}"
!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation.$\r$\n$\r$\n$_CLICK"
!define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_BITMAP ${NSI_PATH}\page_header.bmp
!define MUI_COMPONENTSPAGE_SMALLDESC
!define MUI_FINISHPAGE_TITLE "@CPACK_PACKAGE_NAME@ Install Completed"
!define MUI_FINISHPAGE_LINK "Click here to visit the @CPACK_PACKAGE_NAME@ website."
!define MUI_FINISHPAGE_LINK_LOCATION "http://@TOMAHAWK_ORGANIZATION_DOMAIN@"
!define MUI_FINISHPAGE_NOREBOOTSUPPORT
!ifdef OPTION_FINISHPAGE_RELEASE_NOTES
!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED
!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\NOTES.txt"
!define MUI_FINISHPAGE_SHOWREADME_TEXT "Show release notes"
!endif
!ifdef OPTION_FINISHPAGE_LAUNCHER
!define MUI_FINISHPAGE_NOAUTOCLOSE
!define MUI_FINISHPAGE_RUN
!define MUI_FINISHPAGE_RUN_FUNCTION "LaunchTomahawk"
!endif
;-----------------------------------------------------------------------------
; Page macros.
;-----------------------------------------------------------------------------
!insertmacro MUI_PAGE_WELCOME
!ifdef OPTION_LICENSE_AGREEMENT
!insertmacro MUI_PAGE_LICENSE "LICENSE.txt"
!endif
Page custom PageReinstall PageLeaveReinstall
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!ifdef OPTION_FINISHPAGE
!insertmacro MUI_PAGE_FINISH
!endif
!insertmacro MUI_UNPAGE_CONFIRM
UninstPage custom un.UnPageUserAppData un.UnPageUserAppDataLeave
!insertmacro MUI_UNPAGE_INSTFILES
;-----------------------------------------------------------------------------
; Other MUI macros.
;-----------------------------------------------------------------------------
!insertmacro MUI_LANGUAGE "English"
##############################################################################
# #
# FINISH PAGE LAUNCHER FUNCTIONS #
# #
##############################################################################
Function LaunchTomahawk
${UAC.CallFunctionAsUser} LaunchTomahawkAsUser
FunctionEnd
Function LaunchTomahawkAsUser
Exec "$INSTDIR\tomahawk.exe"
FunctionEnd
##############################################################################
# #
# PROCESS HANDLING FUNCTIONS AND MACROS #
# #
##############################################################################
!macro CheckForProcess processName gotoWhenFound gotoWhenNotFound
Processes::FindProcess ${processName}
StrCmp $R0 "0" ${gotoWhenNotFound} ${gotoWhenFound}
!macroend
!macro ConfirmEndProcess processName
MessageBox MB_YESNO|MB_ICONEXCLAMATION \
"Found ${processName} process(s) which need to be stopped.$\nDo you want the installer to stop these for you?" \
IDYES process_${processName}_kill IDNO process_${processName}_ended
process_${processName}_kill:
DetailPrint "Killing ${processName} processes."
Processes::KillProcess ${processName}
Sleep 1500
StrCmp $R0 "1" process_${processName}_ended
DetailPrint "Process to kill not found!"
process_${processName}_ended:
!macroend
!macro CheckAndConfirmEndProcess processName
!insertmacro CheckForProcess ${processName} 0 no_process_${processName}_to_end
!insertmacro ConfirmEndProcess ${processName}
no_process_${processName}_to_end:
!macroend
Function EnsureTomahawkShutdown
!insertmacro CheckAndConfirmEndProcess "tomahawk.exe"
FunctionEnd
##############################################################################
# #
# RE-INSTALLER FUNCTIONS #
# #
##############################################################################
Function PageReinstall
ReadRegStr $R0 HKLM "Software\Tomahawk" ""
StrCmp $R0 "" 0 +2
Abort
;Detect version
ReadRegDWORD $R0 HKLM "Software\Tomahawk" "VersionMajor"
IntCmp $R0 ${VER_MAJOR} minor_check new_version older_version
minor_check:
ReadRegDWORD $R0 HKLM "Software\Tomahawk" "VersionMinor"
IntCmp $R0 ${VER_MINOR} build_check new_version older_version
build_check:
ReadRegDWORD $R0 HKLM "Software\Tomahawk" "VersionBuild"
IntCmp $R0 ${VER_BUILD} revision_check new_version older_version
revision_check:
ReadRegDWORD $R0 HKLM "Software\Tomahawk" "VersionRevision"
IntCmp $R0 ${REVISION} same_version new_version older_version
new_version:
!insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 1" "Text" "An older version of Tomahawk is installed on your system. It is recommended that you uninstall the current version before installing. Select the operation you want to perform and click Next to continue."
!insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 2" "Text" "Uninstall before installing"
!insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 3" "Text" "Do not uninstall"
!insertmacro MUI_HEADER_TEXT "Already Installed" "Choose how you want to install Tomahawk."
StrCpy $R0 "1"
Goto reinst_start
older_version:
!insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 1" "Text" "A newer version of Tomahawk is already installed! It is not recommended that you install an older version. If you really want to install this older version, it is better to uninstall the current version first. Select the operation you want to perform and click Next to continue."
!insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 2" "Text" "Uninstall before installing"
!insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 3" "Text" "Do not uninstall"
!insertmacro MUI_HEADER_TEXT "Already Installed" "Choose how you want to install Tomahawk."
StrCpy $R0 "1"
Goto reinst_start
same_version:
!insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 1" "Text" "Tomahawk ${VERSION} is already installed.\r\nSelect the operation you want to perform and click Next to continue."
!insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 2" "Text" "Add/Reinstall components"
!insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 3" "Text" "Uninstall Tomahawk"
!insertmacro MUI_HEADER_TEXT "Already Installed" "Choose the maintenance option to perform."
StrCpy $R0 "2"
reinst_start:
!insertmacro INSTALLOPTIONS_DISPLAY "NSIS.InstallOptions.ini"
FunctionEnd
Function PageLeaveReinstall
!insertmacro INSTALLOPTIONS_READ $R1 "NSIS.InstallOptions.ini" "Field 2" "State"
StrCmp $R0 "1" 0 +2
StrCmp $R1 "1" reinst_uninstall reinst_done
StrCmp $R0 "2" 0 +3
StrCmp $R1 "1" reinst_done reinst_uninstall
reinst_uninstall:
ReadRegStr $R1 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tomahawk" "UninstallString"
HideWindow
ClearErrors
ExecWait '$R1 _?=$INSTDIR'
IfErrors no_remove_uninstaller
IfFileExists "$INSTDIR\tomahawk.exe" no_remove_uninstaller
Delete $R1
RMDir $INSTDIR
no_remove_uninstaller:
StrCmp $R0 "2" 0 +3
UAC::Unload
Quit
BringToFront
reinst_done:
FunctionEnd
##############################################################################
# #
# INSTALLER SECTIONS #
# #
##############################################################################
Section "Tomahawk Player" SEC_TOMAHAWK_PLAYER
SectionIn 1 2 3 RO
SetDetailsPrint listonly
SetDetailsPrint textonly
DetailPrint "Installing Tomahawk Player essentials."
SetDetailsPrint listonly
SetOutPath "$INSTDIR"
!ifdef INSTALL_PATH
;Main executable.
File "${INSTALL_PATH}\bin\tomahawk.exe"
File "${INSTALL_PATH}\bin\libqxtweb-standalone.dll"
File "${INSTALL_PATH}\bin\libtomahawk_portfwd.dll"
File "${INSTALL_PATH}\bin\libtomahawk_lastfm2.dll"
File "${INSTALL_PATH}\bin\libtomahawklib.dll"
File "${INSTALL_PATH}\lib\libtomahawk_sip*.dll"
!endif
!ifndef INSTALL_PATH
;Main executable.
File "${BUILD_PATH}\tomahawk.exe"
File "${BUILD_PATH}\libtomahawklib.dll"
File "${BUILD_PATH}\libqxtweb-standalone.dll"
File "${BUILD_PATH}\libtomahawk_portfwd.dll"
File "${BUILD_PATH}\libtomahawk_lastfm2.dll"
File "${BUILD_PATH}\libtomahawk_sip*.dll"
!endif
;License & release notes.
File "@CPACK_RESOURCE_FILE_LICENSE@"
File /oname=NOTES.txt ${NSI_PATH}\RELEASE_NOTES.txt
;QT stuff:
File "${QT_DLL_PATH}\QtCore4.dll"
File "${QT_DLL_PATH}\QtGui4.dll"
File "${QT_DLL_PATH}\QtNetwork4.dll"
File "${QT_DLL_PATH}\QtSql4.dll"
File "${QT_DLL_PATH}\QtXml4.dll"
File "${QT_DLL_PATH}\QtWebKit4.dll"
;SQLite driver
SetOutPath "$INSTDIR\sqldrivers"
File "${SQLITE_DLL_PATH}\qsqlite4.dll"
SetOutPath "$INSTDIR"
;Image plugins
SetOutPath "$INSTDIR\imageformats"
File "${IMAGEFORMATS_DLL_PATH}\qgif4.dll"
File "${IMAGEFORMATS_DLL_PATH}\qjpeg4.dll"
SetOutPath "$INSTDIR"
;Cygwin/c++ stuff
;File "${MING_BIN}\cygmad-0.dll"
;File "${MING_BIN}\libgcc_s_dw2-1.dll"
;File "${MING_BIN}\mingwm10.dll"
File "${MING_BIN}\libgcc_s_sjlj-1.dll"
File "${MING_BIN}\libstdc++-6.dll"
;Phonon stuff
;Fix the phonon build to not use Dbus
File "${QT_DLL_PATH}\QtDbus4.dll"
File "${MING_BIN}\libdbus-1-3.dll"
File "${MING_BIN}\dbus-daemon.exe"
File "${MING_BIN}\libphonon.dll"
SetOutPath "$INSTDIR\phonon_backend"
File "${MING_BIN}\phonon_backend\phonon_vlc.dll"
SetOutPath "$INSTDIR"
;VLC
;SetOutPath "$INSTDIR\phonon_backend"
File "${MING_BIN}\libvlc.dll"
File "${MING_BIN}\libvlccore.dll"
SetOutPath "$INSTDIR\plugins"
File /r "${VLC_PLUGIN_PATH}\*.dll"
SetOutPath "$INSTDIR"
File "${MING_BIN}\libmad-0.dll" ; MP3
File "${MING_BIN}\libFLAC-8.dll" ; FLAC
File "${MING_BIN}\libogg-0.dll" ; OGG, FLAC
File "${MING_BIN}\libvorbis-0.dll" ; OGG
File "${MING_BIN}\libvorbisenc-2.dll" ; OGG
; Other
File "${MING_BIN}\libqjson.dll"
File "${MING_BIN}\libtag.dll"
File "${MING_BIN}\libpng15-15.dll"
File "${MING_BIN}\libjpeg-8.dll"
File "${MING_BIN}\zlib1.dll"
File "${MING_BIN}\libechonest.dll"
File "${MING_BIN}\libQTweetLib.dll"
; Jabber
File "${MING_BIN}\libjreen.dll"
File "${MING_BIN}\libqca.dll"
SetOutPath "$INSTDIR\crypto"
File "${MING_LIB}\qt4\plugins\crypto\libqca-ossl.dll"
SetOutPath "$INSTDIR"
File "${MING_BIN}\libssl-8.dll"
File "${MING_BIN}\libcrypto-8.dll"
File "${MING_LIB}\libclucene-core.dll"
File "${MING_LIB}\libclucene-shared.dll"
File "${MING_BIN}\libqtsparkle.dll"
SectionEnd
SectionGroup "Shortcuts"
!ifdef OPTION_SECTION_SC_START_MENU
${MementoSection} "Start Menu Program Group" SEC_START_MENU
SectionIn 1 2
SetDetailsPrint textonly
DetailPrint "Adding shortcuts for the Tomahawk program group to the Start Menu."
SetDetailsPrint listonly
SetShellVarContext all
RMDir /r "$SMPROGRAMS\Tomahawk"
CreateDirectory "$SMPROGRAMS\Tomahawk"
CreateShortCut "$SMPROGRAMS\Tomahawk\LICENSE.lnk" "$INSTDIR\LICENSE.txt"
CreateShortCut "$SMPROGRAMS\Tomahawk\Tomahawk.lnk" "$INSTDIR\tomahawk.exe"
CreateShortCut "$SMPROGRAMS\Tomahawk\Release notes.lnk" "$INSTDIR\NOTES.txt"
CreateShortCut "$SMPROGRAMS\Tomahawk\Uninstall.lnk" "$INSTDIR\uninstall.exe"
SetShellVarContext current
${MementoSectionEnd}
!endif
!ifdef OPTION_SECTION_SC_DESKTOP
${MementoSection} "Desktop Shortcut" SEC_DESKTOP
SectionIn 1 2
SetDetailsPrint textonly
DetailPrint "Creating Desktop Shortcuts"
SetDetailsPrint listonly
CreateShortCut "$DESKTOP\Tomahawk.lnk" "$INSTDIR\tomahawk.exe"
${MementoSectionEnd}
!endif
!ifdef OPTION_SECTION_SC_QUICK_LAUNCH
${MementoSection} "Quick Launch Shortcut" SEC_QUICK_LAUNCH
SectionIn 1 2
SetDetailsPrint textonly
DetailPrint "Creating Quick Launch Shortcut"
SetDetailsPrint listonly
CreateShortCut "$QUICKLAUNCH\Tomahawk.lnk" "$INSTDIR\tomahawk.exe"
${MementoSectionEnd}
!endif
SectionGroupEnd
${MementoSectionDone}
; Installer section descriptions
;--------------------------------
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_TOMAHAWK_PLAYER} "Tomahawk player essentials."
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_START_MENU} "Tomahawk program group."
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_DESKTOP} "Desktop shortcut for Tomahawk."
!insertmacro MUI_DESCRIPTION_TEXT ${SEC_QUICK_LAUNCH} "Quick Launch shortcut for Tomahawk."
!insertmacro MUI_FUNCTION_DESCRIPTION_END
Section -post
;Uninstaller file.
SetDetailsPrint textonly
DetailPrint "Writing Uninstaller"
SetDetailsPrint listonly
WriteUninstaller $INSTDIR\uninstall.exe
;Registry keys required for installer version handling and uninstaller.
SetDetailsPrint textonly
DetailPrint "Writing Installer Registry Keys"
SetDetailsPrint listonly
;Version numbers used to detect existing installation version for comparisson.
WriteRegStr HKLM "Software\Tomahawk" "" $INSTDIR
WriteRegDWORD HKLM "Software\Tomahawk" "VersionMajor" "${VER_MAJOR}"
WriteRegDWORD HKLM "Software\Tomahawk" "VersionMinor" "${VER_MINOR}"
WriteRegDWORD HKLM "Software\Tomahawk" "VersionRevision" "${REVISION}"
WriteRegDWORD HKLM "Software\Tomahawk" "VersionBuild" "${VER_BUILD}"
;Add or Remove Programs entry.
WriteRegExpandStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tomahawk" "UninstallString" '"$INSTDIR\Uninstall.exe"'
WriteRegExpandStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tomahawk" "InstallLocation" "$INSTDIR"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tomahawk" "DisplayName" "Tomahawk"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tomahawk" "Publisher" "Tomahawk-player.org"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tomahawk" "DisplayIcon" "$INSTDIR\Uninstall.exe,0"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tomahawk" "DisplayVersion" "${VERSION}"
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tomahawk" "VersionMajor" "${VER_MAJOR}"
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tomahawk" "VersionMinor" "${VER_MINOR}.${REVISION}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tomahawk" "URLInfoAbout" "http://tomahawk-player.org/"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tomahawk" "HelpLink" "http://tomahawk-player.org/"
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tomahawk" "NoModify" "1"
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tomahawk" "NoRepair" "1"
; Register tomahawk:// protocol handler
WriteRegStr HKCR "tomahawk" "" "URL: Tomahawk Protocol"
WriteRegStr HKCR "tomahawk\DefaultIcon" "" $INSTDIR\tomahawk.exe,1
WriteRegStr HKCR "tomahawk\shell" "" "open"
WriteRegStr HKCR "tomahawk\shell\open\command" "" '"$INSTDIR\tomahawk.exe" "%1"'
SetDetailsPrint textonly
DetailPrint "Finsihed."
SectionEnd
##############################################################################
# #
# UNINSTALLER SECTION #
# #
##############################################################################
Var UnPageUserAppDataDialog
Var UnPageUserAppDataCheckbox
Var UnPageUserAppDataCheckbox_State
Var UnPageUserAppDataEditBox
Function un.UnPageUserAppData
!insertmacro MUI_HEADER_TEXT "Uninstall Tomahawk" "Remove Tomahawk's data folder from your computer."
nsDialogs::Create /NOUNLOAD 1018
Pop $UnPageUserAppDataDialog
${If} $UnPageUserAppDataDialog == error
Abort
${EndIf}
${NSD_CreateLabel} 0 0 100% 12u "Do you want to delete Tomahawk's data folder?"
Pop $0
${NSD_CreateText} 0 13u 100% 12u "$LOCALAPPDATA\Tomahawk"
Pop $UnPageUserAppDataEditBox
SendMessage $UnPageUserAppDataEditBox ${EM_SETREADONLY} 1 0
${NSD_CreateLabel} 0 46u 100% 24u "Leave unchecked to keep the data folder for later use or check to delete the data folder."
Pop $0
${NSD_CreateCheckbox} 0 71u 100% 8u "Yes, delete this data folder."
Pop $UnPageUserAppDataCheckbox
nsDialogs::Show
FunctionEnd
Function un.UnPageUserAppDataLeave
${NSD_GetState} $UnPageUserAppDataCheckbox $UnPageUserAppDataCheckbox_State
FunctionEnd
Section Uninstall
IfFileExists "$INSTDIR\tomahawk.exe" tomahawk_installed
MessageBox MB_YESNO "It does not appear that Tomahawk is installed in the directory '$INSTDIR'.$\r$\nContinue anyway (not recommended)?" IDYES tomahawk_installed
Abort "Uninstall aborted by user"
tomahawk_installed:
;Delete registry keys.
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tomahawk"
DeleteRegValue HKLM "Software\Tomahawk" "VersionBuild"
DeleteRegValue HKLM "Software\Tomahawk" "VersionMajor"
DeleteRegValue HKLM "Software\Tomahawk" "VersionMinor"
DeleteRegValue HKLM "Software\Tomahawk" "VersionRevision"
DeleteRegValue HKLM "Software\Tomahawk" ""
DeleteRegKey HKLM "Software\Tomahawk"
DeleteRegKey HKCR "tomahawk"
;Start menu shortcuts.
!ifdef OPTION_SECTION_SC_START_MENU
SetShellVarContext all
RMDir /r "$SMPROGRAMS\Tomahawk"
SetShellVarContext current
!endif
;Desktop shortcut.
!ifdef OPTION_SECTION_SC_DESKTOP
IfFileExists "$DESKTOP\Tomahawk.lnk" 0 +2
Delete "$DESKTOP\Tomahawk.lnk"
!endif
;Quick Launch shortcut.
!ifdef OPTION_SECTION_SC_QUICK_LAUNCH
IfFileExists "$QUICKLAUNCH\Tomahawk.lnk" 0 +2
Delete "$QUICKLAUNCH\Tomahawk.lnk"
!endif
;Remove all the Program Files.
RMDir /r $INSTDIR
;Uninstall User Data if option is checked, otherwise skip.
${If} $UnPageUserAppDataCheckbox_State == ${BST_CHECKED}
RMDir /r "$LOCALAPPDATA\Tomahawk"
${EndIf}
SetDetailsPrint textonly
DetailPrint "Finsihed."
SectionEnd
##############################################################################
# #
# NSIS Installer Event Handler Functions #
# #
##############################################################################
Function .onInit
!insertmacro INSTALLOPTIONS_EXTRACT "NSIS.InstallOptions.ini"
;Remove Quick Launch option from Windows 7, as no longer applicable - usually.
${IfNot} ${AtMostWinVista}
SectionSetText ${SEC_QUICK_LAUNCH} "Quick Launch Shortcut (N/A)"
SectionSetFlags ${SEC_QUICK_LAUNCH} ${SF_RO}
SectionSetInstTypes ${SEC_QUICK_LAUNCH} 0
${EndIf}
${MementoSectionRestore}
UAC_Elevate:
UAC::RunElevated
StrCmp 1223 $0 UAC_ElevationAborted ; UAC dialog aborted by user?
StrCmp 0 $0 0 UAC_Err ; Error?
StrCmp 1 $1 0 UAC_Success ;Are we the real deal or just the wrapper?
Quit
UAC_Err:
MessageBox MB_ICONSTOP "Unable to elevate, error $0"
Abort
UAC_ElevationAborted:
Abort
UAC_Success:
StrCmp 1 $3 +4 ;Admin?
StrCmp 3 $1 0 UAC_ElevationAborted ;Try again?
MessageBox MB_ICONSTOP "This installer requires admin access, try again"
goto UAC_Elevate
;Prevent multiple instances.
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "tomahawkInstaller") i .r1 ?e'
Pop $R0
StrCmp $R0 0 +3
MessageBox MB_OK|MB_ICONEXCLAMATION "The installer is already running."
Abort
;Use available InstallLocation when possible. This is useful in the uninstaller
;via re-install, which would otherwise use a default location - a bug.
ReadRegStr $R0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tomahawk" "InstallLocation"
StrCmp $R0 "" SkipSetInstDir
StrCpy $INSTDIR $R0
SkipSetInstDir:
;Shutdown Tomahawk in case Add/Remove re-installer option used.
Call EnsureTomahawkShutdown
FunctionEnd
Function .onInstSuccess
${MementoSectionSave}
UAC::Unload ;Must call unload!
FunctionEnd
Function .onInstFailed
UAC::Unload ;Must call unload!
FunctionEnd
##############################################################################
# #
# NSIS Uninstaller Event Handler Functions #
# #
##############################################################################
Function un.onInit
UAC_Elevate:
UAC::RunElevated
StrCmp 1223 $0 UAC_ElevationAborted ; UAC dialog aborted by user?
StrCmp 0 $0 0 UAC_Err ; Error?
StrCmp 1 $1 0 UAC_Success ;Are we the real deal or just the wrapper?
Quit
UAC_Err:
MessageBox MB_ICONSTOP "Unable to elevate, error $0"
Abort
UAC_ElevationAborted:
Abort
UAC_Success:
StrCmp 1 $3 +4 ;Admin?
StrCmp 3 $1 0 UAC_ElevationAborted ;Try again?
MessageBox MB_ICONSTOP "This uninstaller requires admin access, try again"
goto UAC_Elevate
;Prevent multiple instances.
System::Call 'kernel32::CreateMutexA(i 0, i 0, t "tomahawkUninstaller") i .r1 ?e'
Pop $R0
StrCmp $R0 0 +3
MessageBox MB_OK|MB_ICONEXCLAMATION "This uninstaller is already running."
Abort
FunctionEnd
Function un.onUnInstSuccess
UAC::Unload ;Must call unload!
FunctionEnd
Function un.onUnInstFailed
UAC::Unload ;Must call unload!
FunctionEnd

View File

@@ -0,0 +1,21 @@
# Do not edit! Generated by kwsysDateStamp.py
#=============================================================================
# KWSys - Kitware System Library
# Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# KWSys version date year component. Format is CCYY.
SET(KWSYS_DATE_STAMP_YEAR 2011)
# KWSys version date month component. Format is MM.
SET(KWSYS_DATE_STAMP_MONTH 07)
# KWSys version date day component. Format is DD.
SET(KWSYS_DATE_STAMP_DAY 06)

53
CPack.cmake Normal file
View File

@@ -0,0 +1,53 @@
INCLUDE( InstallRequiredSystemLibraries )
SET( CPACK_PACKAGE_CONTACT "Dominik Schmidt <domme@tomahawk-player.org>" )
SET( CPACK_PACKAGE_FILE_NAME tomahawk-${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
# CPACK_INSTALL_CMAKE_PROJECTS List of four values: Build directory, Project Name, Project Component, Directory in the package /home/andy/vtk/CMake-bin;CMake;ALL;/
SET( CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_SOURCE_DIR}/README" ) # File used as a description of a project /path/to/project/ReadMe.txt
SET( CPACK_PACKAGE_DESCRIPTION_SUMMARY ${TOMAHAWK_DESCRIPTION_SUMMARY} ) # Description summary of a project
# CPACK_PACKAGE_EXECUTABLES List of pairs of executables and labels. Used by the NSIS generator to create Start Menu shortcuts. ccmake;CMake
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_VENDOR ${TOMAHAWK_ORGANIZATION_NAME} ) # Package vendor 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} )
# CPACK_SOURCE_GENERATOR List of generators used for the source package TGZ;TZ
SET( CPACK_SOURCE_GENERATOR TGZ )
SET( CPACK_SOURCE_IGNORE_FILES "/\\\\.git/" ".*~$" ".kate-swp$" "/build_dir/" "/clang/" "/gcc/" "/build/" "/win/" ) # Pattern of files in the source tree that won't be packaged
SET( CPACK_SOURCE_PACKAGE_FILE_NAME tomahawk-${TOMAHAWK_VERSION} ) # Name of the source package
# CPACK_SOURCE_STRIP_FILES List of files in the source tree that will be stripped. Starting with CMake 2.6.0 CPACK_SOURCE_STRIP_FILES will be a boolean variable which enables stripping of all files (a list of files evaluates to TRUE in CMake, so this change is compatible).
# CPACK_STRIP_FILES List of files to be stripped. Starting with CMake 2.6.0 CPACK_STRIP_FILES will be a boolean variable which enables stripping of all files (a list of files evaluates to TRUE in CMake, so this change is compatible). bin/ccmake;bin/cmake;bin/cpack;bin/ctest
# CPACK_SYSTEM_NAME System name, defaults to the value of ${CMAKE_SYSTEM_NAME}. Linux-i686
# Advanced settings
# CPACK_CMAKE_GENERATOR What CMake generator should be used if the project is CMake project. Defaults to the value of CMAKE_GENERATOR. Unix Makefiles
SET( CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE.txt" ) # License file for the project, used by the STGZ, NSIS, and PackageMaker generators. /home/andy/vtk/CMake/Copyright.txt
# CPACK_RESOURCE_FILE_README ReadMe file for the project, used by PackageMaker generator. /home/andy/vtk/CMake/Templates/CPack.GenericDescription.txt
# CPACK_RESOURCE_FILE_WELCOME Welcome file for the project, used by PackageMaker generator. /home/andy/vtk/CMake/Templates/CPack.GenericWelcome.txt
SET( CPACK_PACKAGE_VERSION ${TOMAHAWK_VERSION} )
SET( CPACK_TOPLEVEL_TAG "narf" ) # Directory for the installed files. - needed to provide anything to avoid an error# CPACK_INSTALL_COMMANDS Extra commands to install components.
# CPACK_INSTALL_DIRECTORIES Extra directories to install.
# CPACK_MONOLITHIC_INSTALL When set disables the component-based installer.
# CPACK_PACKAGING_INSTALL_PREFIX Sets the default root that the generated package installs into, '/usr' is the default for the debian and redhat generators /usr/local
##
# INSTALL DEPS
##
# Set the options file that needs to be included inside CMakeCPackOptions.cmake
#SET(QT_DIALOG_CPACK_OPTIONS_FILE ${CMake_BINARY_DIR}/Source/QtDialog/QtDialogCPack.cmake)
configure_file("${CMAKE_SOURCE_DIR}/CPackOptions.cmake.in"
"${CMAKE_BINARY_DIR}/CPackOptions.cmake" @ONLY)
set(CPACK_PROJECT_CONFIG_FILE "${CMAKE_BINARY_DIR}/CPackOptions.cmake") # File included at cpack time, once per generator after setting CPACK_GENERATOR to the actual generator being used; allows per-generator setting of CPACK_* variables at cpack time. ${PROJECT_BINARY_DIR}/CPackOptions.cmake
include(CPack)

73
CPackOptions.cmake.in Normal file
View File

@@ -0,0 +1,73 @@
# This file is configured at cmake time, and loaded at cpack time.
# To pass variables to cpack from cmake, they must be configured
# in this file.
if(CPACK_GENERATOR MATCHES "NSIS")
#SET(CPACK_NSIS_INSTALL_ROOT "@CPACK_NSIS_INSTALL_ROOT@")
# set the install/unistall icon used for the installer itself
# There is a bug in NSI that does not handle full unix paths properly.
#SET(CPACK_NSIS_MUI_ICON "@CMake_SOURCE_DIR@/Utilities/Release\\CMakeLogo.ico")
#SET(CPACK_NSIS_MUI_UNIICON "@CMake_SOURCE_DIR@/Utilities/Release\\CMakeLogo.ico")
# set the package header icon for MUI
#SET(CPACK_PACKAGE_ICON "@CMake_SOURCE_DIR@/Utilities/Release\\CMakeInstall.bmp")
# tell cpack to create links to the doc files
#SET(CPACK_NSIS_MENU_LINKS
# "doc/cmake-@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@/cmake-gui.html" "cmake-gui Help"
# "doc/cmake-@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@/cmake.html" "CMake Help"
# "doc/cmake-@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@/cmake-properties.html"
# "CMake Properties and Variables Help"
# "doc/cmake-@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@/ctest.html" "CTest Help"
# "doc/cmake-@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@/cmake-modules.html" "CMake Modules Help"
# "doc/cmake-@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@/cmake-commands.html" "CMake Commands Help"
# "doc/cmake-@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@/cpack.html" "CPack Help"
# "http://www.cmake.org" "CMake Web Site"
# )
# Use the icon from cmake-gui for add-remove programs
#SET(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\cmake-gui.exe")
#
#SET(CPACK_NSIS_PACKAGE_NAME "@CPACK_NSIS_PACKAGE_NAME@")
#SET(CPACK_NSIS_DISPLAY_NAME "@CPACK_NSIS_PACKAGE_NAME@, a cross-platform, open-source build system")
#SET(CPACK_NSIS_HELP_LINK "http://www.cmake.org")
#SET(CPACK_NSIS_URL_INFO_ABOUT "http://www.kitware.com")
#SET(CPACK_NSIS_CONTACT @CPACK_PACKAGE_CONTACT@)
#SET(CPACK_NSIS_MODIFY_PATH ON)
##### all options
#CPACK_NSIS_MUI_ICON The icon file (.ico) for the generated install program. Both this and CPACK_NSIS_MUI_UNIICON need to set for this to have any effect. installer.ico
#CPACK_NSIS_MUI_UNIICON The icon file (.ico) for the generated uninstall program. Both this and CPACK_NSIS_MUI_ICON need to set for this to have any effect. uninstaller.ico
SET( CPACK_PACKAGE_ICON @CMAKE_SOURCE_DIR@/admin/win/nsi/installer.ico ) # A branding image that will be displayed on the top bar inside the installer. installer.bmp
#CPACK_NSIS_EXTRA_INSTALL_COMMANDS Extra NSIS commands that will be added to the install Section. ExecWait '\\\"$INSTDIR\\\\vcredist_x86.exe\\\" /q:a'
#CPACK_NSIS_EXTRA_UNINSTALL_COMMANDS Extra NSIS commands that will be added to the uninstall Section.
SET( CPACK_NSIS_COMPRESSOR "/SOLID lzma" ) # The arguments that will be passed to the NSIS SetCompressor command. /SOLID lzma
#CPACK_NSIS_MODIFY_PATH If this is set to "ON", then an extra page will appear in the installer that will allow the user to choose whether the program directory should be added to the system PATH variable. ON
#CPACK_NSIS_DISPLAY_NAME Undocumented. "${CPACK_PACKAGE_INSTALL_DIRECTORY} My Famous Project"
#CPACK_NSIS_INSTALLED_ICON_NAME Set the icon used for the Windows "Add or Remove Programs" tool. "bin\\\\MyExecutable.exe"
#CPACK_NSIS_HELP_LINK Adds link to registry. URI. "http:\\\\\\\\www.my-project-home-page.org"
#CPACK_NSIS_URL_INFO_ABOUT Adds link to registry and the vendor in add/remove programs' "Click here for support information" in program entry links here. "http:\\\\\\\\www.my-personal-home-page.com"
#CPACK_NSIS_CONTACT Adds link to add/remove programs' "Click here for support information" in program entry. "me@my-personal-home-page.com"
#CPACK_NSIS_CREATE_ICONS_EXTRA Additional NSIS commands for creating start menu shortcuts. set(CPACK_NSIS_CREATE_ICONS "CreateShortCut '\$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\${PROJECT_NAME}.lnk' '\$INSTDIR\\\\${PROJECT_NAME}.exe'")
#CPACK_NSIS_DELETE_ICONS_EXTRA Undocumented. Possibly: Additional NSIS commands to uninstall start menu shortcuts.
#CPACK_NSIS_MENU_LINKS Used to override the Start Menu links. "doc/cmake-@CMake_VERSION_MAJOR@.@CMake_VERSION_MINOR@/CMakeSetup.html" "CMakeSetup Help"
#CPACK_NSIS_MUI_FINISHPAGE_RUN If used, will make it possible for user to choose (on an additional page, displayed at the end of the installation) to run intalled program. Should point to program name to run, seemingly without any sub-directories of the installation directory in case program installed in such sub-directories (but please check generated NSIS script if you can't make it work). "MyExecutable.exe"
endif(CPACK_GENERATOR MATCHES "NSIS")
## include the cpack options for qt dialog if they exisit
## they might not if qt was not enabled for the build
#INCLUDE("@QT_DIALOG_CPACK_OPTIONS_FILE@" OPTIONAL)
#if("${CPACK_GENERATOR}" STREQUAL "PackageMaker")
# if(CMAKE_PACKAGE_QTGUI)
# set(CPACK_PACKAGE_DEFAULT_LOCATION "/Applications")
# else(CMAKE_PACKAGE_QTGUI)
# set(CPACK_PACKAGE_DEFAULT_LOCATION "/usr")
# endif(CMAKE_PACKAGE_QTGUI)
#endif("${CPACK_GENERATOR}" STREQUAL "PackageMaker")
SET( CMAKE_SOURCE_DIR @CMAKE_SOURCE_DIR@ )
SET( CMAKE_BINARY_DIR @CMAKE_BINARY_DIR@ )

4
README
View File

@@ -19,6 +19,10 @@ Detailed building instructions for OS X
---------------------------------------
See: http://wiki.tomahawk-player.org/mediawiki/index.php/Building_OS_X_Application_Bundle_on_Snow_Leopard_(10.6)
Doxygen Documentation
---------------------
See: http://dev.tomahawk-player.org/api/classes.html
Dependencies
------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
data/images/dashboard.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

BIN
data/images/post.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 13 KiB

300
data/js/tomahawk.js Normal file
View File

@@ -0,0 +1,300 @@
// if run in phantomjs add fake Tomahawk environment
if(window.Tomahawk === undefined)
{
alert("PHANTOMJS ENVIRONMENT");
var Tomahawk = {
fakeEnv: function()
{
return true;
},
resolverData: function()
{
return {
scriptPath: function()
{
return "/home/tomahawk/resolver.js";
}
};
},
log: function( message )
{
console.log( message );
}
};
}
Tomahawk.resolver = {
scriptPath: Tomahawk.resolverData().scriptPath
};
Tomahawk.timestamp = function() {
return Math.round( new Date()/1000 );
}
Tomahawk.dumpResult = function( result ) {
var results = result.results;
Tomahawk.log("Dumping " + results.length + " results for query " + result.qid + "...");
for(var i=0; i<results.length;i++)
{
var result = results[i];
Tomahawk.log( result.artist + " - " + result.track + " | " + result.url );
}
Tomahawk.log("Done.");
}
// javascript part of Tomahawk-Object API
Tomahawk.extend = function(object, members) {
var F = function() {};
F.prototype = object;
var newObject = new F;
for(var key in members)
{
newObject[key] = members[key];
}
return newObject;
}
// Resolver BaseObject, inherit it to implement your own resolver
var TomahawkResolver = {
init: function()
{
},
scriptPath: function()
{
return Tomahawk.resolverData().scriptPath;
},
getConfigUi: function()
{
return {};
},
getUserConfig: function()
{
var configJson = window.localStorage[ this.scriptPath() ];
if( configJson === undefined )
configJson = "{}";
var config = JSON.parse( configJson );
return config;
},
saveUserConfig: function()
{
var config = Tomahawk.resolverData().config;
var configJson = JSON.stringify( config );
window.localStorage[ this.scriptPath() ] = configJson;
},
resolve: function( qid, artist, album, title )
{
return {
qid: qid
};
},
search: function( qid, searchString )
{
return this.resolve( qid, "", "", searchString );
}
};
/**** begin example implementation of a resolver ****/
// implement the resolver
/*
* var DemoResolver = Tomahawk.extend(TomahawkResolver,
* {
* getSettings: function()
* {
* return {
* name: "Demo Resolver",
* weigth: 95,
* timeout: 5,
* limit: 10
};
},
resolve: function( qid, artist, album, track )
{
return {
qid: qid,
results: [
{
artist: "Mokele",
album: "You Yourself are Me Myself and I am in Love",
track: "Hiding In Your Insides (php)",
source: "Mokele.co.uk",
url: "http://play.mokele.co.uk/music/Hiding%20In%20Your%20Insides.mp3",
bitrate: 160,
duration: 248,
size: 4971780,
score: 1.0,
extension: "mp3",
mimetype: "audio/mpeg"
}
]
};
}
}
);
// register the resolver
Tomahawk.resolver.instance = DemoResolver;*/
/**** end example implementation of a resolver ****/
// help functions
Tomahawk.valueForSubNode = function(node, tag)
{
if(node === undefined)
throw new Error("Tomahawk.valueForSubnode: node is undefined!");
var element = node.getElementsByTagName(tag)[0];
if( element === undefined )
return undefined;
return element.textContent;
};
Tomahawk.syncRequest = function(url)
{
var xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open('GET', url, false);
xmlHttpRequest.send(null);
return xmlHttpRequest.responseText;
}
/**
*
* Secure Hash Algorithm (SHA256)
* http://www.webtoolkit.info/
*
* Original code by Angel Marin, Paul Johnston.
*
**/
Tomahawk.sha256=function(s){
var chrsz = 8;
var hexcase = 0;
function safe_add (x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
function S (X, n) { return ( X >>> n ) | (X << (32 - n)); }
function R (X, n) { return ( X >>> n ); }
function Ch(x, y, z) { return ((x & y) ^ ((~x) & z)); }
function Maj(x, y, z) { return ((x & y) ^ (x & z) ^ (y & z)); }
function Sigma0256(x) { return (S(x, 2) ^ S(x, 13) ^ S(x, 22)); }
function Sigma1256(x) { return (S(x, 6) ^ S(x, 11) ^ S(x, 25)); }
function Gamma0256(x) { return (S(x, 7) ^ S(x, 18) ^ R(x, 3)); }
function Gamma1256(x) { return (S(x, 17) ^ S(x, 19) ^ R(x, 10)); }
function core_sha256 (m, l) {
var K = new Array(0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786, 0xFC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x6CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2);
var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19);
var W = new Array(64);
var a, b, c, d, e, f, g, h, i, j;
var T1, T2;
m[l >> 5] |= 0x80 << (24 - l % 32);
m[((l + 64 >> 9) << 4) + 15] = l;
for ( var i = 0; i<m.length; i+=16 ) {
a = HASH[0];
b = HASH[1];
c = HASH[2];
d = HASH[3];
e = HASH[4];
f = HASH[5];
g = HASH[6];
h = HASH[7];
for ( var j = 0; j<64; j++) {
if (j < 16) W[j] = m[j + i];
else W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);
T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);
T2 = safe_add(Sigma0256(a), Maj(a, b, c));
h = g;
g = f;
f = e;
e = safe_add(d, T1);
d = c;
c = b;
b = a;
a = safe_add(T1, T2);
}
HASH[0] = safe_add(a, HASH[0]);
HASH[1] = safe_add(b, HASH[1]);
HASH[2] = safe_add(c, HASH[2]);
HASH[3] = safe_add(d, HASH[3]);
HASH[4] = safe_add(e, HASH[4]);
HASH[5] = safe_add(f, HASH[5]);
HASH[6] = safe_add(g, HASH[6]);
HASH[7] = safe_add(h, HASH[7]);
}
return HASH;
}
function str2binb (str) {
var bin = Array();
var mask = (1 << chrsz) - 1;
for(var i = 0; i < str.length * chrsz; i += chrsz) {
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32);
}
return bin;
}
function Utf8Encode(string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
}
function binb2hex (binarray) {
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for(var i = 0; i < binarray.length * 4; i++) {
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
}
return str;
}
s = Utf8Encode(s);
return binb2hex(core_sha256(str2binb(s), s.length * chrsz));
}

View File

@@ -0,0 +1,18 @@
-- Script to migate from db version 24 to 25.
-- Added the social_attributes table.
--
-- Separate each command with %%
ALTER TABLE dynamic_playlist RENAME TO tmp_dynamic_playlist;
CREATE TABLE IF NOT EXISTS dynamic_playlist (
guid TEXT NOT NULL REFERENCES playlist(guid) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,
pltype TEXT, -- the generator type
plmode INTEGER -- the mode of this playlist
);
INSERT INTO dynamic_playlist( guid, pltype, plmode ) SELECT guid, pltype, plmode FROM tmp_dynamic_playlist;
DROP TABLE tmp_dynamic_playlist;
UPDATE settings SET v = '25' WHERE k == 'schema_version';

0
resource.qrc Normal file
View File

0
resources.prc Normal file
View File

View File

@@ -96,5 +96,7 @@
<file>./data/www/tomahawk_banner_small.png</file>
<file>./data/sql/dbmigrate-22_to_23.sql</file>
<file>./data/sql/dbmigrate-23_to_24.sql</file>
<file>./data/sql/dbmigrate-24_to_25.sql</file>
<file>./data/js/tomahawk.js</file>
</qresource>
</RCC>

View File

@@ -264,4 +264,5 @@ IF( UNIX AND NOT APPLE AND KDE4_INSTALLED ) #install protocol file
ENDIF()
INSTALL( FILES ${CMAKE_BINARY_DIR}/tomahawk.protocol DESTINATION ${PROTOCOL_INSTALL_DIR} )
ENDIF()
#INCLUDE( "CPack.txt" )

View File

@@ -80,6 +80,7 @@ AudioControls::AudioControls( QWidget* parent )
ui->volumeLowButton->setPixmap( RESPATH "images/volume-icon-muted.png" );
ui->volumeHighButton->setPixmap( RESPATH "images/volume-icon-full.png" );
ui->loveButton->setPixmap( RESPATH "images/not-loved.png" );
ui->loveButton->setCheckable( true );
ui->ownerLabel->setForegroundRole( QPalette::Dark );
ui->metaDataArea->setStyleSheet( "QWidget#metaDataArea {\nborder-width: 4px;\nborder-image: url(" RESPATH "images/now-playing-panel.png) 4 4 4 4 stretch stretch; }" );
@@ -151,7 +152,7 @@ AudioControls::AudioControls( QWidget* parent )
connect( ui->artistTrackLabel, SIGNAL( clickedArtist() ), SLOT( onArtistClicked() ) );
connect( ui->artistTrackLabel, SIGNAL( clickedTrack() ), SLOT( onTrackClicked() ) );
connect( ui->albumLabel, SIGNAL( clickedAlbum() ), SLOT( onAlbumClicked() ) );
connect( ui->loveButton, SIGNAL( clicked() ), SLOT( onLoveButtonClicked() ) );
connect( ui->loveButton, SIGNAL( clicked( bool ) ), SLOT( onLoveButtonClicked( bool ) ) );
// <From AudioEngine>
connect( AudioEngine::instance(), SIGNAL( loading( Tomahawk::result_ptr ) ), SLOT( onPlaybackLoading( Tomahawk::result_ptr ) ) );
@@ -166,8 +167,8 @@ AudioControls::AudioControls( QWidget* parent )
.scaled( ui->coverImage->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
SIGNAL( info( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
SLOT( infoSystemInfo( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ) );
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
connect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ), SLOT( infoSystemFinished( QString ) ) );
@@ -217,20 +218,21 @@ AudioControls::onPlaybackStarted( const Tomahawk::result_ptr& result )
trackInfo["artist"] = result->artist()->name();
trackInfo["album"] = result->album()->name();
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo(
s_acInfoIdentifier, Tomahawk::InfoSystem::InfoAlbumCoverArt,
QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo ), Tomahawk::InfoSystem::InfoCustomData() );
Tomahawk::InfoSystem::InfoRequestData requestData;
requestData.caller = s_acInfoIdentifier;
requestData.type = Tomahawk::InfoSystem::InfoAlbumCoverArt;
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo );
requestData.customData = QVariantMap();
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
}
void
AudioControls::infoSystemInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomData customData )
AudioControls::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
{
Q_UNUSED( input );
Q_UNUSED( customData );
qDebug() << Q_FUNC_INFO << caller << type << s_acInfoIdentifier << Tomahawk::InfoSystem::InfoAlbumCoverArt;
if ( caller != s_acInfoIdentifier || type != Tomahawk::InfoSystem::InfoAlbumCoverArt )
qDebug() << Q_FUNC_INFO << requestData.caller << requestData.type << s_acInfoIdentifier << Tomahawk::InfoSystem::InfoAlbumCoverArt;
if ( requestData.caller != s_acInfoIdentifier || requestData.type != Tomahawk::InfoSystem::InfoAlbumCoverArt )
{
qDebug() << "Info of wrong type or not with our identifier";
return;
@@ -242,13 +244,13 @@ AudioControls::infoSystemInfo( QString caller, Tomahawk::InfoSystem::InfoType ty
return;
}
if ( !output.canConvert< Tomahawk::InfoSystem::InfoCustomData >() )
if ( !output.canConvert< QVariantMap >() )
{
qDebug() << "Cannot convert fetched art from a QByteArray";
return;
}
Tomahawk::InfoSystem::InfoCustomData returnedData = output.value< Tomahawk::InfoSystem::InfoCustomData >();
QVariantMap returnedData = output.value< QVariantMap >();
const QByteArray ba = returnedData["imgbytes"].toByteArray();
if ( ba.length() )
{
@@ -282,7 +284,6 @@ AudioControls::onPlaybackLoading( const Tomahawk::result_ptr& result )
ui->albumLabel->setResult( result );
ui->ownerLabel->setText( result->friendlySource() );
ui->coverImage->setPixmap( m_defaultCover );
ui->loveButton->setVisible( true );
ui->timeLabel->setText( TomahawkUtils::timeToString( 0 ) );
ui->timeLeftLabel->setText( "-" + TomahawkUtils::timeToString( result->duration() ) );
@@ -298,6 +299,21 @@ AudioControls::onPlaybackLoading( const Tomahawk::result_ptr& result )
ui->pauseButton->setVisible( true );
ui->playPauseButton->setVisible( false );
ui->playPauseButton->setEnabled( false );
ui->loveButton->setEnabled( true );
ui->loveButton->setVisible( true );
result->loadSocialActions();
if ( result->loved() )
{
ui->loveButton->setPixmap( RESPATH "images/loved.png" );
ui->loveButton->setChecked( true );
}
else
{
ui->loveButton->setPixmap( RESPATH "images/not-loved.png" );
ui->loveButton->setChecked( false );
}
}
@@ -340,12 +356,13 @@ AudioControls::onPlaybackStopped()
ui->timeLeftLabel->setText( "" );
ui->coverImage->setPixmap( QPixmap() );
ui->seekSlider->setVisible( false );
ui->loveButton->setVisible( false );
ui->pauseButton->setVisible( false );
ui->pauseButton->setEnabled( false );
ui->playPauseButton->setEnabled( true );
ui->playPauseButton->setVisible( true );
ui->loveButton->setEnabled( false );
ui->loveButton->setVisible( false );
/* m_pauseAction->setEnabled( false );
m_playAction->setEnabled( true ); */
@@ -489,18 +506,32 @@ AudioControls::onTrackClicked()
void
AudioControls::onLoveButtonClicked()
AudioControls::onLoveButtonClicked( bool checked )
{
Tomahawk::InfoSystem::InfoCriteriaHash trackInfo;
trackInfo["title"] = m_currentTrack->track();
trackInfo["artist"] = m_currentTrack->artist()->name();
trackInfo["album"] = m_currentTrack->album()->name();
if ( checked )
{
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo(
s_acInfoIdentifier, Tomahawk::InfoSystem::InfoLove,
QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo ) );
DatabaseCommand_SocialAction* cmd = new DatabaseCommand_SocialAction( m_currentTrack, QString( "Love" ) );
DatabaseCommand_SocialAction* cmd = new DatabaseCommand_SocialAction( m_currentTrack, QString( "Love" ), QString( "true") );
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>(cmd) );
ui->loveButton->setPixmap( RESPATH "images/loved.png" );
}
else
{
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo(
s_acInfoIdentifier, Tomahawk::InfoSystem::InfoUnLove,
QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo ) );
DatabaseCommand_SocialAction* cmd = new DatabaseCommand_SocialAction( m_currentTrack, QString( "Love" ), QString( "false" ) );
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>(cmd) );
ui->loveButton->setPixmap( RESPATH "images/not-loved.png" );
}
}

View File

@@ -65,9 +65,9 @@ private slots:
void onArtistClicked();
void onAlbumClicked();
void onTrackClicked();
void onLoveButtonClicked();
void onLoveButtonClicked( bool );
void infoSystemInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomData customData );
void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
void infoSystemFinished( QString target );
private:

View File

@@ -251,6 +251,8 @@
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="ImageButton" name="loveButton">
<property name="sizePolicy">
@@ -259,11 +261,29 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="text">
<string>love</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>13</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="ownerLabel">
<property name="font">

View File

@@ -21,6 +21,7 @@
#include <QDialog>
#include <QDialogButtonBox>
#include <QVBoxLayout>
#include <QPushButton>
class DelegateConfigWrapper : public QDialog
{
@@ -39,6 +40,7 @@ public:
v->addWidget( m_widget );
QDialogButtonBox* buttons = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this );
m_okButton = buttons->button( QDialogButtonBox::Ok );
connect( buttons, SIGNAL( clicked( QAbstractButton*) ), this, SLOT( closed( QAbstractButton* ) ) );
connect( this, SIGNAL( rejected() ), this, SLOT( rejected() ) );
v->addWidget( buttons );
@@ -57,6 +59,11 @@ public:
}
public slots:
void toggleOkButton( bool dataError )
{
// if dataError is True we want to set the button enabled to false
m_okButton->setEnabled( !dataError );
}
void closed( QAbstractButton* b )
{
// let the config widget live to see another day
@@ -90,6 +97,7 @@ public slots:
private:
QWidget* m_widget;
QPushButton* m_okButton;
};
#endif

View File

@@ -22,8 +22,7 @@
#ifdef ENABLE_HEADLESS
#define TOMAHAWK_APPLICATION QCoreApplication
#define TOMAHAWK_HEADLESS
#include <QApplication>>
#include <QApplication>
#else

View File

@@ -31,6 +31,7 @@ set( libSources
viewpage.cpp
viewmanager.cpp
globalactionmanager.cpp
contextMenu.cpp
sip/SipPlugin.cpp
sip/SipHandler.cpp
@@ -81,6 +82,7 @@ set( libSources
database/databasecommand_addclientauth.cpp
database/databasecommand_clientauthvalid.cpp
database/databasecommand_socialaction.cpp
database/databasecommand_loadsocialactions.cpp
database/database.cpp
infosystem/infosystemcache.cpp
@@ -169,7 +171,9 @@ set( libSources
widgets/welcomewidget.cpp
widgets/welcomeplaylistmodel.cpp
widgets/overlaywidget.cpp
widgets/HeaderLabel.cpp
widgets/infowidgets/sourceinfowidget.cpp
widgets/infowidgets/ArtistInfoWidget.cpp
kdsingleapplicationguard/kdsingleapplicationguard.cpp
kdsingleapplicationguard/kdsharedmemorylocker.cpp
@@ -191,9 +195,9 @@ set( libHeaders
result.h
source.h
sourceplaylistinterface.h
viewpage.h
viewmanager.h
globalactionmanager.h
contextMenu.h
artist.h
album.h
@@ -249,6 +253,7 @@ set( libHeaders
database/databasecommand_addclientauth.h
database/databasecommand_clientauthvalid.h
database/databasecommand_socialaction.h
database/databasecommand_loadsocialactions.h
infosystem/infosystem.h
infosystem/infosystemworker.h
@@ -304,7 +309,6 @@ set( libHeaders
playlist/dynamic/DynamicPlaylist.h
playlist/dynamic/DynamicControl.h
playlist/dynamic/GeneratorFactory.h
playlist/dynamic/GeneratorInterface.h
playlist/dynamic/DynamicView.h
playlist/dynamic/DynamicModel.h
@@ -320,7 +324,6 @@ set( libHeaders
playlist/dynamic/widgets/DynamicSetupWidget.h
playlist/dynamic/widgets/LoadingSpinner.h
utils/tomahawkutils.h
utils/querylabel.h
utils/elidedlabel.h
utils/animatedcounterlabel.h
@@ -337,23 +340,31 @@ set( libHeaders
widgets/welcomewidget.h
widgets/welcomeplaylistmodel.h
widgets/overlaywidget.h
widgets/HeaderLabel.h
widgets/infowidgets/sourceinfowidget.h
widgets/infowidgets/ArtistInfoWidget.h
kdsingleapplicationguard/kdsingleapplicationguard.h
kdsingleapplicationguard/kdsharedmemorylocker.h
kdsingleapplicationguard/kdtoolsglobal.h
kdsingleapplicationguard/kdlockedsharedmemorypointer.h
)
set( libHeaders_NoMOC
viewpage.h
infosystem/infoplugins/unix/imageconverter.h
playlist/dynamic/GeneratorInterface.h
playlist/dynamic/GeneratorFactory.h
utils/tomahawkutils.h
)
set( libUI ${libUI}
widgets/playlisttypeselectordlg.ui
widgets/newplaylistwidget.ui
widgets/searchwidget.ui
widgets/welcomewidget.ui
widgets/infowidgets/sourceinfowidget.ui
widgets/infowidgets/ArtistInfoWidget.ui
playlist/topbar/topbar.ui
playlist/infobar/infobar.ui
)
@@ -379,17 +390,21 @@ include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/.
IF( UNIX AND NOT APPLE )
SET( libSources ${libSources}
infosystem/infoplugins/win/gfwnotifyplugin.cpp
infosystem/infoplugins/unix/fdonotifyplugin.cpp
infosystem/infoplugins/unix/imageconverter.cpp )
SET( libHeaders ${libHeaders}
infosystem/infoplugins/win/gfwnotifyplugin.h
infosystem/infoplugins/unix/fdonotifyplugin.h
infosystem/infoplugins/unix/imageconverter.h )
ENDIF( UNIX AND NOT APPLE )
IF( WIN32 )
SET( libSources ${libSources}
infosystem/infoplugins/win/gfwnotifyplugin.cpp )
SET( libHeaders ${libHeaders}
infosystem/infoplugins/win/gfwnotifyplugin.h )
SET( OS_SPECIFIC_LINK_LIBRARIES
${OS_SPECIFIC_LINK_LIBRARIES}
# System

View File

@@ -71,6 +71,8 @@ signals:
void trackCountChanged( unsigned int tracks );
void sourceTrackCountChanged( unsigned int tracks );
void nextTrackReady();
private slots:
void onTracksAdded( const QList<Tomahawk::query_ptr>& tracks );

View File

@@ -26,9 +26,27 @@
using namespace Tomahawk;
Artist::Artist() {}
Artist::~Artist() {}
Artist::Artist()
{
}
Artist::~Artist()
{
}
artist_ptr
Artist::get( const QString& name, bool autoCreate )
{
int artid = Database::instance()->impl()->artistId( name, autoCreate );
if ( artid < 1 )
return artist_ptr();
return Artist::get( artid, name );
}
artist_ptr
Artist::get( unsigned int id, const QString& name )

View File

@@ -36,6 +36,7 @@ class DLLEXPORT Artist : public QObject, public PlaylistInterface
Q_OBJECT
public:
static artist_ptr get( const QString& name, bool autoCreate = false );
static artist_ptr get( unsigned int id, const QString& name );
Artist( unsigned int id, const QString& name );
@@ -71,6 +72,8 @@ signals:
void trackCountChanged( unsigned int tracks );
void sourceTrackCountChanged( unsigned int tracks );
void nextTrackReady();
private slots:
void onTracksAdded( const QList<Tomahawk::query_ptr>& tracks );

View File

@@ -22,10 +22,10 @@
#include "playlistinterface.h"
#include "sourceplaylistinterface.h"
#include "tomahawksettings.h"
#include "database/database.h"
#include "database/databasecommand_logplayback.h"
#include "infosystem/infosystem.h"
#include "network/servent.h"
#include "album.h"
@@ -51,6 +51,8 @@ AudioEngine::AudioEngine()
, m_queue( 0 )
, m_timeElapsed( 0 )
, m_expectStop( false )
, m_waitingOnNewTrack( false )
, m_infoSystemConnected( false )
{
s_instance = this;
qDebug() << "Init AudioEngine";
@@ -74,17 +76,12 @@ AudioEngine::AudioEngine()
// Since it's indendent, we'll set it to 75% since that's nicer
setVolume( 75 );
#endif
m_retryTimer.setInterval( 10000 );
m_retryTimer.setSingleShot( false );
connect( &m_retryTimer, SIGNAL( timeout() ), SLOT( loadNextTrack() ) );
}
AudioEngine::~AudioEngine()
{
qDebug() << Q_FUNC_INFO;
m_retryTimer.stop();
m_mediaObject->stop();
// stop();
@@ -133,18 +130,16 @@ AudioEngine::pause()
m_mediaObject->pause();
emit paused();
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo(
s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNowPaused, QVariant() );
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNowPaused, QVariant() );
}
void
AudioEngine::stop( bool sendNotification )
AudioEngine::stop()
{
qDebug() << Q_FUNC_INFO;
m_mediaObject->stop();
m_retryTimer.stop();
if ( m_playlist )
m_playlist->reset();
@@ -152,9 +147,19 @@ AudioEngine::stop( bool sendNotification )
setCurrentTrack( Tomahawk::result_ptr() );
emit stopped();
if ( sendNotification )
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo(
s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNowStopped, QVariant() );
Tomahawk::InfoSystem::InfoTypeMap map;
map[ Tomahawk::InfoSystem::InfoNowStopped ] = QVariant();
if ( m_waitingOnNewTrack )
sendWaitingNotification();
else if ( TomahawkSettings::instance()->verboseNotifications() )
{
QVariantMap stopInfo;
stopInfo["message"] = QString( "Tomahawk is stopped." );
map[ Tomahawk::InfoSystem::InfoNotifyUser ] = QVariant::fromValue< QVariantMap >( stopInfo );
}
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( s_aeInfoIdentifier, map );
}
@@ -232,6 +237,92 @@ AudioEngine::mute()
}
void
AudioEngine::sendWaitingNotification() const
{
QVariantMap retryInfo;
retryInfo["message"] = QString( "The current track could not be resolved. Tomahawk will pick back up with the next resolvable track from this source." );
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo(
s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNotifyUser,
QVariant::fromValue< QVariantMap >( retryInfo ) );
}
void
AudioEngine::sendNowPlayingNotification()
{
qDebug() << Q_FUNC_INFO;
if ( ! m_infoSystemConnected )
{
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
connect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ), SLOT( infoSystemFinished( QString ) ) );
m_infoSystemConnected = true;
}
Tomahawk::InfoSystem::InfoCriteriaHash trackInfo;
trackInfo["artist"] = m_currentTrack->album()->artist()->name();
trackInfo["album"] = m_currentTrack->album()->name();
Tomahawk::InfoSystem::InfoRequestData requestData;
requestData.caller = s_aeInfoIdentifier;
requestData.type = Tomahawk::InfoSystem::InfoAlbumCoverArt;
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo );
requestData.customData = QVariantMap();
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
}
void
AudioEngine::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
{
qDebug() << Q_FUNC_INFO;
if ( requestData.caller != s_aeInfoIdentifier ||
requestData.type != Tomahawk::InfoSystem::InfoAlbumCoverArt )
{
qDebug() << Q_FUNC_INFO << " not destined for us or wrong type, caller is " << requestData.caller << " and type is " << requestData.type;
return;
}
QVariantMap playInfo;
playInfo["message"] = QString( "Tomahawk is playing \"%1\" by %2 on album %3." )
.arg( m_currentTrack->track() )
.arg( m_currentTrack->artist()->name() )
.arg( m_currentTrack->album()->name() );
if ( !output.isNull() && output.isValid() )
{
qDebug() << Q_FUNC_INFO << " output is valid";
QVariantMap returnedData = output.value< QVariantMap >();
const QByteArray ba = returnedData["imgbytes"].toByteArray();
qDebug() << "ba.length = " << ba.length();
if ( ba.length() )
{
QPixmap pm;
pm.loadFromData( ba );
playInfo["image"] = QVariant( pm.toImage() );
}
}
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo(
s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNotifyUser,
QVariant::fromValue< QVariantMap >( playInfo ) );
}
void
AudioEngine::infoSystemFinished( QString caller )
{
Q_UNUSED( caller );
qDebug() << Q_FUNC_INFO;
}
void
AudioEngine::onTrackAboutToFinish()
{
@@ -244,8 +335,6 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
{
qDebug() << Q_FUNC_INFO << thread() << result;
m_retryTimer.stop();
bool err = false;
{
@@ -306,14 +395,17 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>(cmd) );
Tomahawk::InfoSystem::InfoCriteriaHash trackInfo;
trackInfo["title"] = m_currentTrack->track();
trackInfo["artist"] = m_currentTrack->artist()->name();
trackInfo["album"] = m_currentTrack->album()->name();
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo(
s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNowPlaying,
QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo ) );
if ( TomahawkSettings::instance()->verboseNotifications() )
sendNowPlayingNotification();
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo(
s_aeInfoIdentifier,
Tomahawk::InfoSystem::InfoNowPlaying,
QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo ) );
}
}
@@ -323,6 +415,7 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
return false;
}
m_waitingOnNewTrack = false;
return true;
}
@@ -331,8 +424,6 @@ AudioEngine::loadPreviousTrack()
{
qDebug() << Q_FUNC_INFO;
m_retryTimer.stop();
if ( !m_playlist )
{
stop();
@@ -352,9 +443,6 @@ AudioEngine::loadNextTrack()
{
qDebug() << Q_FUNC_INFO;
bool wasRetrying = m_retryTimer.isActive();
m_retryTimer.stop();
Tomahawk::result_ptr result;
if ( m_queue && m_queue->trackCount() )
@@ -371,20 +459,9 @@ AudioEngine::loadNextTrack()
loadTrack( result );
else
{
stop( false );
if ( m_playlist && m_playlist->retryMode() == Tomahawk::PlaylistInterface::Retry )
{
if ( !wasRetrying )
{
Tomahawk::InfoSystem::InfoCriteriaHash retryInfo;
retryInfo["message"] = QString( "The current track could not be resolved. Tomahawk will keep trying..." );
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo(
s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNotifyUser,
QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( retryInfo ) );
}
m_retryTimer.setInterval( m_playlist->retryInterval() );
m_retryTimer.start();
}
m_waitingOnNewTrack = true;
stop();
}
}
@@ -402,19 +479,25 @@ AudioEngine::playItem( Tomahawk::PlaylistInterface* playlist, const Tomahawk::re
if ( !result.isNull() )
loadTrack( result );
else if ( m_playlist->retryMode() == PlaylistInterface::Retry )
else if ( m_playlist && m_playlist->retryMode() == PlaylistInterface::Retry )
{
Tomahawk::InfoSystem::InfoCriteriaHash retryInfo;
retryInfo["message"] = QString( "The current track could not be resolved. Tomahawk will keep trying..." );
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo(
s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNotifyUser,
QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( retryInfo ) );
m_retryTimer.setInterval( playlist->retryInterval() );
m_retryTimer.start();
m_waitingOnNewTrack = true;
stop();
}
}
void
AudioEngine::playlistNextTrackReady()
{
if ( !m_waitingOnNewTrack )
return;
m_waitingOnNewTrack = false;
next();
}
void
AudioEngine::onAboutToFinish()
{
@@ -476,7 +559,12 @@ AudioEngine::setPlaylist( PlaylistInterface* playlist )
{
if ( m_playlist )
m_playlist->reset();
m_playlist = playlist;
if ( m_playlist && m_playlist->object() && m_playlist->retryMode() == PlaylistInterface::Retry )
connect( m_playlist->object(), SIGNAL( nextTrackReady() ), SLOT( playlistNextTrackReady() ) );
emit playlistChanged( playlist );
}
@@ -500,7 +588,7 @@ AudioEngine::setCurrentTrack( const Tomahawk::result_ptr& result )
bool
AudioEngine::isHttpResult( const QString& url ) const
{
return url.startsWith( "http://" );
return url.startsWith( "http://" ) || url.startsWith( "https://" );
}

View File

@@ -25,6 +25,8 @@
#include <phonon/MediaObject>
#include <phonon/AudioOutput>
#include "infosystem/infosystem.h"
#include "result.h"
#include "typedefs.h"
@@ -65,7 +67,7 @@ public slots:
void playPause();
void play();
void pause();
void stop( bool sendNotification = true );
void stop();
void previous();
void next();
@@ -83,6 +85,11 @@ public slots:
void onTrackAboutToFinish();
void playlistNextTrackReady();
void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
void infoSystemFinished( QString caller );
signals:
void loading( const Tomahawk::result_ptr& track );
void started( const Tomahawk::result_ptr& track );
@@ -115,6 +122,8 @@ private slots:
private:
bool isHttpResult( const QString& ) const;
bool isLocalResult( const QString& ) const;
void sendWaitingNotification() const;
void sendNowPlayingNotification();
bool m_isPlayingHttp;
QSharedPointer<QIODevice> m_input;
@@ -130,8 +139,8 @@ private:
unsigned int m_timeElapsed;
bool m_expectStop;
QTimer m_retryTimer;
bool m_waitingOnNewTrack;
bool m_infoSystemConnected;
static AudioEngine* s_instance;
};

View File

@@ -0,0 +1,218 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "contextMenu.h"
#include <QDebug>
#include "globalactionmanager.h"
#include "playlistview.h"
#include "viewmanager.h"
using namespace Tomahawk;
ContextMenu::ContextMenu( QWidget* parent )
: QMenu( parent )
{
m_sigmap = new QSignalMapper( this );
connect( m_sigmap, SIGNAL( mapped( int ) ), SLOT( onTriggered( int ) ) );
m_supportedActions = ActionPlay | ActionQueue | ActionCopyLink;
}
void
ContextMenu::clear()
{
QMenu::clear();
m_queries.clear();
m_albums.clear();
m_artists.clear();
}
void
ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
{
if ( queries.isEmpty() )
return;
QMenu::clear();
m_queries.clear();
m_queries << queries;
if ( m_supportedActions & ActionPlay && itemCount() == 1 )
m_sigmap->setMapping( addAction( tr( "&Play" ) ), ActionPlay );
if ( m_supportedActions & ActionQueue )
m_sigmap->setMapping( addAction( tr( "Add to &Queue" ) ), ActionQueue );
//m_sigmap->setMapping( addAction( tr( "&Add to Playlist" ) ), ActionAddToPlaylist );
addSeparator();
if ( m_supportedActions & ActionCopyLink && itemCount() == 1 )
m_sigmap->setMapping( addAction( tr( "Copy Track &Link" ) ), ActionCopyLink );
addSeparator();
if ( m_supportedActions & ActionDelete )
m_sigmap->setMapping( addAction( queries.count() > 1 ? tr( "&Delete Items" ) : tr( "&Delete Item" ) ), ActionDelete );
foreach ( QAction* action, actions() )
{
connect( action, SIGNAL( triggered() ), m_sigmap, SLOT( map() ) );
}
}
void
ContextMenu::setQuery( const Tomahawk::query_ptr& query )
{
QList<query_ptr> queries;
queries << query;
setQueries( queries );
}
void
ContextMenu::setAlbums( const QList<Tomahawk::album_ptr>& albums )
{
if ( albums.isEmpty() )
return;
QMenu::clear();
m_albums.clear();
m_albums << albums;
if ( m_supportedActions & ActionPlay && itemCount() == 1 )
m_sigmap->setMapping( addAction( tr( "&Play" ) ), ActionPlay );
if ( m_supportedActions & ActionQueue )
m_sigmap->setMapping( addAction( tr( "Add to &Queue" ) ), ActionQueue );
//m_sigmap->setMapping( addAction( tr( "&Add to Playlist" ) ), ActionAddToPlaylist );
addSeparator();
/* if ( m_supportedActions & ActionCopyLink && itemCount() == 1 )
m_sigmap->setMapping( addAction( tr( "Copy Album &Link" ) ), ActionCopyLink ); */
foreach ( QAction* action, actions() )
{
connect( action, SIGNAL( triggered() ), m_sigmap, SLOT( map() ) );
}
}
void
ContextMenu::setAlbum( const Tomahawk::album_ptr& album )
{
QList<album_ptr> albums;
albums << album;
setAlbums( albums );
}
void
ContextMenu::setArtists( const QList<Tomahawk::artist_ptr>& artists )
{
if ( artists.isEmpty() )
return;
QMenu::clear();
m_artists.clear();
m_artists << artists;
if ( m_supportedActions & ActionPlay && itemCount() == 1 )
m_sigmap->setMapping( addAction( tr( "&Play" ) ), ActionPlay );
if ( m_supportedActions & ActionQueue )
m_sigmap->setMapping( addAction( tr( "Add to &Queue" ) ), ActionQueue );
//m_sigmap->setMapping( addAction( tr( "&Add to Playlist" ) ), ActionAddToPlaylist );
addSeparator();
/* if ( m_supportedActions & ActionCopyLink && itemCount() == 1 )
m_sigmap->setMapping( addAction( tr( "Copy Artist &Link" ) ), ActionCopyLink ); */
foreach ( QAction* action, actions() )
{
connect( action, SIGNAL( triggered() ), m_sigmap, SLOT( map() ) );
}
}
void
ContextMenu::setArtist( const Tomahawk::artist_ptr& artist )
{
QList<artist_ptr> artists;
artists << artist;
setArtists( artists );
}
void
ContextMenu::onTriggered( int action )
{
switch ( action )
{
case ActionQueue:
addToQueue();
break;
case ActionCopyLink:
copyLink();
break;
default:
emit triggered( action );
}
}
void ContextMenu::addToQueue()
{
foreach ( const query_ptr& query, m_queries )
{
ViewManager::instance()->queue()->model()->append( query );
}
foreach ( const artist_ptr& artist, m_artists )
{
ViewManager::instance()->queue()->model()->append( artist );
}
foreach ( const album_ptr& album, m_albums )
{
ViewManager::instance()->queue()->model()->append( album );
}
ViewManager::instance()->showQueue();
}
void
ContextMenu::copyLink()
{
if ( m_queries.count() )
{
GlobalActionManager::instance()->copyToClipboard( m_queries.first() );
}
}

View File

@@ -0,0 +1,78 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CONTEXTMENU_H
#define CONTEXTMENU_H
#include <QSignalMapper>
#include <QMenu>
#include "typedefs.h"
#include "dllmacro.h"
namespace Tomahawk
{
class DLLEXPORT ContextMenu : public QMenu
{
Q_OBJECT
public:
enum MenuActions
{ ActionPlay = 1, ActionQueue = 2, ActionDelete = 4, ActionCopyLink = 8 };
explicit ContextMenu( QWidget* parent = 0 );
int supportedActions() const { return m_supportedActions; }
void setSupportedActions( int actions ) { m_supportedActions = actions; }
void setQuery( const Tomahawk::query_ptr& query );
void setQueries( const QList<Tomahawk::query_ptr>& queries );
void setArtist( const Tomahawk::artist_ptr& artist );
void setArtists( const QList<Tomahawk::artist_ptr>& artists );
void setAlbum( const Tomahawk::album_ptr& album );
void setAlbums( const QList<Tomahawk::album_ptr>& albums );
void clear();
unsigned int itemCount() const { return m_queries.count() + m_artists.count() + m_albums.count(); }
signals:
void triggered( int action );
private slots:
void onTriggered( int action );
void copyLink();
void addToQueue();
private:
QSignalMapper* m_sigmap;
int m_supportedActions;
QList<Tomahawk::query_ptr> m_queries;
QList<Tomahawk::artist_ptr> m_artists;
QList<Tomahawk::album_ptr> m_albums;
};
}; // ns
#endif

View File

@@ -69,6 +69,8 @@ private slots:
void setIsReadyTrue() { m_ready = true; }
private:
DatabaseImpl* impl() const { return m_impl; }
bool m_ready;
DatabaseImpl* m_impl;
DatabaseWorker* m_workerRW;
@@ -77,6 +79,8 @@ private:
int m_maxConcurrentThreads;
static Database* s_instance;
friend class Tomahawk::Artist;
};
#endif // DATABASE_H

View File

@@ -31,6 +31,7 @@
#include "databasecommand_deletedynamicplaylist.h"
#include "databasecommand_setdynamicplaylistrevision.h"
#include "databasecommand_socialaction.h"
#include "databasecommand_loadsocialactions.h"
DatabaseCommand::DatabaseCommand( QObject* parent )

View File

@@ -148,14 +148,16 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
if( !source()->isLocal() )
url = QString( "servent://%1\t%2" ).arg( source()->userName() ).arg( url );
bool isnew;
artistid = dbi->artistId( artist, isnew );
bool autoCreate = true;
artistid = dbi->artistId( artist, autoCreate );
if ( artistid < 1 )
continue;
trackid = dbi->trackId( artistid, track, isnew );
autoCreate = true; // artistId overwrites autoCreate (reference)
trackid = dbi->trackId( artistid, track, autoCreate );
if ( trackid < 1 )
continue;
albumid = dbi->albumId( artistid, album, isnew );
autoCreate = true; // trackId overwrites autoCreate (reference)
albumid = dbi->albumId( artistid, album, autoCreate );
// Now add the association
query_filejoin.bindValue( 0, fileid );

View File

@@ -0,0 +1,75 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christopher Reichert <creichert07@gmail.com>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (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 "databasecommand_loadsocialactions.h"
#include <QSqlQuery>
#include "database/database.h"
#include "databaseimpl.h"
#include "network/servent.h"
#include "result.h"
using namespace Tomahawk;
void
DatabaseCommand_LoadSocialActions::exec( DatabaseImpl* dbi )
{
qDebug() << Q_FUNC_INFO;
Q_ASSERT( !source().isNull() );
TomahawkSqlQuery query = dbi->newquery();
QVariant srcid = source()->isLocal() ? QVariant( QVariant::Int ) : source()->id();
bool autoCreate = true;
int artid = dbi->artistId( m_artist, autoCreate );
if( artid < 1 )
return;
autoCreate = true; // artistId overwrites autoCreate (reference)
int trkid = dbi->trackId( artid, m_track, autoCreate );
if( trkid < 1 )
return;
QString whereToken;
whereToken = QString( "WHERE id IS %1" ).arg( trkid );
QString sql = QString(
"SELECT k, v, timestamp, source "
"FROM social_attributes %1 "
"ORDER BY timestamp ASC" ).arg( whereToken );
query.prepare( sql );
query.exec();
QList< Tomahawk::SocialAction > allSocialActions;
while ( query.next() ) {
Tomahawk::SocialAction action;
action.action = query.value( 0 ); // action
action.value = query.value( 1 ); // comment
action.timestamp = query.value( 2 ); // timestamp
action.source = query.value( 3 ); // source
allSocialActions.append( action );
}
m_result->setAllSocialActions( allSocialActions );
}

View File

@@ -0,0 +1,73 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Christopher Reichert <creichert07@gmail.com>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (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 DATABASECOMMAND_LOADSOCIALACTIONS_H
#define DATABASECOMMAND_LOADSOCIALACTIONS_H
#include <QDateTime>
#include <QList>
#include "database/databasecommand.h"
#include "sourcelist.h"
#include "typedefs.h"
#include "artist.h"
#include "result.h"
#include "dllmacro.h"
class DLLEXPORT DatabaseCommand_LoadSocialActions : public DatabaseCommand
{
Q_OBJECT
public:
explicit DatabaseCommand_LoadSocialActions( QObject* parent = 0 )
: DatabaseCommand( parent )
{}
explicit DatabaseCommand_LoadSocialActions( Tomahawk::Result* result, QObject* parent = 0 )
: DatabaseCommand( parent ), m_result( result )
{
setSource( SourceList::instance()->getLocal() );
setArtist( result->artist()->name() );
setTrack( result->track() );
}
virtual QString commandname() const { return "loadsocialactions"; }
virtual void exec( DatabaseImpl* );
QString artist() const { return m_artist; }
void setArtist( const QString& s ) { m_artist = s; }
QString track() const { return m_track; }
void setTrack( const QString& s ) { m_track = s; }
signals:
void done( QList< Tomahawk::SocialAction >& allSocialActions );
private:
Tomahawk::Result* m_result;
QString m_artist;
QString m_track;
};
#endif // DATABASECOMMAND_LOADSOCIALACTIONS_H

View File

@@ -40,7 +40,7 @@ DatabaseCommand_LogPlayback::postCommitHook()
// do not auto resolve this track
Tomahawk::query_ptr q = Tomahawk::Query::get( m_artist, m_track, QString() );
q->setPlayedBy( source() );
q->setPlayedBy( source(), m_playtime );
if ( m_action == Finished )
{
@@ -80,12 +80,13 @@ DatabaseCommand_LogPlayback::exec( DatabaseImpl* dbi )
query.bindValue( 0, srcid );
bool isnew;
int artid = dbi->artistId( m_artist, isnew );
bool autoCreate = true;
int artid = dbi->artistId( m_artist, autoCreate );
if( artid < 1 )
return;
int trkid = dbi->trackId( artid, m_track, isnew );
autoCreate = true; // artistId overwrites autoCreate (reference)
int trkid = dbi->trackId( artid, m_track, autoCreate );
if( trkid < 1 )
return;

View File

@@ -67,11 +67,11 @@ DatabaseCommand_PlaybackHistory::exec( DatabaseImpl* dbi )
if ( query.value( 3 ).toUInt() == 0 )
{
q->setPlayedBy( SourceList::instance()->getLocal() );
q->setPlayedBy( SourceList::instance()->getLocal(), query.value( 1 ).toUInt() );
}
else
{
q->setPlayedBy( SourceList::instance()->get( query.value( 3 ).toUInt() ) );
q->setPlayedBy( SourceList::instance()->get( query.value( 3 ).toUInt() ), query.value( 1 ).toUInt() );
}
ql << q;

View File

@@ -51,12 +51,13 @@ DatabaseCommand_SocialAction::exec( DatabaseImpl* dbi )
QVariant srcid = source()->isLocal() ? QVariant( QVariant::Int ) : source()->id();
bool isnew;
int artid = dbi->artistId( m_artist, isnew );
bool autoCreate = true;
int artid = dbi->artistId( m_artist, autoCreate );
if( artid < 1 )
return;
int trkid = dbi->trackId( artid, m_track, isnew );
autoCreate = true; // artistId overwrites autoCreate (reference)
int trkid = dbi->trackId( artid, m_track, autoCreate );
if( trkid < 1 )
return;

View File

@@ -28,7 +28,17 @@
#include "dllmacro.h"
/**
* \class DatabaseCommand_SocialAction
* \brief Database command used to write social actions to database.
*
* This Database command allows Tomahawk to write social actions to
* the local database. These social actions can be interfaced with social
* networking API's such as LastFm, Facebook, or Twitter to allow the user
* to sync these actions with their accounts on these sites.
*
* \see DatabaseCommand_LoadSocialAction
*/
class DLLEXPORT DatabaseCommand_SocialAction : public DatabaseCommand
{
Q_OBJECT
@@ -38,10 +48,24 @@ Q_PROPERTY( int timestamp READ timestamp WRITE setTimestamp )
public:
/**
* \brief Default constructor for DatabaseCommand_SocialAction.
*
* Constructs an empty database command for a social action.
*/
explicit DatabaseCommand_SocialAction( QObject* parent = 0 )
: DatabaseCommand( parent )
{}
/**
* \brief Overloaded constructor for DatabaseCommand_SocialAction.
* \param result Pointer to a Tomahawk::Result.
* \param action Name of the social action to be written to the database.
* \param comment Comment associated with this social action.
* \param parent Parent class.
*
* Constructor which creates a new database command for the specified social action.
*/
explicit DatabaseCommand_SocialAction( const Tomahawk::result_ptr& result, QString action, QString comment="", QObject* parent = 0 )
: DatabaseCommand( parent ), m_result( result ), m_action( action )
{
@@ -53,26 +77,94 @@ public:
setTimestamp( QDateTime::currentDateTime().toTime_t() );
}
/**
* \brief Returns the name of this database command.
* \return QString containing the database command name 'socialaction'.
*/
virtual QString commandname() const { return "socialaction"; }
virtual void exec( DatabaseImpl* );
/**
* \brief Executes the database command.
* \param dbi Database instance.
*
* This method prepares an sql query to write this social action
* into the local database.
*/
virtual void exec( DatabaseImpl* dbi );
/**
* \brief Triggers a Database Sync.
*/
virtual void postCommitHook();
/**
* \brief Returns the artist associated with this database command.
* \return Name of the artist.
* \see setArtist()
*/
QString artist() const { return m_artist; }
/**
* \brief Sets the artist name for this database command.
* \param s QString containing the artist name.
* \see artist()
*/
void setArtist( const QString& s ) { m_artist = s; }
/**
* \brief Returns the track name associated with this social action.
* \return QString containing the track name.
* \see setTrack()
*/
QString track() const { return m_track; }
void setTrack( const QString& s ) { m_track = s; }
// key
/**
* \brief Sets the track name associated with this database command.
* \param track QString containing the track name.
* \see track()
*/
void setTrack( const QString& track ) { m_track = track; }
/**
* \brief Returns the social action for this database command instance.
* \return QString containing the action name.
* \see setAction()
*/
QString action() const { return m_action; }
/**
* \brief Sets the social actions
* \param a QString containing action to be set in this class.
* \see action()
*/
void setAction( QString a ) { m_action = a; }
// value
/**
* \brief Returns comment associated with this social action.
* \return QString containing comment associated with this social action.
* \see setComment()
*/
QString comment() const { return m_comment; }
/**
* \brief Sets the comment associated with this social action.
* \param com Comment associated with this social action.
* \see comment()
*/
void setComment( const QString& com ) { m_comment = com; }
/**
* \brief Returns the timestamp associated with this social action.
* \return unsigned integer containing timestamp
* \see setTimesetamp()
*/
int timestamp() const { return m_timestamp; }
/**
* \brief Sets the timestamp associated with this social action.
* \param ts unsigned integer associated with this social action.
* \see timestamp()
*/
void setTimestamp( const int ts ) { m_timestamp = ts; }
private:

View File

@@ -38,7 +38,7 @@
*/
#include "schema.sql.h"
#define CURRENT_SCHEMA_VERSION 24
#define CURRENT_SCHEMA_VERSION 25
DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent )
@@ -149,10 +149,10 @@ DatabaseImpl::updateSchema( int oldVersion )
QStringList statements = sql.split( ";", QString::SkipEmptyParts );
db.transaction();
foreach( const QString& sl, statements )
foreach ( const QString& sl, statements )
{
QString s( sl.trimmed() );
if( s.length() == 0 )
if ( s.length() == 0 )
continue;
qDebug() << "Executing:" << s;
@@ -173,18 +173,18 @@ DatabaseImpl::updateSchema( int oldVersion )
QString path = QString( RESPATH "sql/dbmigrate-%1_to_%2.sql" ).arg( cur - 1 ).arg( cur );
QFile script( path );
if( !script.exists() || !script.open( QIODevice::ReadOnly ) )
if ( !script.exists() || !script.open( QIODevice::ReadOnly ) )
{
qWarning() << "Failed to find or open upgrade script from" << (cur-1) << "to" << cur << " (" << path << ")! Aborting upgrade..";
qWarning() << "Failed to find or open upgrade script from" << (cur-1) << "to" << cur << " (" << path << ")! Aborting upgrade...";
return false;
}
QString sql = QString::fromUtf8( script.readAll() ).trimmed();
QStringList statements = sql.split( ";", QString::SkipEmptyParts );
foreach( const QString& sql, statements )
foreach ( const QString& sql, statements )
{
QString clean = cleanSql( sql ).trimmed();
if( clean.isEmpty() )
if ( clean.isEmpty() )
continue;
qDebug() << "Executing upgrade statement:" << clean;
@@ -224,7 +224,7 @@ DatabaseImpl::file( int fid )
"WHERE file.id = file_join.file AND file.id = %1" )
.arg( fid ) );
if( query.next() )
if ( query.next() )
{
Tomahawk::source_ptr s;
@@ -266,10 +266,10 @@ DatabaseImpl::file( int fid )
int
DatabaseImpl::artistId( const QString& name_orig, bool& isnew )
DatabaseImpl::artistId( const QString& name_orig, bool& autoCreate )
{
isnew = false;
if( m_lastart == name_orig )
bool isnew = false;
if ( m_lastart == name_orig )
return m_lastartid;
int id = 0;
@@ -279,22 +279,24 @@ DatabaseImpl::artistId( const QString& name_orig, bool& isnew )
query.prepare( "SELECT id FROM artist WHERE sortname = ?" );
query.addBindValue( sortname );
query.exec();
if( query.next() )
if ( query.next() )
{
id = query.value( 0 ).toInt();
}
if( id )
if ( id )
{
m_lastart = name_orig;
m_lastartid = id;
return id;
}
if ( autoCreate )
{
// not found, insert it.
query.prepare( "INSERT INTO artist(id,name,sortname) VALUES(NULL,?,?)" );
query.addBindValue( name_orig );
query.addBindValue( sortname );
if( !query.exec() )
if ( !query.exec() )
{
qDebug() << "Failed to insert artist:" << name_orig;
return 0;
@@ -304,6 +306,9 @@ DatabaseImpl::artistId( const QString& name_orig, bool& isnew )
isnew = true;
m_lastart = name_orig;
m_lastartid = id;
}
autoCreate = isnew;
return id;
}

View File

@@ -53,7 +53,7 @@ public:
TomahawkSqlQuery newquery() { return TomahawkSqlQuery( db ); }
QSqlDatabase& database() { return db; }
int artistId( const QString& name_orig, bool& isnew );
int artistId( const QString& name_orig, bool& autoCreate );
int trackId( int artistid, const QString& name_orig, bool& isnew );
int albumId( int artistid, const QString& name_orig, bool& isnew );

View File

@@ -106,7 +106,7 @@ CREATE TABLE IF NOT EXISTS playlist_revision (
-- VALUES('revisionguid-11', 'dynamic_playlist-guid-2', '[]');
CREATE TABLE IF NOT EXISTS dynamic_playlist (
guid TEXT PRIMARY KEY,
guid TEXT NOT NULL REFERENCES playlist(guid) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,
pltype TEXT, -- the generator type
plmode INTEGER -- the mode of this playlist
);
@@ -282,4 +282,4 @@ CREATE TABLE IF NOT EXISTS settings (
v TEXT NOT NULL DEFAULT ''
);
INSERT INTO settings(k,v) VALUES('schema_version', '24');
INSERT INTO settings(k,v) VALUES('schema_version', '25');

View File

@@ -1,5 +1,5 @@
/*
This file was automatically generated from ./schema.sql on Sun Jun 12 05:17:25 CEST 2011.
This file was automatically generated from ./schema.sql on Fri Jun 24 09:10:23 CEST 2011.
*/
static const char * tomahawk_schema_sql =
@@ -76,7 +76,7 @@ static const char * tomahawk_schema_sql =
" previous_revision TEXT REFERENCES playlist_revision(guid) DEFERRABLE INITIALLY DEFERRED"
");"
"CREATE TABLE IF NOT EXISTS dynamic_playlist ("
" guid TEXT PRIMARY KEY,"
" guid TEXT NOT NULL REFERENCES playlist(guid) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,"
" pltype TEXT, "
" plmode INTEGER "
");"
@@ -183,7 +183,7 @@ static const char * tomahawk_schema_sql =
" k TEXT NOT NULL PRIMARY KEY,"
" v TEXT NOT NULL DEFAULT ''"
");"
"INSERT INTO settings(k,v) VALUES('schema_version', '24');"
"INSERT INTO settings(k,v) VALUES('schema_version', '25');"
;
const char * get_tomahawk_sql()

View File

@@ -20,6 +20,10 @@
#include <echonest/Artist.h>
#include <echonest/ArtistTypes.h>
#include "utils/tomahawkutils.h"
#include <QNetworkConfiguration>
using namespace Tomahawk::InfoSystem;
using namespace Echonest;
@@ -44,42 +48,55 @@ EchoNestPlugin::namChangedSlot( QNetworkAccessManager *nam )
if( !nam )
return;
m_nam = QWeakPointer< QNetworkAccessManager >( nam );
Echonest::Config::instance()->setNetworkAccessManager( nam );
QNetworkAccessManager* currNam = Echonest::Config::instance()->nam();
TomahawkUtils::NetworkProxyFactory* oldProxyFactory = dynamic_cast< TomahawkUtils::NetworkProxyFactory* >( nam->proxyFactory() );
if ( !oldProxyFactory )
{
qDebug() << "Could not get old proxyFactory!";
return;
}
currNam->setConfiguration( nam->configuration() );
currNam->setNetworkAccessible( nam->networkAccessible() );
TomahawkUtils::NetworkProxyFactory* newProxyFactory = new TomahawkUtils::NetworkProxyFactory();
newProxyFactory->setNoProxyHosts( oldProxyFactory->noProxyHosts() );
newProxyFactory->setProxy( oldProxyFactory->proxy() );
currNam->setProxyFactory( newProxyFactory );
}
void
EchoNestPlugin::getInfo(const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData)
EchoNestPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
{
switch (type)
switch ( requestData.type )
{
case Tomahawk::InfoSystem::InfoArtistBiography:
return getArtistBiography(caller, input, customData);
return getArtistBiography( requestId, requestData );
case Tomahawk::InfoSystem::InfoArtistFamiliarity:
return getArtistFamiliarity(caller, input, customData);
return getArtistFamiliarity( requestId, requestData );
case Tomahawk::InfoSystem::InfoArtistHotttness:
return getArtistHotttnesss(caller, input, customData);
return getArtistHotttnesss( requestId, requestData );
case Tomahawk::InfoSystem::InfoArtistTerms:
return getArtistTerms(caller, input, customData);
return getArtistTerms( requestId, requestData );
case Tomahawk::InfoSystem::InfoTrackEnergy:
return getSongProfile(caller, input, customData, "energy");
return getSongProfile( requestId, requestData, "energy" );
case Tomahawk::InfoSystem::InfoMiscTopTerms:
return getMiscTopTerms(caller, input, customData);
return getMiscTopTerms( requestId, requestData );
default:
{
emit info(caller, Tomahawk::InfoSystem::InfoNoInfo, QVariant(), QVariant(), customData);
emit info( requestId, requestData, QVariant() );
return;
}
}
}
void
EchoNestPlugin::getSongProfile(const QString &caller, const QVariant &input, const InfoCustomData &customData, const QString &item)
EchoNestPlugin::getSongProfile( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData, const QString &item )
{
//WARNING: Totally not implemented yet
Q_UNUSED( item );
if( !isValidTrackData( caller, input, customData ) )
if( !isValidTrackData( requestId, requestData ) )
return;
// Track track( input.toString() );
@@ -91,74 +108,69 @@ EchoNestPlugin::getSongProfile(const QString &caller, const QVariant &input, con
}
void
EchoNestPlugin::getArtistBiography(const QString &caller, const QVariant &input, const InfoCustomData &customData)
EchoNestPlugin::getArtistBiography( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData )
{
if( !isValidArtistData( caller, input, customData ) )
if( !isValidArtistData( requestId, requestData ) )
return;
Echonest::Artist artist( input.toString() );
Echonest::Artist artist( requestData.input.toString() );
QNetworkReply *reply = artist.fetchBiographies();
reply->setProperty("artist", QVariant::fromValue<Echonest::Artist>(artist));
reply->setProperty( "input", input );
m_replyMap[reply] = customData;
m_callerMap[reply] = caller;
connect(reply, SIGNAL(finished()), SLOT(getArtistBiographySlot()));
reply->setProperty( "artist", QVariant::fromValue< Echonest::Artist >( artist ) );
reply->setProperty( "requestId", requestId );
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
connect( reply, SIGNAL( finished() ), SLOT( getArtistBiographySlot() ) );
}
void
EchoNestPlugin::getArtistFamiliarity(const QString &caller, const QVariant &input, const InfoCustomData &customData)
EchoNestPlugin::getArtistFamiliarity( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData )
{
if( !isValidArtistData( caller, input, customData ) )
if( !isValidArtistData( requestId, requestData ) )
return;
qDebug() << "Fetching artist familiarity!" << input;
Echonest::Artist artist( input.toString() );
qDebug() << "Fetching artist familiarity!" << requestData.input;
Echonest::Artist artist( requestData.input.toString() );
QNetworkReply* reply = artist.fetchFamiliarity();
reply->setProperty( "artist", QVariant::fromValue<Echonest::Artist>(artist));
reply->setProperty( "input", input );
m_replyMap[reply] = customData;
m_callerMap[reply] = caller;
connect(reply, SIGNAL(finished()), SLOT(getArtistFamiliaritySlot()));
reply->setProperty( "artist", QVariant::fromValue< Echonest::Artist >( artist ) );
reply->setProperty( "requestId", requestId );
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
connect( reply, SIGNAL( finished() ), SLOT( getArtistFamiliaritySlot() ) );
}
void
EchoNestPlugin::getArtistHotttnesss(const QString &caller, const QVariant &input, const InfoCustomData &customData)
EchoNestPlugin::getArtistHotttnesss( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData )
{
if( !isValidArtistData( caller, input, customData ) )
if( !isValidArtistData( requestId, requestData ) )
return;
Echonest::Artist artist( input.toString() );
Echonest::Artist artist( requestData.input.toString() );
QNetworkReply* reply = artist.fetchHotttnesss();
reply->setProperty( "artist", QVariant::fromValue<Echonest::Artist>(artist));
reply->setProperty( "input", input );
m_replyMap[reply] = customData;
m_callerMap[reply] = caller;
connect(reply, SIGNAL(finished()), SLOT(getArtistHotttnesssSlot()));
reply->setProperty( "artist", QVariant::fromValue< Echonest::Artist >( artist ) );
reply->setProperty( "requestId", requestId );
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
connect( reply, SIGNAL( finished() ), SLOT( getArtistHotttnesssSlot() ) );
}
void
EchoNestPlugin::getArtistTerms(const QString &caller, const QVariant &input, const InfoCustomData &customData)
EchoNestPlugin::getArtistTerms( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData )
{
if( !isValidArtistData( caller, input, customData ) )
if( !isValidArtistData( requestId, requestData ) )
return;
Echonest::Artist artist( input.toString() );
Echonest::Artist artist( requestData.input.toString() );
QNetworkReply* reply = artist.fetchTerms( Echonest::Artist::Weight );
reply->setProperty( "artist", QVariant::fromValue<Echonest::Artist>(artist));
reply->setProperty( "input", input );
m_replyMap[reply] = customData;
m_callerMap[reply] = caller;
connect(reply, SIGNAL(finished()), SLOT(getArtistTermsSlot()));
reply->setProperty( "artist", QVariant::fromValue< Echonest::Artist >( artist ) );
reply->setProperty( "requestId", requestId );
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
connect( reply, SIGNAL( finished() ), SLOT( getArtistTermsSlot() ) );
}
void
EchoNestPlugin::getMiscTopTerms(const QString &caller, const QVariant &input, const InfoCustomData& customData)
EchoNestPlugin::getMiscTopTerms( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData )
{
Q_UNUSED( input );
QNetworkReply* reply = Echonest::Artist::topTerms( 20 );
m_replyMap[reply] = customData;
m_callerMap[reply] = caller;
connect( reply,SIGNAL(finished()), SLOT( getMiscTopSlot()));
reply->setProperty( "requestId", requestId );
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
connect( reply, SIGNAL( finished() ), SLOT( getMiscTopSlot() ) );
}
@@ -179,9 +191,10 @@ EchoNestPlugin::getArtistBiographySlot()
biographyMap[biography.site()]["attribution"] = biography.license().url.toString();
}
emit info( m_callerMap[reply], Tomahawk::InfoSystem::InfoArtistBiography, reply->property( "input" ), QVariant::fromValue<Tomahawk::InfoSystem::InfoGenericMap>(biographyMap), m_replyMap[reply] );
m_replyMap.remove(reply);
m_callerMap.remove(reply);
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
emit info( reply->property( "requestId" ).toUInt(),
requestData,
QVariant::fromValue< Tomahawk::InfoSystem::InfoGenericMap >( biographyMap ) );
reply->deleteLater();
}
@@ -191,9 +204,10 @@ EchoNestPlugin::getArtistFamiliaritySlot()
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
Echonest::Artist artist = artistFromReply( reply );
qreal familiarity = artist.familiarity();
emit info( m_callerMap[reply], Tomahawk::InfoSystem::InfoArtistFamiliarity, reply->property( "input" ), familiarity, m_replyMap[reply] );
m_replyMap.remove(reply);
m_callerMap.remove(reply);
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
emit info( reply->property( "requestId" ).toUInt(),
requestData,
familiarity );
reply->deleteLater();
}
@@ -203,9 +217,10 @@ EchoNestPlugin::getArtistHotttnesssSlot()
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
Echonest::Artist artist = artistFromReply( reply );
qreal hotttnesss = artist.hotttnesss();
emit info( m_callerMap[reply], Tomahawk::InfoSystem::InfoArtistHotttness, reply->property( "input" ), hotttnesss, m_replyMap[reply] );
m_replyMap.remove(reply);
m_callerMap.remove(reply);
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
emit info( reply->property( "requestId" ).toUInt(),
requestData,
hotttnesss );
reply->deleteLater();
}
@@ -222,9 +237,10 @@ EchoNestPlugin::getArtistTermsSlot()
termMap[ "frequency" ] = QString::number(term.frequency());
termsMap[ term.name() ] = termMap;
}
emit info( m_callerMap[reply], Tomahawk::InfoSystem::InfoArtistTerms, reply->property( "input" ), QVariant::fromValue<Tomahawk::InfoSystem::InfoGenericMap>(termsMap), m_replyMap[reply] );
m_replyMap.remove(reply);
m_callerMap.remove(reply);
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
emit info( reply->property( "requestId" ).toUInt(),
requestData,
QVariant::fromValue< Tomahawk::InfoSystem::InfoGenericMap >( termsMap ) );
reply->deleteLater();
}
@@ -240,57 +256,61 @@ EchoNestPlugin::getMiscTopSlot()
termMap[ "frequency" ] = QString::number( term.frequency() );
termsMap[ term.name().toLower() ] = termMap;
}
emit info( m_callerMap[reply], Tomahawk::InfoSystem::InfoMiscTopTerms, QVariant(), QVariant::fromValue<Tomahawk::InfoSystem::InfoGenericMap>(termsMap), m_replyMap[reply] );
m_replyMap.remove(reply);
m_callerMap.remove(reply);
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
emit info( reply->property( "requestId" ).toUInt(),
requestData,
QVariant::fromValue< Tomahawk::InfoSystem::InfoGenericMap >( termsMap ) );
reply->deleteLater();
}
bool
EchoNestPlugin::isValidArtistData(const QString &caller, const QVariant &input, const InfoCustomData &customData)
EchoNestPlugin::isValidArtistData( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData )
{
if (input.isNull() || !input.isValid() || !input.canConvert<QString>())
if ( requestData.input.isNull() || !requestData.input.isValid() || !requestData.input.canConvert< QString >() )
{
emit info(caller, Tomahawk::InfoSystem::InfoNoInfo, QVariant(), QVariant(), customData);
emit info( requestId, requestData, QVariant() );
return false;
}
QString artistName = input.toString();
if (artistName.isEmpty() )
QString artistName = requestData.input.toString();
if ( artistName.isEmpty() )
{
emit info(caller, Tomahawk::InfoSystem::InfoNoInfo, QVariant(), QVariant(), customData);
emit info( requestId, requestData, QVariant() );
return false;
}
return true;
}
bool
EchoNestPlugin::isValidTrackData(const QString &caller, const QVariant &input, const InfoCustomData &customData)
EchoNestPlugin::isValidTrackData( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData )
{
if (input.isNull() || !input.isValid() || !input.canConvert<QString>())
if ( requestData.input.isNull() || !requestData.input.isValid() || !requestData.input.canConvert< QString >() )
{
emit info(caller, Tomahawk::InfoSystem::InfoNoInfo, QVariant(), QVariant(), customData);
emit info( requestId, requestData, QVariant() );
return false;
}
QString trackName = input.toString();
if (trackName.isEmpty() )
QString trackName = requestData.input.toString();
if ( trackName.isEmpty() )
{
emit info(caller, Tomahawk::InfoSystem::InfoNoInfo, QVariant(), QVariant(), customData);
emit info( requestId, requestData, QVariant() );
return false;
}
if (!customData.contains("artistName") ||
customData["artistName"].toString().isEmpty())
if ( !requestData.customData.contains( "artistName" ) || requestData.customData[ "artistName" ].toString().isEmpty() )
{
emit info( requestId, requestData, QVariant() );
return false;
}
return true;
}
Artist
EchoNestPlugin::artistFromReply(QNetworkReply* reply)
EchoNestPlugin::artistFromReply( QNetworkReply* reply )
{
Echonest::Artist artist = reply->property("artist").value<Echonest::Artist>();
try {
artist.parseProfile(reply);
artist.parseProfile( reply );
} catch( const Echonest::ParseError& e ) {
qWarning() << "Caught parser error from echonest!" << e.what();
}
return artist;
}
//

View File

@@ -44,7 +44,7 @@ public:
virtual ~EchoNestPlugin();
protected slots:
virtual void getInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData );
virtual void getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant data )
{
@@ -53,28 +53,26 @@ protected slots:
Q_UNUSED( data );
}
virtual void notInCacheSlot( const Tomahawk::InfoSystem::InfoCriteriaHash criteria, const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData )
virtual void notInCacheSlot( uint requestId, Tomahawk::InfoSystem::InfoCriteriaHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
{
Q_UNUSED( requestId );
Q_UNUSED( criteria );
Q_UNUSED( caller );
Q_UNUSED( type );
Q_UNUSED( input );
Q_UNUSED( customData );
Q_UNUSED( requestData );
}
public slots:
void namChangedSlot( QNetworkAccessManager *nam );
private:
void getSongProfile( const QString &caller, const QVariant &input, const InfoCustomData &customData, const QString &item = QString() );
void getArtistBiography ( const QString &caller, const QVariant &input, const InfoCustomData &customData );
void getArtistFamiliarity( const QString &caller, const QVariant &input, const InfoCustomData &customData );
void getArtistHotttnesss( const QString &caller, const QVariant &input, const InfoCustomData &customData );
void getArtistTerms( const QString &caller, const QVariant &input, const InfoCustomData &customData );
void getMiscTopTerms( const QString &caller, const QVariant &input, const InfoCustomData &customData );
void getSongProfile( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData, const QString &item = QString() );
void getArtistBiography( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData );
void getArtistFamiliarity( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData );
void getArtistHotttnesss( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData );
void getArtistTerms( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData );
void getMiscTopTerms( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData );
bool isValidArtistData( const QString &caller, const QVariant &input, const InfoCustomData& customData );
bool isValidTrackData( const QString &caller, const QVariant &input, const InfoCustomData& customData );
bool isValidArtistData( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData );
bool isValidTrackData( uint requestId, const Tomahawk::InfoSystem::InfoRequestData &requestData );
Echonest::Artist artistFromReply( QNetworkReply* );
private slots:
@@ -83,11 +81,6 @@ private slots:
void getArtistHotttnesssSlot();
void getArtistTermsSlot();
void getMiscTopSlot();
private:
QHash< QNetworkReply*, InfoCustomData > m_replyMap;
QHash< QNetworkReply*, QString > m_callerMap;
QWeakPointer< QNetworkAccessManager > m_nam;
};
}

View File

@@ -21,6 +21,7 @@
#include <QDir>
#include <QSettings>
#include <QCryptographicHash>
#include <QNetworkConfiguration>
#include "album.h"
#include "typedefs.h"
@@ -45,8 +46,8 @@ LastFmPlugin::LastFmPlugin()
: InfoPlugin()
, m_scrobbler( 0 )
{
m_supportedGetTypes << InfoAlbumCoverArt << InfoArtistImages << InfoLove;
m_supportedPushTypes << InfoSubmitScrobble << InfoSubmitNowPlaying << InfoLove;
m_supportedGetTypes << InfoAlbumCoverArt << InfoArtistImages << InfoArtistSimilars << InfoArtistSongs;
m_supportedPushTypes << InfoSubmitScrobble << InfoSubmitNowPlaying << InfoLove << InfoUnLove;
/*
Your API Key is 7194b85b6d1f424fe1668173a78c0c4a
@@ -93,39 +94,64 @@ void
LastFmPlugin::namChangedSlot( QNetworkAccessManager *nam )
{
qDebug() << Q_FUNC_INFO;
if( !nam )
if ( !nam )
return;
m_nam = QWeakPointer< QNetworkAccessManager >( nam );
QNetworkAccessManager* currNam = lastfm::nam();
TomahawkUtils::NetworkProxyFactory* oldProxyFactory = dynamic_cast< TomahawkUtils::NetworkProxyFactory* >( nam->proxyFactory() );
if ( !oldProxyFactory )
{
qDebug() << "Could not get old proxyFactory!";
return;
}
currNam->setConfiguration( nam->configuration() );
currNam->setNetworkAccessible( nam->networkAccessible() );
TomahawkUtils::NetworkProxyFactory* newProxyFactory = new TomahawkUtils::NetworkProxyFactory();
newProxyFactory->setNoProxyHosts( oldProxyFactory->noProxyHosts() );
newProxyFactory->setProxy( oldProxyFactory->proxy() );
currNam->setProxyFactory( newProxyFactory );
//FIXME: on Mac/Win as liblastfm's network access manager also sets its overriding application proxy
//may have to do a QNetworkProxy::setApplicationProxy and clobber our own factory to override it
settingsChanged(); // to get the scrobbler set up
}
void
LastFmPlugin::dataError( const QString &caller, const Tomahawk::InfoSystem::InfoType type, const QVariant &input, const Tomahawk::InfoSystem::InfoCustomData &customData )
LastFmPlugin::dataError( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
{
emit info( caller, type, input, QVariant(), customData );
emit info( requestId, requestData, QVariant() );
return;
}
void
LastFmPlugin::getInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData )
LastFmPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
{
qDebug() << Q_FUNC_INFO;
switch ( type )
switch ( requestData.type )
{
case InfoArtistImages:
fetchArtistImages( caller, type, input, customData );
fetchArtistImages( requestId, requestData );
break;
case InfoAlbumCoverArt:
fetchCoverArt( caller, type, input, customData );
fetchCoverArt( requestId, requestData );
break;
case InfoArtistSimilars:
fetchSimilarArtists( requestId, requestData );
break;
case InfoArtistSongs:
fetchTopTracks( requestId, requestData );
break;
default:
dataError( caller, type, input, customData );
dataError( requestId, requestData );
}
}
@@ -146,7 +172,8 @@ LastFmPlugin::pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoTy
break;
case InfoLove:
sendLoveSong( input );
case InfoUnLove:
sendLoveSong( type, input );
break;
default:
@@ -171,7 +198,6 @@ LastFmPlugin::nowPlaying( const QVariant &input )
if ( !hash.contains( "title" ) || !hash.contains( "artist" ) || !hash.contains( "album" ) || !hash.contains( "duration" ) )
return;
qDebug() << "LastFmPlugin::nowPlaying valid criteria hash";
m_track = lastfm::MutableTrack();
m_track.stamp();
@@ -201,7 +227,7 @@ LastFmPlugin::scrobble()
void
LastFmPlugin::sendLoveSong( QVariant input )
LastFmPlugin::sendLoveSong( const InfoType type, QVariant input )
{
qDebug() << Q_FUNC_INFO;
@@ -224,23 +250,77 @@ LastFmPlugin::sendLoveSong( QVariant input )
bool ok;
track.setDuration( hash["duration"].toUInt( &ok ) );
track.setSource( lastfm::Track::Player );
if ( type == Tomahawk::InfoSystem::InfoLove )
{
track.love();
}
else if ( type == Tomahawk::InfoSystem::InfoUnLove )
{
track.unlove();
}
}
void
LastFmPlugin::fetchCoverArt( const QString &caller, const InfoType type, const QVariant &input, const Tomahawk::InfoSystem::InfoCustomData &customData )
LastFmPlugin::fetchSimilarArtists( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
{
qDebug() << Q_FUNC_INFO;
if ( !input.canConvert< Tomahawk::InfoSystem::InfoCriteriaHash >() )
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoCriteriaHash >() )
{
dataError( caller, type, input, customData );
dataError( requestId, requestData );
return;
}
InfoCriteriaHash hash = input.value< Tomahawk::InfoSystem::InfoCriteriaHash >();
InfoCriteriaHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash >();
if ( !hash.contains( "artist" ) )
{
dataError( requestId, requestData );
return;
}
Tomahawk::InfoSystem::InfoCriteriaHash criteria;
criteria["artist"] = hash["artist"];
emit getCachedInfo( requestId, criteria, 2419200000, requestData );
}
void
LastFmPlugin::fetchTopTracks( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
{
qDebug() << Q_FUNC_INFO;
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoCriteriaHash >() )
{
dataError( requestId, requestData );
return;
}
InfoCriteriaHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash >();
if ( !hash.contains( "artist" ) )
{
dataError( requestId, requestData );
return;
}
Tomahawk::InfoSystem::InfoCriteriaHash criteria;
criteria["artist"] = hash["artist"];
emit getCachedInfo( requestId, criteria, 2419200000, requestData );
}
void
LastFmPlugin::fetchCoverArt( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
{
qDebug() << Q_FUNC_INFO;
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoCriteriaHash >() )
{
dataError( requestId, requestData );
return;
}
InfoCriteriaHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash >();
if ( !hash.contains( "artist" ) || !hash.contains( "album" ) )
{
dataError( caller, type, input, customData );
dataError( requestId, requestData );
return;
}
@@ -248,47 +328,69 @@ LastFmPlugin::fetchCoverArt( const QString &caller, const InfoType type, const Q
criteria["artist"] = hash["artist"];
criteria["album"] = hash["album"];
emit getCachedInfo( criteria, 2419200000, caller, type, input, customData );
emit getCachedInfo( requestId, criteria, 2419200000, requestData );
}
void
LastFmPlugin::fetchArtistImages( const QString &caller, const InfoType type, const QVariant &input, const Tomahawk::InfoSystem::InfoCustomData &customData )
LastFmPlugin::fetchArtistImages( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
{
qDebug() << Q_FUNC_INFO;
if ( !input.canConvert< Tomahawk::InfoSystem::InfoCriteriaHash >() )
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoCriteriaHash >() )
{
dataError( caller, type, input, customData );
dataError( requestId, requestData );
return;
}
InfoCriteriaHash hash = input.value< Tomahawk::InfoSystem::InfoCriteriaHash >();
InfoCriteriaHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash >();
if ( !hash.contains( "artist" ) )
{
dataError( caller, type, input, customData );
dataError( requestId, requestData );
return;
}
Tomahawk::InfoSystem::InfoCriteriaHash criteria;
criteria["artist"] = hash["artist"];
emit getCachedInfo( criteria, 2419200000, caller, type, input, customData );
emit getCachedInfo( requestId, criteria, 2419200000, requestData );
}
void
LastFmPlugin::notInCacheSlot( const QHash<QString, QString> criteria, const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData )
LastFmPlugin::notInCacheSlot( uint requestId, QHash<QString, QString> criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
{
qDebug() << Q_FUNC_INFO;
qDebug() << Q_FUNC_INFO << " for requestId " << requestId;
if ( m_nam.isNull() )
if ( !lastfm::nam() )
{
qDebug() << "Have a null QNAM, uh oh";
emit info( caller, type, input, QVariant(), customData );
emit info( requestId, requestData, QVariant() );
return;
}
switch ( type )
switch ( requestData.type )
{
case InfoArtistSimilars:
{
lastfm::Artist a( criteria["artist"] );
QNetworkReply* reply = a.getSimilar();
reply->setProperty( "requestId", requestId );
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
connect( reply, SIGNAL( finished() ), SLOT( similarArtistsReturned() ) );
return;
}
case InfoArtistSongs:
{
lastfm::Artist a( criteria["artist"] );
QNetworkReply* reply = a.getTopTracks();
reply->setProperty( "requestId", requestId );
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
connect( reply, SIGNAL( finished() ), SLOT( topTracksReturned() ) );
return;
}
case InfoAlbumCoverArt:
{
QString artistName = criteria["artist"];
@@ -296,11 +398,9 @@ LastFmPlugin::notInCacheSlot( const QHash<QString, QString> criteria, const QStr
QString imgurl = "http://ws.audioscrobbler.com/2.0/?method=album.imageredirect&artist=%1&album=%2&autocorrect=1&size=large&api_key=7a90f6672a04b809ee309af169f34b8b";
QNetworkRequest req( imgurl.arg( artistName ).arg( albumName ) );
QNetworkReply* reply = m_nam.data()->get( req );
reply->setProperty( "customData", QVariant::fromValue<Tomahawk::InfoSystem::InfoCustomData>( customData ) );
reply->setProperty( "origData", input );
reply->setProperty( "caller", caller );
reply->setProperty( "type", (uint)(type) );
QNetworkReply* reply = lastfm::nam()->get( req );
reply->setProperty( "requestId", requestId );
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
connect( reply, SIGNAL( finished() ), SLOT( coverArtReturned() ) );
return;
@@ -310,13 +410,11 @@ LastFmPlugin::notInCacheSlot( const QHash<QString, QString> criteria, const QStr
{
QString artistName = criteria["artist"];
QString imgurl = "http://ws.audioscrobbler.com/2.0/?method=artist.imageredirect&artist=%1&autocorrect=1&size=medium&api_key=7a90f6672a04b809ee309af169f34b8b";
QString imgurl = "http://ws.audioscrobbler.com/2.0/?method=artist.imageredirect&artist=%1&autocorrect=1&size=large&api_key=7a90f6672a04b809ee309af169f34b8b";
QNetworkRequest req( imgurl.arg( artistName ) );
QNetworkReply* reply = m_nam.data()->get( req );
reply->setProperty( "customData", QVariant::fromValue<Tomahawk::InfoSystem::InfoCustomData>( customData ) );
reply->setProperty( "origData", input );
reply->setProperty( "caller", caller );
reply->setProperty( "type", (uint)(type) );
QNetworkReply* reply = lastfm::nam()->get( req );
reply->setProperty( "requestId", requestId );
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
connect( reply, SIGNAL( finished() ), SLOT( artistImagesReturned() ) );
return;
@@ -325,13 +423,78 @@ LastFmPlugin::notInCacheSlot( const QHash<QString, QString> criteria, const QStr
default:
{
qDebug() << "Couldn't figure out what to do with this type of request after cache miss";
emit info( caller, type, input, QVariant(), customData );
emit info( requestId, requestData, QVariant() );
return;
}
}
}
void
LastFmPlugin::similarArtistsReturned()
{
qDebug() << Q_FUNC_INFO;
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
QMap< int, QString > similarArtists = lastfm::Artist::getSimilar( reply );
QStringList al;
QStringList sl;
foreach ( const QString& a, similarArtists.values() )
{
qDebug() << "Got sim-artist:" << a;
al << a;
}
QVariantMap returnedData;
returnedData["artists"] = al;
returnedData["score"] = sl;
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
emit info(
reply->property( "requestId" ).toUInt(),
requestData,
returnedData
);
Tomahawk::InfoSystem::InfoCriteriaHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash>();
Tomahawk::InfoSystem::InfoCriteriaHash criteria;
criteria["artist"] = origData["artist"];
emit updateCache( criteria, 2419200000, requestData.type, returnedData );
}
void
LastFmPlugin::topTracksReturned()
{
qDebug() << Q_FUNC_INFO;
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
QStringList topTracks = lastfm::Artist::getTopTracks( reply );
foreach ( const QString& t, topTracks )
{
qDebug() << "Got top-track:" << t;
}
QVariantMap returnedData;
returnedData["tracks"] = topTracks;
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
emit info(
reply->property( "requestId" ).toUInt(),
requestData,
returnedData
);
Tomahawk::InfoSystem::InfoCriteriaHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash>();
Tomahawk::InfoSystem::InfoCriteriaHash criteria;
criteria["artist"] = origData["artist"];
emit updateCache( criteria, 2419200000, requestData.type, returnedData );
}
void
LastFmPlugin::coverArtReturned()
{
@@ -341,49 +504,49 @@ LastFmPlugin::coverArtReturned()
if ( redir.isEmpty() )
{
QByteArray ba = reply->readAll();
if ( ba.isNull() || !ba.length() )
{
qDebug() << "Uh oh, null byte array";
emit info( reply->property( "requestId" ).toUInt(), reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
return;
}
foreach ( const QUrl& url, m_badUrls )
{
if ( reply->url().toString().startsWith( url.toString() ) )
ba = QByteArray();
}
InfoCustomData returnedData;
QVariantMap returnedData;
returnedData["imgbytes"] = ba;
returnedData["url"] = reply->url().toString();
InfoCustomData customData = reply->property( "customData" ).value< Tomahawk::InfoSystem::InfoCustomData >();
InfoType type = (Tomahawk::InfoSystem::InfoType)(reply->property( "type" ).toUInt());
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
emit info(
reply->property( "caller" ).toString(),
type,
reply->property( "origData" ),
returnedData,
customData
reply->property( "requestId" ).toUInt(),
requestData,
returnedData
);
InfoCriteriaHash origData = reply->property( "origData" ).value< Tomahawk::InfoSystem::InfoCriteriaHash >();
Tomahawk::InfoSystem::InfoCriteriaHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash>();
Tomahawk::InfoSystem::InfoCriteriaHash criteria;
criteria["artist"] = origData["artist"];
criteria["album"] = origData["album"];
emit updateCache( criteria, 2419200000, type, returnedData );
emit updateCache( criteria, 2419200000, requestData.type, returnedData );
}
else
{
if ( m_nam.isNull() )
if ( !lastfm::nam() )
{
qDebug() << "Uh oh, nam is null";
InfoType type = (Tomahawk::InfoSystem::InfoType)(reply->property( "type" ).toUInt());
InfoCustomData customData = reply->property( "customData" ).value< Tomahawk::InfoSystem::InfoCustomData >();
emit info( reply->property( "caller" ).toString(), type, reply->property( "origData" ), QVariant(), customData );
emit info( reply->property( "requestId" ).toUInt(), reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
return;
}
// Follow HTTP redirect
QNetworkRequest req( redir );
QNetworkReply* newReply = m_nam.data()->get( req );
newReply->setProperty( "origData", reply->property( "origData" ) );
newReply->setProperty( "customData", reply->property( "customData" ) );
newReply->setProperty( "caller", reply->property( "caller" ) );
newReply->setProperty( "type", reply->property( "type" ) );
QNetworkReply* newReply = lastfm::nam()->get( req );
newReply->setProperty( "requestId", reply->property( "requestId" ) );
newReply->setProperty( "requestData", reply->property( "requestData" ) );
connect( newReply, SIGNAL( finished() ), SLOT( coverArtReturned() ) );
}
@@ -400,42 +563,43 @@ LastFmPlugin::artistImagesReturned()
if ( redir.isEmpty() )
{
QByteArray ba = reply->readAll();
if ( ba.isNull() || !ba.length() )
{
qDebug() << "Uh oh, null byte array";
emit info( reply->property( "requestId" ).toUInt(), reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
return;
}
foreach ( const QUrl& url, m_badUrls )
{
if ( reply->url().toString().startsWith( url.toString() ) )
ba = QByteArray();
}
InfoCustomData returnedData;
QVariantMap returnedData;
returnedData["imgbytes"] = ba;
returnedData["url"] = reply->url().toString();
InfoType type = (Tomahawk::InfoSystem::InfoType)(reply->property( "type" ).toUInt());
InfoCustomData customData = reply->property( "customData" ).value< Tomahawk::InfoSystem::InfoCustomData >();
emit info( reply->property( "caller" ).toString(), type, reply->property( "origData" ), returnedData, customData );
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
InfoCriteriaHash origData = reply->property( "origData" ).value< Tomahawk::InfoSystem::InfoCriteriaHash >();
emit info( reply->property( "requestId" ).toUInt(), requestData, returnedData );
Tomahawk::InfoSystem::InfoCriteriaHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash>();
Tomahawk::InfoSystem::InfoCriteriaHash criteria;
criteria["artist"] = origData["artist"];
emit updateCache( criteria, 2419200000, type, returnedData );
emit updateCache( criteria, 2419200000, requestData.type, returnedData );
}
else
{
if ( m_nam.isNull() )
if ( !lastfm::nam() )
{
qDebug() << "Uh oh, nam is null";
InfoType type = (Tomahawk::InfoSystem::InfoType)(reply->property( "type" ).toUInt());
InfoCustomData customData = reply->property( "customData" ).value< Tomahawk::InfoSystem::InfoCustomData >();
emit info( reply->property( "caller" ).toString(), type, reply->property( "origData" ), QVariant(), customData );
emit info( reply->property( "requestId" ).toUInt(), reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
return;
}
// Follow HTTP redirect
QNetworkRequest req( redir );
QNetworkReply* newReply = m_nam.data()->get( req );
newReply->setProperty( "origData", reply->property( "origData" ) );
newReply->setProperty( "customData", reply->property( "customData" ) );
newReply->setProperty( "caller", reply->property( "caller" ) );
newReply->setProperty( "type", reply->property( "type" ) );
QNetworkReply* newReply = lastfm::nam()->get( req );
newReply->setProperty( "requestId", reply->property( "requestId" ) );
newReply->setProperty( "requestData", reply->property( "requestData" ) );
connect( newReply, SIGNAL( finished() ), SLOT( artistImagesReturned() ) );
}

View File

@@ -49,33 +49,35 @@ public slots:
void onAuthenticated();
void coverArtReturned();
void artistImagesReturned();
void similarArtistsReturned();
void topTracksReturned();
void namChangedSlot( QNetworkAccessManager *nam );
protected slots:
virtual void getInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData );
virtual void notInCacheSlot( const Tomahawk::InfoSystem::InfoCriteriaHash criteria, const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData );
virtual void getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void notInCacheSlot( uint requestId, Tomahawk::InfoSystem::InfoCriteriaHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant data );
virtual void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant data );
private:
void fetchCoverArt( const QString &caller, const Tomahawk::InfoSystem::InfoType type, const QVariant &input, const Tomahawk::InfoSystem::InfoCustomData &customData );
void fetchArtistImages( const QString &caller, const Tomahawk::InfoSystem::InfoType type, const QVariant &input, const Tomahawk::InfoSystem::InfoCustomData &customData );
void fetchCoverArt( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
void fetchArtistImages( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
void fetchSimilarArtists( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
void fetchTopTracks( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
void createScrobbler();
void nowPlaying( const QVariant &input );
void scrobble();
void sendLoveSong( const InfoType type, QVariant input );
void dataError( const QString &caller, const Tomahawk::InfoSystem::InfoType type, const QVariant &input, const Tomahawk::InfoSystem::InfoCustomData &customData );
void sendLoveSong( QVariant input );
void dataError( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
lastfm::MutableTrack m_track;
lastfm::Audioscrobbler* m_scrobbler;
QString m_pw;
QList< QUrl > m_badUrls;
QWeakPointer< QNetworkAccessManager > m_nam;
};
}

View File

@@ -51,53 +51,52 @@ MusixMatchPlugin::namChangedSlot( QNetworkAccessManager *nam )
}
void
MusixMatchPlugin::getInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData )
MusixMatchPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
{
qDebug() << Q_FUNC_INFO;
if( !isValidTrackData(caller, input, customData) || !input.canConvert<Tomahawk::InfoSystem::InfoCustomData>() || m_nam.isNull() || type != Tomahawk::InfoSystem::InfoTrackLyrics )
if( !isValidTrackData( requestId, requestData ) || !requestData.input.canConvert< QVariantMap >() || m_nam.isNull() || requestData.type != Tomahawk::InfoSystem::InfoTrackLyrics )
return;
Tomahawk::InfoSystem::InfoCustomData hash = input.value<Tomahawk::InfoSystem::InfoCustomData>();
QVariantMap hash = requestData.input.value< QVariantMap >();
QString artist = hash["artistName"].toString();
QString track = hash["trackName"].toString();
if( artist.isEmpty() || track.isEmpty() )
{
emit info(caller, Tomahawk::InfoSystem::InfoTrackLyrics, input, QVariant(), customData);
emit info( requestId, requestData, QVariant() );
return;
}
qDebug() << "artist is " << artist << ", track is " << track;
QString requestString("http://api.musixmatch.com/ws/1.1/track.search?format=xml&page_size=1&f_has_lyrics=1");
QUrl url(requestString);
url.addQueryItem("apikey", m_apiKey);
url.addQueryItem("q_artist", artist);
url.addQueryItem("q_track", track);
QNetworkReply* reply = m_nam.data()->get(QNetworkRequest(url));
reply->setProperty("customData", QVariant::fromValue<Tomahawk::InfoSystem::InfoCustomData>(customData));
reply->setProperty("origData", input);
reply->setProperty("caller", caller);
QString requestString( "http://api.musixmatch.com/ws/1.1/track.search?format=xml&page_size=1&f_has_lyrics=1" );
QUrl url( requestString );
url.addQueryItem( "apikey", m_apiKey );
url.addQueryItem( "q_artist", artist );
url.addQueryItem( "q_track", track );
QNetworkReply* reply = m_nam.data()->get( QNetworkRequest( url ) );
reply->setProperty( "requestId", requestId );
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
connect(reply, SIGNAL(finished()), SLOT(trackSearchSlot()));
connect( reply, SIGNAL( finished() ), SLOT( trackSearchSlot() ) );
}
bool
MusixMatchPlugin::isValidTrackData( const QString &caller, const QVariant &input, const Tomahawk::InfoSystem::InfoCustomData &customData )
MusixMatchPlugin::isValidTrackData( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
{
qDebug() << Q_FUNC_INFO;
if (input.isNull() || !input.isValid() || !input.canConvert<Tomahawk::InfoSystem::InfoCustomData>())
if ( requestData.input.isNull() || !requestData.input.isValid() || !requestData.input.canConvert< QVariantMap >() )
{
emit info(caller, Tomahawk::InfoSystem::InfoTrackLyrics, input, QVariant(), customData);
emit info( requestId, requestData, QVariant() );
qDebug() << "MusixMatchPlugin::isValidTrackData: Data null, invalid, or can't convert";
return false;
}
InfoCustomData hash = input.value<Tomahawk::InfoSystem::InfoCustomData>();
if (hash["trackName"].toString().isEmpty() )
QVariantMap hash = requestData.input.value< QVariantMap >();
if ( hash[ "trackName" ].toString().isEmpty() )
{
emit info(caller, Tomahawk::InfoSystem::InfoTrackLyrics, input, QVariant(), customData);
emit info( requestId, requestData, QVariant() );
qDebug() << "MusixMatchPlugin::isValidTrackData: Track name is empty";
return false;
}
if (hash["artistName"].toString().isEmpty() )
if ( hash[ "artistName" ].toString().isEmpty() )
{
emit info(caller, Tomahawk::InfoSystem::InfoTrackLyrics, input, QVariant(), customData);
emit info( requestId, requestData, QVariant() );
qDebug() << "MusixMatchPlugin::isValidTrackData: No artist name found";
return false;
}
@@ -109,51 +108,46 @@ MusixMatchPlugin::trackSearchSlot()
{
qDebug() << Q_FUNC_INFO;
QNetworkReply* oldReply = qobject_cast<QNetworkReply*>( sender() );
if ( !oldReply || m_nam.isNull() )
{
emit info(QString(), Tomahawk::InfoSystem::InfoTrackLyrics, QVariant(), QVariant(), Tomahawk::InfoSystem::InfoCustomData());
return;
}
if ( !oldReply )
return; //timeout will handle it
QDomDocument doc;
doc.setContent(oldReply->readAll());
qDebug() << doc.toString();
QDomNodeList domNodeList = doc.elementsByTagName("track_id");
if (domNodeList.isEmpty())
if ( domNodeList.isEmpty() )
{
emit info(oldReply->property("caller").toString(), Tomahawk::InfoSystem::InfoTrackLyrics, oldReply->property("origData"), QVariant(), oldReply->property("customData").value<Tomahawk::InfoSystem::InfoCustomData>());
emit info( oldReply->property( "requestId" ).toUInt(), oldReply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
return;
}
QString track_id = domNodeList.at(0).toElement().text();
QString requestString("http://api.musixmatch.com/ws/1.1/track.lyrics.get?track_id=%1&format=xml&apikey=%2");
QUrl url(requestString);
url.addQueryItem("apikey", m_apiKey);
url.addQueryItem("track_id", track_id);
QNetworkReply* newReply = m_nam.data()->get(QNetworkRequest(url));
newReply->setProperty("origData", oldReply->property("origData"));
newReply->setProperty("customData", oldReply->property("customData"));
newReply->setProperty("caller", oldReply->property("caller"));
connect(newReply, SIGNAL(finished()), SLOT(trackLyricsSlot()));
QString requestString( "http://api.musixmatch.com/ws/1.1/track.lyrics.get?track_id=%1&format=xml&apikey=%2" );
QUrl url( requestString );
url.addQueryItem( "apikey", m_apiKey );
url.addQueryItem( "track_id", track_id );
QNetworkReply* newReply = m_nam.data()->get( QNetworkRequest( url ) );
newReply->setProperty( "requestId", oldReply->property( "requestId" ) );
newReply->setProperty( "requestData", oldReply->property( "requestData" ) );
connect( newReply, SIGNAL( finished() ), SLOT( trackLyricsSlot() ) );
}
void
MusixMatchPlugin::trackLyricsSlot()
{
qDebug() << Q_FUNC_INFO;
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
if (!reply)
{
emit info(QString(), Tomahawk::InfoSystem::InfoTrackLyrics, QVariant(), QVariant(), Tomahawk::InfoSystem::InfoCustomData());
return;
}
QNetworkReply* reply = qobject_cast< QNetworkReply* >( sender() );
if ( !reply )
return; //timeout will handle it
QDomDocument doc;
doc.setContent(reply->readAll());
QDomNodeList domNodeList = doc.elementsByTagName("lyrics_body");
if (domNodeList.isEmpty())
doc.setContent( reply->readAll() );
QDomNodeList domNodeList = doc.elementsByTagName( "lyrics_body" );
if ( domNodeList.isEmpty() )
{
emit info(reply->property("caller").toString(), Tomahawk::InfoSystem::InfoTrackLyrics, reply->property("origData"), QVariant(), reply->property("customData").value<Tomahawk::InfoSystem::InfoCustomData>());
emit info( reply->property( "requestId" ).toUInt(), reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant() );
return;
}
QString lyrics = domNodeList.at(0).toElement().text();
qDebug() << "Emitting lyrics: " << lyrics;
emit info(reply->property("caller").toString(), Tomahawk::InfoSystem::InfoTrackLyrics, reply->property("origData"), QVariant(lyrics), reply->property("customData").value<Tomahawk::InfoSystem::InfoCustomData>());
emit info( reply->property( "requestId" ).toUInt(), reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >(), QVariant( lyrics ) );
}

View File

@@ -45,26 +45,24 @@ public slots:
void namChangedSlot( QNetworkAccessManager *nam );
protected slots:
virtual void getInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData );
virtual void getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
virtual void pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant data )
virtual void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant data )
{
Q_UNUSED( caller );
Q_UNUSED( type );
Q_UNUSED( data );
}
virtual void notInCacheSlot( const Tomahawk::InfoSystem::InfoCriteriaHash criteria, const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData )
virtual void notInCacheSlot( uint requestId, Tomahawk::InfoSystem::InfoCriteriaHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
{
Q_UNUSED( requestId );
Q_UNUSED( criteria );
Q_UNUSED( caller );
Q_UNUSED( type );
Q_UNUSED( input );
Q_UNUSED( customData );
Q_UNUSED( requestData );
}
private:
bool isValidTrackData( const QString &caller, const QVariant &input, const InfoCustomData &customData );
bool isValidTrackData( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
QString m_apiKey;

View File

@@ -74,6 +74,7 @@ AdiumPlugin::AdiumPlugin()
this, SLOT( clearStatus() ) );
}
AdiumPlugin::~AdiumPlugin()
{
qDebug() << Q_FUNC_INFO;
@@ -81,6 +82,7 @@ AdiumPlugin::~AdiumPlugin()
setStatus( "" );
}
void
AdiumPlugin::clearStatus()
{
@@ -88,6 +90,7 @@ AdiumPlugin::clearStatus()
setStatus( "" );
}
void
AdiumPlugin::settingsChanged()
{
@@ -96,21 +99,9 @@ AdiumPlugin::settingsChanged()
setStatus( "" );
}
void
AdiumPlugin::getInfo( const QString caller, const InfoType type, const QVariant data, InfoCustomData customData )
{
switch (type)
{
default:
{
emit info(caller, Tomahawk::InfoSystem::InfoNoInfo, QVariant(), QVariant(), customData);
return;
}
}
}
void
AdiumPlugin::pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input )
AdiumPlugin::pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input )
{
qDebug() << Q_FUNC_INFO;

View File

@@ -39,12 +39,23 @@ public:
virtual ~AdiumPlugin();
protected slots:
void getInfo( const QString caller, const InfoType type, const QVariant data, InfoCustomData customData );
void pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input );
virtual void getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
{
Q_UNUSED( requestId );
Q_UNUSED( requestData );
}
void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input );
public slots:
void namChangedSlot( QNetworkAccessManager* /*nam*/ ) {} // unused
void notInCacheSlot( const Tomahawk::InfoSystem::InfoCriteriaHash /*criteria*/, const QString /*caller*/, const Tomahawk::InfoSystem::InfoType /*type*/, const QVariant /*input*/, const Tomahawk::InfoSystem::InfoCustomData /*customData*/ ) {} // unused
virtual void notInCacheSlot( uint requestId, const Tomahawk::InfoSystem::InfoCriteriaHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
{
Q_UNUSED( requestId );
Q_UNUSED( criteria );
Q_UNUSED( requestData );
}
private slots:
void clearStatus();

View File

@@ -59,16 +59,16 @@ FdoNotifyPlugin::~FdoNotifyPlugin()
}
void
FdoNotifyPlugin::pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant pushData )
FdoNotifyPlugin::pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant pushData )
{
Q_UNUSED( caller );
qDebug() << Q_FUNC_INFO;
if ( type != Tomahawk::InfoSystem::InfoNotifyUser || !pushData.canConvert< Tomahawk::InfoSystem::InfoCriteriaHash >() )
if ( type != Tomahawk::InfoSystem::InfoNotifyUser || !pushData.canConvert< QVariantMap >() )
{
qDebug() << Q_FUNC_INFO << " not the right type or could not convert the hash";
return;
}
Tomahawk::InfoSystem::InfoCriteriaHash hash = pushData.value< Tomahawk::InfoSystem::InfoCriteriaHash >();
QVariantMap hash = pushData.value< QVariantMap >();
if ( !hash.contains( "message" ) )
{
qDebug() << Q_FUNC_INFO << " hash did not contain a message";
@@ -81,10 +81,17 @@ FdoNotifyPlugin::pushInfo( const QString caller, const Tomahawk::InfoSystem::Inf
arguments << quint32( 0 ); //notification_id
arguments << QString(); //app_icon
arguments << QString( "Tomahawk" ); //summary
arguments << hash["message"]; //body
arguments << hash["message"].toString(); //body
arguments << QStringList(); //actions
QVariantMap dict;
dict["desktop-entry"] = QString( "tomahawk" );
if ( hash.contains( "image" ) )
{
QVariant tempVariant = hash["image"];
QImage tempImage = tempVariant.value< QImage >();
dict["image_data"] = ImageConverter::variantForImage( tempImage );
}
else
dict["image_data"] = ImageConverter::variantForImage( QImage( RESPATH "icons/tomahawk-icon-128x128.png" ) );
arguments << dict; //hints
arguments << qint32( -1 ); //expire_timeout

View File

@@ -38,23 +38,19 @@ public:
virtual void namChangedSlot( QNetworkAccessManager* ) {}
protected slots:
virtual void getInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData )
virtual void getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
{
Q_UNUSED( caller );
Q_UNUSED( type );
Q_UNUSED( input );
Q_UNUSED( customData );
Q_UNUSED( requestId );
Q_UNUSED( requestData );
}
virtual void pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant pushData );
virtual void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant pushData );
virtual void notInCacheSlot( const Tomahawk::InfoSystem::InfoCriteriaHash criteria, const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData )
virtual void notInCacheSlot( uint requestId, Tomahawk::InfoSystem::InfoCriteriaHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
{
Q_UNUSED( requestId );
Q_UNUSED( criteria );
Q_UNUSED( caller );
Q_UNUSED( type );
Q_UNUSED( input );
Q_UNUSED( customData );
Q_UNUSED( requestData );
}
};

View File

@@ -50,8 +50,10 @@ InfoSystem::instance()
}
InfoSystem::InfoSystem(QObject *parent)
: QObject(parent)
InfoSystem::InfoSystem( QObject *parent )
: QObject( parent )
, m_infoSystemCacheThreadController( 0 )
, m_infoSystemWorkerThreadController( 0 )
{
s_instance = this;
@@ -71,11 +73,12 @@ InfoSystem::InfoSystem(QObject *parent)
connect( TomahawkSettings::instance(), SIGNAL( changed() ), SLOT( newNam() ) );
connect( m_cache.data(), SIGNAL( info( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
this, SLOT( infoSlot( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ), Qt::UniqueConnection );
connect( m_cache.data(), SIGNAL( info( uint, Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
m_worker.data(), SLOT( infoSlot( uint, Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
connect( m_worker.data(), SIGNAL( info( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
this, SLOT( infoSlot( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ), Qt::UniqueConnection );
connect( m_worker.data(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
this, SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
connect( m_worker.data(), SIGNAL( finished( QString ) ), this, SIGNAL( finished( QString ) ), Qt::UniqueConnection );
}
InfoSystem::~InfoSystem()
@@ -116,21 +119,25 @@ InfoSystem::newNam() const
void
InfoSystem::getInfo( const QString &caller, const InfoType type, const QVariant& input, InfoCustomData customData )
InfoSystem::getInfo( const InfoRequestData &requestData, uint timeoutMillis )
{
qDebug() << Q_FUNC_INFO;
m_dataTracker[caller][type] = m_dataTracker[caller][type] + 1;
qDebug() << "current count in dataTracker for type" << type << "is" << m_dataTracker[caller][type];
QMetaObject::invokeMethod( m_worker.data(), "getInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input ), Q_ARG( Tomahawk::InfoSystem::InfoCustomData, customData ) );
QMetaObject::invokeMethod( m_worker.data(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ), Q_ARG( uint, timeoutMillis ) );
}
void
InfoSystem::getInfo( const QString &caller, const InfoMap &input, InfoCustomData customData )
InfoSystem::getInfo( const QString &caller, const InfoTypeMap &inputMap, const QVariantMap &customData, const InfoTimeoutMap &timeoutMap )
{
Q_FOREACH( InfoType type, input.keys() )
getInfo( caller, type, input[type], customData );
InfoRequestData requestData;
requestData.caller = caller;
requestData.customData = customData;
Q_FOREACH( InfoType type, inputMap.keys() )
{
requestData.type = type;
requestData.input = inputMap[ type ];
QMetaObject::invokeMethod( m_worker.data(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ), Q_ARG( uint, ( timeoutMap.contains( type ) ? timeoutMap[ type ] : 3000 ) ) );
}
}
@@ -138,43 +145,15 @@ void
InfoSystem::pushInfo( const QString &caller, const InfoType type, const QVariant& input )
{
qDebug() << Q_FUNC_INFO;
QMetaObject::invokeMethod( m_worker.data(), "pushInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input ) );
}
void
InfoSystem::pushInfo( const QString &caller, const InfoMap &input )
InfoSystem::pushInfo( const QString &caller, const InfoTypeMap &input )
{
Q_FOREACH( InfoType type, input.keys() )
pushInfo( caller, type, input[type] );
}
void
InfoSystem::infoSlot( QString target, InfoType type, QVariant input, QVariant output, InfoCustomData customData )
{
qDebug() << Q_FUNC_INFO;
qDebug() << "current count in dataTracker is " << m_dataTracker[target][type];
if (m_dataTracker[target][type] == 0)
{
qDebug() << "Caller was not waiting for that type of data!";
return;
}
emit info(target, type, input, output, customData);
m_dataTracker[target][type] = m_dataTracker[target][type] - 1;
qDebug() << "current count in dataTracker is " << m_dataTracker[target][type];
Q_FOREACH(InfoType testtype, m_dataTracker[target].keys())
{
if (m_dataTracker[target][testtype] != 0)
{
qDebug() << "found outstanding request of type" << testtype;
return;
}
}
qDebug() << "emitting finished with target" << target;
emit finished(target);
QMetaObject::invokeMethod( m_worker.data(), "pushInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input[ type ] ) );
}
} //namespace InfoSystem

View File

@@ -75,8 +75,8 @@ enum InfoType { // as items are saved in cache, mark them here to not change the
InfoArtistNews = 29,
InfoArtistProfile = 30,
InfoArtistReviews = 31,
InfoArtistSongs = 32,
InfoArtistSimilars = 33,
InfoArtistSongs = 32, //cached -- do not change
InfoArtistSimilars = 33, //cached -- do not change
InfoArtistTerms = 34,
InfoArtistLinks = 35,
InfoArtistVideos = 36,
@@ -107,9 +107,16 @@ enum InfoType { // as items are saved in cache, mark them here to not change the
InfoNotifyUser = 55
};
typedef QMap< InfoType, QVariant > InfoMap;
struct InfoRequestData {
QString caller;
Tomahawk::InfoSystem::InfoType type;
QVariant input;
QVariantMap customData;
};
typedef QMap< InfoType, QVariant > InfoTypeMap;
typedef QMap< InfoType, uint > InfoTimeoutMap;
typedef QMap< QString, QMap< QString, QString > > InfoGenericMap;
typedef QHash< QString, QVariant > InfoCustomData;
typedef QHash< QString, QString > InfoCriteriaHash;
class DLLEXPORT InfoPlugin : public QObject
@@ -125,15 +132,15 @@ public:
QSet< InfoType > supportedPushTypes() const { return m_supportedPushTypes; }
signals:
void getCachedInfo( Tomahawk::InfoSystem::InfoCriteriaHash criteria, qint64 newMaxAge, QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, Tomahawk::InfoSystem::InfoCustomData customData );
void updateCache( Tomahawk::InfoSystem::InfoCriteriaHash criteria, qint64, Tomahawk::InfoSystem::InfoType type, QVariant output );
void info( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomData customData );
void finished( QString, Tomahawk::InfoSystem::InfoType );
void getCachedInfo( uint requestId, Tomahawk::InfoSystem::InfoCriteriaHash criteria, qint64 newMaxAge, Tomahawk::InfoSystem::InfoRequestData requestData );
void info( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
void updateCache( Tomahawk::InfoSystem::InfoCriteriaHash criteria, qint64 maxAge, Tomahawk::InfoSystem::InfoType type, QVariant output );
protected slots:
virtual void getInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant data, const Tomahawk::InfoSystem::InfoCustomData customData ) = 0;
virtual void pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant data ) = 0;
virtual void notInCacheSlot( const Tomahawk::InfoSystem::InfoCriteriaHash criteria, const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData ) = 0;
virtual void getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData ) = 0;
virtual void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant data ) = 0;
virtual void notInCacheSlot( uint requestId, Tomahawk::InfoSystem::InfoCriteriaHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData ) = 0;
virtual void namChangedSlot( QNetworkAccessManager *nam ) = 0;
@@ -158,23 +165,19 @@ public:
InfoSystem( QObject *parent );
~InfoSystem();
void getInfo( const QString &caller, const InfoType type, const QVariant &input, InfoCustomData customData );
void getInfo( const QString &caller, const InfoMap &input, InfoCustomData customData );
void getInfo( const InfoRequestData &requestData, uint timeoutMillis = 3000 );
void getInfo( const QString &caller, const InfoTypeMap &inputMap, const QVariantMap &customData, const InfoTimeoutMap &timeoutMap = InfoTimeoutMap() );
void pushInfo( const QString &caller, const InfoType type, const QVariant &input );
void pushInfo( const QString &caller, const InfoMap &input );
void pushInfo( const QString &caller, const InfoTypeMap &input );
signals:
void info( QString caller, Tomahawk::InfoSystem::InfoType, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomData customData );
void info( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
void finished( QString target );
public slots:
void infoSlot( const QString target, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const QVariant output, const Tomahawk::InfoSystem::InfoCustomData customData );
void newNam() const;
private:
QHash< QString, QHash< InfoType, int > > m_dataTracker;
QWeakPointer< InfoSystemCache > m_cache;
QWeakPointer< InfoSystemWorker > m_worker;
QThread* m_infoSystemCacheThreadController;
@@ -205,8 +208,8 @@ inline uint qHash( Tomahawk::InfoSystem::InfoCriteriaHash hash )
return returnval;
}
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoRequestData );
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoGenericMap );
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoCustomData );
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoCriteriaHash );
Q_DECLARE_METATYPE( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache > );

View File

@@ -84,26 +84,26 @@ InfoSystemCache::pruneTimerFired()
void
InfoSystemCache::getCachedInfoSlot( const Tomahawk::InfoSystem::InfoCriteriaHash criteria, const qint64 newMaxAge, const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData )
InfoSystemCache::getCachedInfoSlot( uint requestId, Tomahawk::InfoSystem::InfoCriteriaHash criteria, qint64 newMaxAge, Tomahawk::InfoSystem::InfoRequestData requestData )
{
qDebug() << Q_FUNC_INFO;
const QString criteriaHashVal = criteriaMd5( criteria );
QHash< QString, QString > fileLocationHash = m_fileLocationCache[type];
QHash< QString, QString > fileLocationHash = m_fileLocationCache[ requestData.type ];
if ( !fileLocationHash.contains( criteriaHashVal ) )
{
if ( !fileLocationHash.isEmpty() )
{
//We already know of some values, so no need to re-read the directory again as it's already happened
emit notInCache( criteria, caller, type, input, customData );
emit notInCache( requestId, criteria, requestData );
return;
}
const QString cacheDir = m_cacheBaseDir + QString::number( (int)type );
const QString cacheDir = m_cacheBaseDir + QString::number( (int)requestData.type );
QDir dir( cacheDir );
if ( !dir.exists() )
{
//Dir doesn't exist so clearly not in cache
emit notInCache( criteria, caller, type, input, customData );
emit notInCache( requestId, criteria, requestData );
return;
}
@@ -111,20 +111,20 @@ InfoSystemCache::getCachedInfoSlot( const Tomahawk::InfoSystem::InfoCriteriaHash
foreach ( QFileInfo file, fileList )
{
QString baseName = file.baseName();
fileLocationHash[baseName] = file.canonicalFilePath();
fileLocationHash[ baseName ] = file.canonicalFilePath();
}
//Store what we've loaded up
m_fileLocationCache[type] = fileLocationHash;
m_fileLocationCache[ requestData.type ] = fileLocationHash;
if ( !fileLocationHash.contains( criteriaHashVal ) )
{
//Still didn't fine it? It's really not in the cache then
emit notInCache( criteria, caller, type, input, customData );
emit notInCache( requestId, criteria, requestData );
return;
}
}
QFileInfo file( fileLocationHash[criteriaHashVal] );
QFileInfo file( fileLocationHash[ criteriaHashVal ] );
qlonglong currMaxAge = file.suffix().toLongLong();
if ( currMaxAge < QDateTime::currentMSecsSinceEpoch() )
@@ -135,10 +135,10 @@ InfoSystemCache::getCachedInfoSlot( const Tomahawk::InfoSystem::InfoCriteriaHash
qDebug() << "Removed stale cache file " << file.canonicalFilePath();
fileLocationHash.remove( criteriaHashVal );
m_fileLocationCache[type] = fileLocationHash;
m_fileLocationCache[ requestData.type ] = fileLocationHash;
m_dataCache.remove( criteriaHashVal );
emit notInCache( criteria, caller, type, input, customData );
emit notInCache( requestId, criteria, requestData );
return;
}
else if ( newMaxAge > 0 )
@@ -148,29 +148,31 @@ InfoSystemCache::getCachedInfoSlot( const Tomahawk::InfoSystem::InfoCriteriaHash
if ( !QFile::rename( file.canonicalFilePath(), newFilePath ) )
{
qDebug() << "Failed to move old cache file to new location!";
emit notInCache( criteria, caller, type, input, customData );
emit notInCache( requestId, criteria, requestData );
return;
}
fileLocationHash[criteriaHashVal] = newFilePath;
m_fileLocationCache[type] = fileLocationHash;
fileLocationHash[ criteriaHashVal ] = newFilePath;
m_fileLocationCache[ requestData.type ] = fileLocationHash;
}
if ( !m_dataCache.contains( criteriaHashVal ) )
{
QSettings cachedSettings( fileLocationHash[criteriaHashVal], QSettings::IniFormat );
QSettings cachedSettings( fileLocationHash[ criteriaHashVal ], QSettings::IniFormat );
QVariant output = cachedSettings.value( "data" );
m_dataCache.insert( criteriaHashVal, new QVariant( output ) );
emit info( caller, type, input, output, customData );
emit info( requestId, requestData, output );
}
else
emit info( caller, type, input, QVariant( *(m_dataCache[criteriaHashVal]) ), customData );
{
emit info( requestId, requestData, QVariant( *(m_dataCache[criteriaHashVal]) ) );
}
}
void
InfoSystemCache::updateCacheSlot( const Tomahawk::InfoSystem::InfoCriteriaHash criteria, const qint64 maxAge, const Tomahawk::InfoSystem::InfoType type, const QVariant output )
InfoSystemCache::updateCacheSlot( Tomahawk::InfoSystem::InfoCriteriaHash criteria, qint64 maxAge, Tomahawk::InfoSystem::InfoType type, QVariant output )
{
qDebug() << Q_FUNC_INFO;

View File

@@ -43,12 +43,12 @@ public:
virtual ~InfoSystemCache();
signals:
void notInCache( Tomahawk::InfoSystem::InfoCriteriaHash criteria, QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, Tomahawk::InfoSystem::InfoCustomData customData );
void info( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomData customData );
void notInCache( uint requestId, Tomahawk::InfoSystem::InfoCriteriaHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
void info( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
public slots:
void getCachedInfoSlot( const Tomahawk::InfoSystem::InfoCriteriaHash criteria, const qint64 newMaxAge, const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData );
void updateCacheSlot( const Tomahawk::InfoSystem::InfoCriteriaHash criteria, const qint64 maxAge, const Tomahawk::InfoSystem::InfoType type, const QVariant output );
void getCachedInfoSlot( uint requestId, Tomahawk::InfoSystem::InfoCriteriaHash criteria, qint64 newMaxAge, Tomahawk::InfoSystem::InfoRequestData requestData );
void updateCacheSlot( Tomahawk::InfoSystem::InfoCriteriaHash criteria, qint64 maxAge, Tomahawk::InfoSystem::InfoType type, QVariant output );
private slots:
void pruneTimerFired();

View File

@@ -43,8 +43,15 @@ namespace InfoSystem
{
InfoSystemWorker::InfoSystemWorker()
: QObject()
, m_nextRequest( 0 )
{
qDebug() << Q_FUNC_INFO;
m_checkTimeoutsTimer.setInterval( 1000 );
m_checkTimeoutsTimer.setSingleShot( false );
connect( &m_checkTimeoutsTimer, SIGNAL( timeout() ), SLOT( checkTimeoutsTimerFired() ) );
m_checkTimeoutsTimer.start();
}
@@ -91,23 +98,23 @@ InfoSystemWorker::init( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache> cac
{
connect(
plugin.data(),
SIGNAL( info( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
InfoSystem::instance(),
SLOT( infoSlot( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
SIGNAL( info( uint, Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
this,
SLOT( infoSlot( uint, Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
Qt::UniqueConnection
);
connect(
plugin.data(),
SIGNAL( getCachedInfo( Tomahawk::InfoSystem::InfoCriteriaHash, qint64, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
SIGNAL( getCachedInfo( uint, Tomahawk::InfoSystem::InfoCriteriaHash, qint64, Tomahawk::InfoSystem::InfoRequestData ) ),
cache.data(),
SLOT( getCachedInfoSlot( Tomahawk::InfoSystem::InfoCriteriaHash, qint64, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) )
SLOT( getCachedInfoSlot( uint, Tomahawk::InfoSystem::InfoCriteriaHash, qint64, Tomahawk::InfoSystem::InfoRequestData ) )
);
connect(
cache.data(),
SIGNAL( notInCache( Tomahawk::InfoSystem::InfoCriteriaHash, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
SIGNAL( notInCache( uint, Tomahawk::InfoSystem::InfoCriteriaHash, Tomahawk::InfoSystem::InfoRequestData ) ),
plugin.data(),
SLOT( notInCacheSlot( Tomahawk::InfoSystem::InfoCriteriaHash, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) )
SLOT( notInCacheSlot( uint, Tomahawk::InfoSystem::InfoCriteriaHash, Tomahawk::InfoSystem::InfoRequestData ) )
);
connect(
plugin.data(),
@@ -151,33 +158,53 @@ InfoSystemWorker::determineOrderedMatches( const InfoType type ) const
void
InfoSystemWorker::getInfo( QString caller, InfoType type, QVariant input, InfoCustomData customData )
InfoSystemWorker::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData, uint timeoutMillis )
{
qDebug() << Q_FUNC_INFO;
QLinkedList< InfoPluginPtr > providers = determineOrderedMatches(type);
QLinkedList< InfoPluginPtr > providers = determineOrderedMatches( requestData.type );
if ( providers.isEmpty() )
{
emit info( caller, type, QVariant(), QVariant(), customData );
emit info( requestData, QVariant() );
checkFinished( requestData.caller );
return;
}
InfoPluginPtr ptr = providers.first();
if ( !ptr )
{
emit info( caller, type, QVariant(), QVariant(), customData );
emit info( requestData, QVariant() );
checkFinished( requestData.caller );
return;
}
QMetaObject::invokeMethod( ptr.data(), "getInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input ), Q_ARG( Tomahawk::InfoSystem::InfoCustomData, customData ) );
uint requestId = ++m_nextRequest;
m_requestSatisfiedMap[ requestId ] = false;
if ( timeoutMillis != 0 )
{
qint64 currMs = QDateTime::currentMSecsSinceEpoch();
m_timeRequestMapper.insert( currMs + timeoutMillis, requestId );
}
qDebug() << "assigning request with requestId " << requestId << " and type " << requestData.type;
m_dataTracker[ requestData.caller ][ requestData.type ] = m_dataTracker[ requestData.caller ][ requestData.type ] + 1;
qDebug() << "current count in dataTracker for type" << requestData.type << "is" << m_dataTracker[ requestData.caller ][ requestData.type ];
InfoRequestData* data = new InfoRequestData;
data->caller = requestData.caller;
data->type = requestData.type;
data->input = requestData.input;
data->customData = requestData.customData;
m_savedRequestMap[ requestId ] = data;
QMetaObject::invokeMethod( ptr.data(), "getInfo", Qt::QueuedConnection, Q_ARG( uint, requestId ), Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ) );
}
void
InfoSystemWorker::pushInfo( const QString caller, const InfoType type, const QVariant input )
InfoSystemWorker::pushInfo( QString caller, InfoType type, QVariant input )
{
qDebug() << Q_FUNC_INFO;
Q_FOREACH( InfoPluginPtr ptr, m_infoPushMap[type] )
Q_FOREACH( InfoPluginPtr ptr, m_infoPushMap[ type ] )
{
if( ptr )
QMetaObject::invokeMethod( ptr.data(), "pushInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input ) );
@@ -185,6 +212,101 @@ InfoSystemWorker::pushInfo( const QString caller, const InfoType type, const QVa
}
void
InfoSystemWorker::infoSlot( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
{
qDebug() << Q_FUNC_INFO << " with requestId " << requestId;
if ( m_dataTracker[ requestData.caller ][ requestData.type ] == 0 )
{
qDebug() << Q_FUNC_INFO << " caller was not waiting for that type of data!";
return;
}
if ( !m_requestSatisfiedMap.contains( requestId ) || m_requestSatisfiedMap[ requestId ] )
{
qDebug() << Q_FUNC_INFO << " request was already taken care of!";
return;
}
m_requestSatisfiedMap[ requestId ] = true;
emit info( requestData, output );
m_dataTracker[ requestData.caller ][ requestData.type ] = m_dataTracker[ requestData.caller ][ requestData.type ] - 1;
qDebug() << "current count in dataTracker for target " << requestData.caller << " is " << m_dataTracker[ requestData.caller ][ requestData.type ];
delete m_savedRequestMap[ requestId ];
m_savedRequestMap.remove( requestId );
checkFinished( requestData.caller );
}
void
InfoSystemWorker::checkFinished( const QString &target )
{
Q_FOREACH( InfoType testtype, m_dataTracker[ target ].keys() )
{
if ( m_dataTracker[ target ][ testtype ] != 0)
{
qDebug() << "found outstanding request of type" << testtype;
return;
}
}
qDebug() << "emitting finished with target" << target;
emit finished( target );
}
void
InfoSystemWorker::checkTimeoutsTimerFired()
{
qint64 currTime = QDateTime::currentMSecsSinceEpoch();
Q_FOREACH( qint64 time, m_timeRequestMapper.keys() )
{
Q_FOREACH( uint requestId, m_timeRequestMapper.values( time ) )
{
if ( time < currTime )
{
if ( m_requestSatisfiedMap[ requestId ] )
{
qDebug() << Q_FUNC_INFO << " removing mapping of " << requestId << " which expired at time " << time << " and was already satisfied";
m_timeRequestMapper.remove( time, requestId );
if ( !m_timeRequestMapper.count( time ) )
m_timeRequestMapper.remove( time );
continue;
}
//doh, timed out
qDebug() << Q_FUNC_INFO << " doh, timed out for requestId " << requestId;
InfoRequestData *savedData = m_savedRequestMap[ requestId ];
InfoRequestData returnData;
returnData.caller = savedData->caller;
returnData.type = savedData->type;
returnData.input = savedData->input;
returnData.customData = savedData->customData;
emit info( returnData, QVariant() );
delete savedData;
m_savedRequestMap.remove( requestId );
m_dataTracker[ returnData.caller ][ returnData.type ] = m_dataTracker[ returnData.caller ][ returnData.type ] - 1;
qDebug() << "current count in dataTracker for target " << returnData.caller << " is " << m_dataTracker[ returnData.caller ][ returnData.type ];
m_requestSatisfiedMap[ requestId ] = true;
m_timeRequestMapper.remove( time, requestId );
if ( !m_timeRequestMapper.count( time ) )
m_timeRequestMapper.remove( time );
checkFinished( returnData.caller );
}
else
{
//we've caught up, the remaining requets still have time to work
return;
}
}
}
}
QNetworkAccessManager*
InfoSystemWorker::nam() const
{
@@ -239,7 +361,6 @@ InfoSystemWorker::newNam()
//FIXME: Currently leaking nam/proxyfactory above -- how to change in a thread-safe way?
}
} //namespace InfoSystem
} //namespace Tomahawk

View File

@@ -29,6 +29,7 @@
#include <QtCore/QSet>
#include <QtCore/QLinkedList>
#include <QtCore/QVariant>
#include <QtCore/QTimer>
#include "dllmacro.h"
@@ -36,6 +37,7 @@ namespace Tomahawk {
namespace InfoSystem {
class DLLEXPORT InfoSystemWorker : public QObject
{
Q_OBJECT
@@ -48,16 +50,32 @@ public:
QNetworkAccessManager* nam() const;
signals:
void info( QString target, Tomahawk::InfoSystem::InfoType, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomData customData );
void info( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
void finished( QString target );
void namChanged( QNetworkAccessManager* );
public slots:
void init( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache > cache );
void getInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData );
void pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input );
void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData, uint timeoutMillis );
void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input );
void infoSlot( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
void newNam();
private slots:
void checkTimeoutsTimerFired();
private:
void checkFinished( const QString &target );
QHash< QString, QHash< InfoType, int > > m_dataTracker;
QMultiMap< qint64, uint > m_timeRequestMapper;
QHash< uint, bool > m_requestSatisfiedMap;
QHash< uint, InfoRequestData* > m_savedRequestMap;
QLinkedList< InfoPluginPtr > determineOrderedMatches( const InfoType type ) const;
// For now, statically instantiate plugins; this is just somewhere to keep them
@@ -67,6 +85,10 @@ private:
QMap< InfoType, QLinkedList< InfoPluginPtr > > m_infoPushMap;
QWeakPointer< QNetworkAccessManager> m_nam;
uint m_nextRequest;
QTimer m_checkTimeoutsTimer;
};
}

View File

@@ -19,7 +19,7 @@ namespace {
}
static Version kdParseQtVersion( const char * const version ) {
if ( !version || qstrlen( version ) < 5 || version[1] != '.' || version[3] != '.' || version[5] != 0 && version[5] != '.' && version[5] != '-' )
if ( !version || qstrlen( version ) < 5 || version[1] != '.' || version[3] != '.' || ( version[5] != 0 && version[5] != '.' && version[5] != '-' ) )
return Version(); // parse error
const Version result = { { version[0] - '0', version[2] - '0', version[4] - '0' } };
return result;

View File

@@ -195,12 +195,27 @@ Servent::createConnectionKey( const QString& name, const QString &nodeid, const
void
Servent::setExternalAddress( QHostAddress ha, unsigned int port )
{
QString ip = ha.toString();
if ( !qApp->arguments().contains( "--lanhack" ) )
{
if ( ip.startsWith( "10." ) || ip.startsWith( "172.16." ) || ip.startsWith( "192.168." ) )
{
qDebug() << Q_FUNC_INFO << "Tried to set an invalid ip as external address!";
return;
}
m_externalAddress = ha;
m_externalPort = port;
if( m_externalPort == 0 || m_externalAddress.toString().isEmpty() )
}
else
{
if( !TomahawkSettings::instance()->externalHostname().isEmpty() &&
m_externalAddress = ha;
m_externalPort = port;
}
if ( m_externalPort == 0 || m_externalAddress.toString().isEmpty() )
{
if ( !TomahawkSettings::instance()->externalHostname().isEmpty() &&
!TomahawkSettings::instance()->externalPort() == 0 )
{
qDebug() << "UPnP failed, have external address/port -- falling back";

View File

@@ -208,6 +208,8 @@ signals:
void trackCountChanged( unsigned int tracks );
void sourceTrackCountChanged( unsigned int tracks );
void nextTrackReady();
public slots:
// want to update the playlist from the model?
// generate a newrev using uuid() and call this:

View File

@@ -44,8 +44,8 @@ AlbumModel::AlbumModel( QObject* parent )
.scaled( QSize( 120, 120 ), Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
SIGNAL( info( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
SLOT( infoSystemInfo( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ) );
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
connect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ), SLOT( infoSystemFinished( QString ) ) );
}
@@ -311,26 +311,25 @@ AlbumModel::onAlbumsAdded( const QList<Tomahawk::album_ptr>& albums )
void
AlbumModel::infoSystemInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomData customData )
AlbumModel::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
{
Q_UNUSED( customData );
qDebug() << Q_FUNC_INFO;
qDebug() << Q_FUNC_INFO << " with caller " << requestData.caller;
if ( caller != s_tmInfoIdentifier ||
( type != Tomahawk::InfoSystem::InfoAlbumCoverArt && type != Tomahawk::InfoSystem::InfoArtistImages ) )
if ( requestData.caller != s_tmInfoIdentifier ||
( requestData.type != Tomahawk::InfoSystem::InfoAlbumCoverArt && requestData.type != Tomahawk::InfoSystem::InfoArtistImages ) )
{
qDebug() << "Info of wrong type or not with our identifier";
return;
}
if ( !output.canConvert< Tomahawk::InfoSystem::InfoCustomData >() )
if ( !output.canConvert< QVariantMap >() )
{
qDebug() << "Cannot convert fetched art from a QByteArray";
return;
}
Tomahawk::InfoSystem::InfoCriteriaHash pptr = input.value< Tomahawk::InfoSystem::InfoCriteriaHash >();
Tomahawk::InfoSystem::InfoCustomData returnedData = output.value< Tomahawk::InfoSystem::InfoCustomData >();
Tomahawk::InfoSystem::InfoCriteriaHash pptr = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash >();
QVariantMap returnedData = output.value< QVariantMap >();
const QByteArray ba = returnedData["imgbytes"].toByteArray();
if ( ba.length() )
{

View File

@@ -97,7 +97,7 @@ private slots:
void onAlbumsAdded( const QList<Tomahawk::album_ptr>& albums );
void onDataChanged();
void infoSystemInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomData customData );
void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
void infoSystemFinished( QString target );
private:

View File

@@ -40,6 +40,7 @@ AlbumProxyModel::AlbumProxyModel( QObject* parent )
setSourceAlbumModel( 0 );
}
void
AlbumProxyModel::setSourceModel( QAbstractItemModel* sourceModel )
{
@@ -48,6 +49,7 @@ AlbumProxyModel::setSourceModel( QAbstractItemModel* sourceModel )
Q_ASSERT( false );
}
void
AlbumProxyModel::setSourceAlbumModel( AlbumModel* sourceModel )
{

View File

@@ -65,6 +65,8 @@ signals:
void filterChanged( const QString& filter );
void nextTrackReady();
public slots:
virtual void setRepeatMode( RepeatMode mode ) { m_repeatMode = mode; emit repeatModeChanged( mode ); }
virtual void setShuffled( bool enabled ) { m_shuffled = enabled; emit shuffleModeChanged( enabled ); }

View File

@@ -162,9 +162,13 @@ AlbumView::onScrollTimeout()
trackInfo["album"] = item->album()->name();
trackInfo["pptr"] = QString::number( (qlonglong)item );
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo(
s_tmInfoIdentifier, Tomahawk::InfoSystem::InfoAlbumCoverArt,
QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo ), Tomahawk::InfoSystem::InfoCustomData() );
Tomahawk::InfoSystem::InfoRequestData requestData;
requestData.caller = s_tmInfoIdentifier;
requestData.type = Tomahawk::InfoSystem::InfoAlbumCoverArt;
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo );
requestData.customData = QVariantMap();
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
}
}
}

View File

@@ -46,6 +46,7 @@ ArtistView::ArtistView( QWidget* parent )
, m_proxyModel( 0 )
// , m_delegate( 0 )
, m_loadingSpinner( new LoadingSpinner( this ) )
, m_contextMenu( new ContextMenu( this ) )
, m_showModes( true )
{
setAlternatingRowColors( true );
@@ -59,6 +60,7 @@ ArtistView::ArtistView( QWidget* parent )
setAllColumnsShowFocus( true );
setSelectionMode( QAbstractItemView::ExtendedSelection );
setSelectionBehavior( QAbstractItemView::SelectRows );
setContextMenuPolicy( Qt::CustomContextMenu );
setHeader( m_header );
setProxyModel( new TreeProxyModel( this ) );
@@ -81,6 +83,8 @@ ArtistView::ArtistView( QWidget* parent )
connect( &m_timer, SIGNAL( timeout() ), SLOT( onScrollTimeout() ) );
connect( this, SIGNAL( doubleClicked( QModelIndex ) ), SLOT( onItemActivated( QModelIndex ) ) );
connect( this, SIGNAL( customContextMenuRequested( const QPoint& ) ), SLOT( onCustomContextMenu( const QPoint& ) ) );
connect( m_contextMenu, SIGNAL( triggered( int ) ), SLOT( onMenuTriggered( int ) ) );
}
@@ -116,7 +120,7 @@ ArtistView::setTreeModel( TreeModel* model )
if ( m_proxyModel )
{
m_proxyModel->setSourceModel( model );
m_proxyModel->setSourceTreeModel( model );
m_proxyModel->sort( 0 );
}
@@ -238,14 +242,74 @@ ArtistView::onScrollTimeout()
for ( int i = left.row(); i < max; i++ )
{
TreeModelItem* item = m_model->itemFromIndex( m_proxyModel->mapToSource( m_proxyModel->index( i, 0 ) ) );
if ( item->artist().isNull() )
continue;
Tomahawk::InfoSystem::InfoCriteriaHash trackInfo;
trackInfo["artist"] = item->artist()->name();
trackInfo["pptr"] = QString::number( (qlonglong)item );
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo(
s_tmInfoIdentifier, Tomahawk::InfoSystem::InfoArtistImages,
QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo ), Tomahawk::InfoSystem::InfoCustomData() );
Tomahawk::InfoSystem::InfoRequestData requestData;
requestData.caller = s_tmInfoIdentifier;
requestData.type = Tomahawk::InfoSystem::InfoArtistImages;
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo );
requestData.customData = QVariantMap();
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
}
}
void
ArtistView::onCustomContextMenu( const QPoint& pos )
{
m_contextMenu->clear();
QModelIndex idx = indexAt( pos );
idx = idx.sibling( idx.row(), 0 );
m_contextMenuIndex = idx;
if ( !idx.isValid() )
return;
QList<query_ptr> queries;
QList<artist_ptr> artists;
QList<album_ptr> albums;
foreach ( const QModelIndex& index, selectedIndexes() )
{
if ( index.column() || selectedIndexes().contains( index.parent() ) )
continue;
TreeModelItem* item = m_proxyModel->itemFromIndex( m_proxyModel->mapToSource( index ) );
if ( item && !item->result().isNull() )
queries << item->result()->toQuery();
if ( item && !item->artist().isNull() )
artists << item->artist();
if ( item && !item->album().isNull() )
albums << item->album();
}
m_contextMenu->setQueries( queries );
m_contextMenu->setArtists( artists );
m_contextMenu->setAlbums( albums );
m_contextMenu->exec( mapToGlobal( pos ) );
}
void
ArtistView::onMenuTriggered( int action )
{
switch ( action )
{
case ContextMenu::ActionPlay:
onItemActivated( m_contextMenuIndex );
break;
default:
break;
}
}

View File

@@ -22,6 +22,7 @@
#include <QTreeView>
#include <QSortFilterProxyModel>
#include "contextMenu.h"
#include "treemodel.h"
#include "treeproxymodel.h"
#include "viewpage.h"
@@ -79,6 +80,9 @@ private slots:
void onViewChanged();
void onScrollTimeout();
void onCustomContextMenu( const QPoint& pos );
void onMenuTriggered( int action );
private:
TreeHeader* m_header;
TreeModel* m_model;
@@ -86,6 +90,8 @@ private:
// PlaylistItemDelegate* m_delegate;
LoadingSpinner* m_loadingSpinner;
QModelIndex m_contextMenuIndex;
Tomahawk::ContextMenu* m_contextMenu;
bool m_showModes;
QTimer m_timer;

View File

@@ -55,6 +55,8 @@ public:
void addFilteredCollection( const Tomahawk::collection_ptr& collection, unsigned int amount, DatabaseCommand_AllTracks::SortOrder order );
virtual void append( const Tomahawk::query_ptr& /*query*/ ) {}
virtual void append( const Tomahawk::artist_ptr& /*artist*/ ) {}
virtual void append( const Tomahawk::album_ptr& /*album*/ ) {}
signals:
void repeatModeChanged( Tomahawk::PlaylistInterface::RepeatMode mode );

View File

@@ -38,9 +38,6 @@ CollectionView::CollectionView( QWidget* parent )
setDragDropMode( QAbstractItemView::DragOnly );
setAcceptDrops( false );
setContextMenuPolicy( Qt::CustomContextMenu );
connect( this, SIGNAL( customContextMenuRequested( const QPoint& ) ), SLOT( onCustomContextMenu( const QPoint& ) ) );
}
@@ -80,42 +77,6 @@ CollectionView::dragEnterEvent( QDragEnterEvent* event )
}
void
CollectionView::setupMenus()
{
m_itemMenu.clear();
m_playItemAction = m_itemMenu.addAction( tr( "&Play" ) );
m_addItemsToQueueAction = m_itemMenu.addAction( tr( "Add to &Queue" ) );
m_itemMenu.addSeparator();
foreach( QAction* a, actions() )
m_itemMenu.addAction( a );
// m_addItemsToPlaylistAction = m_itemMenu.addAction( tr( "&Add to Playlist" ) );
connect( m_playItemAction, SIGNAL( triggered() ), SLOT( playItem() ) );
connect( m_addItemsToQueueAction, SIGNAL( triggered() ), SLOT( addItemsToQueue() ) );
// connect( m_addItemsToPlaylistAction, SIGNAL( triggered() ), SLOT( addItemsToPlaylist() ) );
}
void
CollectionView::onCustomContextMenu( const QPoint& pos )
{
qDebug() << Q_FUNC_INFO;
setupMenus();
QModelIndex idx = indexAt( pos );
idx = idx.sibling( idx.row(), 0 );
setContextMenuIndex( idx );
if ( !idx.isValid() )
return;
m_itemMenu.exec( mapToGlobal( pos ) );
}
void
CollectionView::onTrackCountChanged( unsigned int tracks )
{

View File

@@ -19,8 +19,6 @@
#ifndef COLLECTIONVIEW_H
#define COLLECTIONVIEW_H
#include <QMenu>
#include "trackproxymodel.h"
#include "trackmodel.h"
#include "trackview.h"
@@ -52,20 +50,10 @@ public:
virtual bool jumpToCurrentTrack();
private slots:
void onCustomContextMenu( const QPoint& pos );
void onTrackCountChanged( unsigned int tracks );
protected:
virtual void dragEnterEvent( QDragEnterEvent* event );
private:
void setupMenus();
QMenu m_itemMenu;
QAction* m_playItemAction;
QAction* m_addItemsToQueueAction;
QAction* m_addItemsToPlaylistAction;
};
#endif // COLLECTIONVIEW_H

View File

@@ -27,7 +27,6 @@ namespace Tomahawk
class StationModelItem;
/**
* Extends PlaylistModel with support for handling stations
*/
@@ -55,6 +54,9 @@ public:
// a batchof static tracks wre generated
void tracksGenerated( const QList< query_ptr > entries, int limitResolvedTo = -1 );
using PlaylistModel::loadPlaylist;
signals:
void collapseFromTo( int startRow, int num );
void checkForOverflow();
@@ -62,6 +64,7 @@ signals:
void trackGenerationFailure( const QString& msg );
void tracksAdded();
private slots:
void newTrackGenerated( const Tomahawk::query_ptr& query );
@@ -69,6 +72,7 @@ private slots:
void newTrackLoading();
void filteringTrackResolved( bool successful );
private:
void filterUnresolved( const QList< query_ptr >& entries );
void addToPlaylist( const QList< query_ptr >& entries, bool clearFirst );

View File

@@ -43,18 +43,25 @@ InfoBar::InfoBar( QWidget* parent )
boldFont.setPixelSize( 12 );
ui->descriptionLabel->setFont( boldFont );
ui->descriptionLabel->setMargin( 10 );
QFont regFont = ui->longDescriptionLabel->font();
regFont.setPixelSize( 11 );
ui->longDescriptionLabel->setFont( regFont );
QPalette whitePal = ui->captionLabel->palette();
whitePal.setColor( QPalette::Foreground, Qt::white );
ui->captionLabel->setPalette( whitePal );
ui->descriptionLabel->setPalette( whitePal );
ui->longDescriptionLabel->setPalette( whitePal );
ui->captionLabel->setMargin( 6 );
ui->descriptionLabel->setMargin( 6 );
ui->longDescriptionLabel->setMargin( 4 );
ui->captionLabel->setText( QString() );
ui->captionLabel->setMargin( 6 );
ui->descriptionLabel->setText( QString() );
ui->longDescriptionLabel->setText( QString() );
ui->imageLabel->setText( QString() );
setAutoFillBackground( true );
@@ -81,6 +88,13 @@ InfoBar::setDescription( const QString& s )
}
void
InfoBar::setLongDescription( const QString& s )
{
ui->longDescriptionLabel->setText( s );
}
void
InfoBar::setPixmap( const QPixmap& p )
{

View File

@@ -39,6 +39,7 @@ public:
public slots:
void setCaption( const QString& s );
void setDescription( const QString& s );
void setLongDescription( const QString& s );
void setPixmap( const QPixmap& p );
protected:

View File

@@ -36,7 +36,7 @@
</property>
<property name="sizeHint" stdset="0">
<size>
<width>32</width>
<width>16</width>
<height>20</height>
</size>
</property>
@@ -65,7 +65,7 @@
</property>
<property name="sizeHint" stdset="0">
<size>
<width>32</width>
<width>16</width>
<height>20</height>
</size>
</property>
@@ -73,10 +73,13 @@
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetMinimumSize</enum>
</property>
<item>
<widget class="ElidedLabel" name="captionLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -89,7 +92,7 @@
<item>
<widget class="ElidedLabel" name="descriptionLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -101,6 +104,73 @@
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>16</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetMaximumSize</enum>
</property>
<item>
<widget class="QLabel" name="longDescriptionLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>62</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>62</height>
</size>
</property>
<property name="text">
<string>TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>1</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
@@ -111,7 +181,7 @@
</property>
<property name="sizeHint" stdset="0">
<size>
<width>32</width>
<width>16</width>
<height>20</height>
</size>
</property>

View File

@@ -37,6 +37,8 @@
#define PLAYING_ICON QString( RESPATH "images/now-playing-speaker.png" )
using namespace Tomahawk;
PlaylistItemDelegate::PlaylistItemDelegate( TrackView* parent, TrackProxyModel* proxy )
: QStyledItemDelegate( (QObject*)parent )
@@ -147,6 +149,8 @@ PlaylistItemDelegate::paintShort( QPainter* painter, const QStyleOptionViewItem&
QPixmap pixmap;
QString artist, track, upperText, lowerText;
source_ptr source = item->query()->playedBy().first;
if ( item->query()->results().count() )
{
artist = item->query()->results().first()->artist()->name();
@@ -158,7 +162,7 @@ PlaylistItemDelegate::paintShort( QPainter* painter, const QStyleOptionViewItem&
track = item->query()->track();
}
if ( item->query()->playedBy().isNull() )
if ( source.isNull() )
{
upperText = artist;
lowerText = track;
@@ -166,13 +170,14 @@ PlaylistItemDelegate::paintShort( QPainter* painter, const QStyleOptionViewItem&
else
{
upperText = QString( "%1 - %2" ).arg( artist ).arg( track );
QString playtime = TomahawkUtils::ageToString( QDateTime::fromTime_t( item->query()->playedBy().second ) );
if ( item->query()->playedBy() == SourceList::instance()->getLocal() )
lowerText = QString( "played by you" );
if ( source == SourceList::instance()->getLocal() )
lowerText = QString( "played %1 ago by you" ).arg( playtime );
else
lowerText = QString( "played by %1" ).arg( item->query()->playedBy()->friendlyName() );
lowerText = QString( "played %1 ago by %2" ).arg( playtime ).arg( source->friendlyName() );
pixmap = item->query()->playedBy()->avatar();
pixmap = source->avatar();
}
if ( pixmap.isNull() )
@@ -200,15 +205,16 @@ PlaylistItemDelegate::paintShort( QPainter* painter, const QStyleOptionViewItem&
QFont boldFont = opt.font;
boldFont.setBold( true );
r.adjust( ir.width() + 12, 0, 0, 0 );
r.adjust( ir.width() + 12, 0, -12, 0 );
QTextOption to( Qt::AlignTop );
QString text = painter->fontMetrics().elidedText( upperText, Qt::ElideRight, r.width() - 3 );
to.setWrapMode( QTextOption::NoWrap );
painter->setFont( boldFont );
QString text = painter->fontMetrics().elidedText( upperText, Qt::ElideRight, r.width() );
painter->drawText( r.adjusted( 0, 1, 0, 0 ), text, to );
to.setAlignment( Qt::AlignBottom );
text = painter->fontMetrics().elidedText( lowerText, Qt::ElideRight, r.width() - 3 );
painter->setFont( opt.font );
text = painter->fontMetrics().elidedText( lowerText, Qt::ElideRight, r.width() );
painter->drawText( r.adjusted( 0, 1, 0, 0 ), text, to );
}
painter->restore();
@@ -257,8 +263,8 @@ PlaylistItemDelegate::paintDetailed( QPainter* painter, const QStyleOptionViewIt
if ( m_view->header()->visualIndex( index.column() ) == 0 )
{
r.adjust( 0, 0, 0, -3 );
painter->drawPixmap( r.adjusted( 3, 3, 18 - r.width(), 0 ), m_nowPlayingIcon );
r.adjust( 22, 0, 0, 3 );
painter->drawPixmap( r.adjusted( 3, 1, 18 - r.width(), 1 ), m_nowPlayingIcon );
r.adjust( 25, 0, 0, 3 );
}
painter->setPen( opt.palette.text().color() );

View File

@@ -23,7 +23,7 @@
#include <QTreeView>
#include "album.h"
#include "pipeline.h"
#include "database/database.h"
#include "database/databasecommand_playbackhistory.h"
#include "dynamic/GeneratorInterface.h"
@@ -188,6 +188,9 @@ PlaylistModel::append( const Tomahawk::query_ptr& query )
QList< Tomahawk::query_ptr > ql;
ql << query;
if ( !query->resolvingFinished() )
Pipeline::instance()->resolve( query );
onTracksAdded( ql );
}
@@ -201,7 +204,8 @@ PlaylistModel::append( const Tomahawk::album_ptr& album )
connect( album.data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr> ) ),
SLOT( onTracksAdded( QList<Tomahawk::query_ptr> ) ) );
if( rowCount( QModelIndex() ) == 0 ) {
if ( rowCount( QModelIndex() ) == 0 )
{
setTitle( album->name() );
setDescription( tr( "All tracks by %1 on album %2" ).arg( album->artist()->name() ).arg( album->name() ) );
m_isTemporary = true;
@@ -220,7 +224,8 @@ PlaylistModel::append( const Tomahawk::artist_ptr& artist )
connect( artist.data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr> ) ),
SLOT( onTracksAdded( QList<Tomahawk::query_ptr> ) ) );
if( rowCount( QModelIndex() ) == 0 ) {
if ( rowCount( QModelIndex() ) == 0 )
{
setTitle( artist->name() );
setDescription( tr( "All tracks by %1" ).arg( artist->name() ) );
m_isTemporary = true;

View File

@@ -32,16 +32,10 @@ using namespace Tomahawk;
PlaylistView::PlaylistView( QWidget* parent )
: TrackView( parent )
, m_model( 0 )
, m_itemMenu( 0 )
, m_playItemAction( 0 )
, m_addItemsToQueueAction( 0 )
, m_addItemsToPlaylistAction( 0 )
, m_deleteItemsAction( 0 )
{
setProxyModel( new PlaylistProxyModel( this ) );
setContextMenuPolicy( Qt::CustomContextMenu );
connect( this, SIGNAL( customContextMenuRequested( const QPoint& ) ), SLOT( onCustomContextMenu( const QPoint& ) ) );
connect( contextMenu(), SIGNAL( triggered( int ) ), SLOT( onMenuTriggered( int ) ) );
}
@@ -81,54 +75,6 @@ PlaylistView::setPlaylistModel( PlaylistModel* model )
}
void
PlaylistView::setupMenus()
{
m_itemMenu.clear();
unsigned int i = 0;
foreach( const QModelIndex& idx, selectedIndexes() )
if ( idx.column() == 0 )
i++;
m_playItemAction = m_itemMenu.addAction( tr( "&Play" ) );
m_addItemsToQueueAction = m_itemMenu.addAction( tr( "Add to &Queue" ) );
m_itemMenu.addSeparator();
foreach( QAction* a, actions() )
m_itemMenu.addAction( a );
// m_addItemsToPlaylistAction = m_itemMenu.addAction( tr( "&Add to Playlist" ) );
// m_itemMenu.addSeparator();
m_deleteItemsAction = m_itemMenu.addAction( i > 1 ? tr( "&Delete Items" ) : tr( "&Delete Item" ) );
if ( model() )
m_deleteItemsAction->setEnabled( !model()->isReadOnly() );
connect( m_playItemAction, SIGNAL( triggered() ), SLOT( playItem() ) );
connect( m_addItemsToQueueAction, SIGNAL( triggered() ), SLOT( addItemsToQueue() ) );
// connect( m_addItemsToPlaylistAction, SIGNAL( triggered() ), SLOT( addItemsToPlaylist() ) );
connect( m_deleteItemsAction, SIGNAL( triggered() ), SLOT( deleteItems() ) );
}
void
PlaylistView::onCustomContextMenu( const QPoint& pos )
{
qDebug() << Q_FUNC_INFO;
setupMenus();
QModelIndex idx = indexAt( pos );
idx = idx.sibling( idx.row(), 0 );
setContextMenuIndex( idx );
if ( !idx.isValid() )
return;
m_itemMenu.exec( mapToGlobal( pos ) );
}
void
PlaylistView::keyPressEvent( QKeyEvent* event )
{
@@ -152,6 +98,7 @@ PlaylistView::deleteItems()
proxyModel()->removeIndexes( selectedIndexes() );
}
void
PlaylistView::onTrackCountChanged( unsigned int tracks )
{
@@ -196,3 +143,19 @@ PlaylistView::isTemporaryPage() const
{
return ( m_model && m_model->isTemporary() );
}
void
PlaylistView::onMenuTriggered( int action )
{
switch ( action )
{
case ContextMenu::ActionDelete:
deleteItems();
break;
default:
TrackView::onMenuTriggered( action );
break;
}
}

View File

@@ -19,8 +19,6 @@
#ifndef PLAYLISTVIEW_H
#define PLAYLISTVIEW_H
#include <QMenu>
#include "playlist/trackproxymodel.h"
#include "playlist/playlistmodel.h"
#include "trackview.h"
@@ -62,26 +60,19 @@ protected:
void keyPressEvent( QKeyEvent* event );
private slots:
void onCustomContextMenu( const QPoint& pos );
void onTrackCountChanged( unsigned int tracks );
void onMenuTriggered( int action );
void deleteItems();
void onDeleted();
void onChanged();
private:
void setupMenus();
private:
PlaylistModel* m_model;
QMenu m_itemMenu;
QString m_customTitle;
QString m_customDescripton;
QAction* m_playItemAction;
QAction* m_addItemsToQueueAction;
QAction* m_addItemsToPlaylistAction;
QAction* m_deleteItemsAction;
};
#endif // PLAYLISTVIEW_H

View File

@@ -47,13 +47,12 @@ QueueProxyModel::siblingItem( int itemsAway )
setCurrentIndex( QModelIndex() );
Tomahawk::result_ptr res = PlaylistProxyModel::siblingItem( itemsAway );
qDebug() << "new rowcount:" << rowCount( QModelIndex() );
removeIndex( currentIndex() );
return res;
}
void
QueueProxyModel::onTrackCountChanged( unsigned int count )
{

View File

@@ -35,6 +35,8 @@ public:
virtual Tomahawk::result_ptr siblingItem( int itemsAway );
using PlaylistProxyModel::siblingItem;
private slots:
void onTrackCountChanged( unsigned int count );
};

View File

@@ -89,6 +89,8 @@ public:
virtual void ensureResolved();
virtual void append( const Tomahawk::query_ptr& query ) = 0;
virtual void append( const Tomahawk::artist_ptr& artist ) = 0;
virtual void append( const Tomahawk::album_ptr& album ) = 0;
TrackModelItem* itemFromIndex( const QModelIndex& index ) const;

View File

@@ -300,8 +300,6 @@ TrackProxyModel::removeIndexes( const QList<QPersistentModelIndex>& indexes )
bool
TrackProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) const
{
qDebug() << Q_FUNC_INFO;
TrackModelItem* p1 = itemFromIndex( left );
TrackModelItem* p2 = itemFromIndex( right );

View File

@@ -74,6 +74,8 @@ signals:
void filterChanged( const QString& filter );
void nextTrackReady();
public slots:
virtual void setRepeatMode( RepeatMode mode ) { m_repeatMode = mode; emit repeatModeChanged( mode ); }
virtual void setShuffled( bool enabled ) { m_shuffled = enabled; emit shuffleModeChanged( enabled ); }

View File

@@ -34,7 +34,6 @@
#include "trackmodel.h"
#include "trackproxymodel.h"
#include "track.h"
#include "globalactionmanager.h"
using namespace Tomahawk;
@@ -49,6 +48,7 @@ TrackView::TrackView( QWidget* parent )
, m_loadingSpinner( new LoadingSpinner( this ) )
, m_resizing( false )
, m_dragging( false )
, m_contextMenu( new ContextMenu( this ) )
{
setAlternatingRowColors( true );
setSelectionMode( QAbstractItemView::ExtendedSelection );
@@ -67,6 +67,7 @@ TrackView::TrackView( QWidget* parent )
setHeader( m_header );
setSortingEnabled( true );
sortByColumn( -1 );
setContextMenuPolicy( Qt::CustomContextMenu );
#ifndef Q_WS_WIN
QFont f = font();
@@ -79,11 +80,9 @@ TrackView::TrackView( QWidget* parent )
setFont( f );
#endif
QAction* createLinkAction = new QAction( tr( "Copy Track Link" ), this );
connect( createLinkAction, SIGNAL( triggered( bool ) ), this, SLOT( copyLink() ) );
addAction( createLinkAction );
connect( this, SIGNAL( doubleClicked( QModelIndex ) ), SLOT( onItemActivated( QModelIndex ) ) );
connect( this, SIGNAL( customContextMenuRequested( const QPoint& ) ), SLOT( onCustomContextMenu( const QPoint& ) ) );
connect( m_contextMenu, SIGNAL( triggered( int ) ), SLOT( onMenuTriggered( int ) ) );
}
@@ -200,24 +199,6 @@ TrackView::playItem()
}
void
TrackView::addItemsToQueue()
{
foreach( const QModelIndex& idx, selectedIndexes() )
{
if ( idx.column() )
continue;
TrackModelItem* item = model()->itemFromIndex( proxyModel()->mapToSource( idx ) );
if ( item && item->query()->numResults() )
{
ViewManager::instance()->queue()->model()->append( item->query() );
ViewManager::instance()->showQueue();
}
}
}
void
TrackView::resizeEvent( QResizeEvent* event )
{
@@ -374,17 +355,6 @@ TrackView::onFilterChanged( const QString& )
}
void
TrackView::copyLink()
{
TrackModelItem* item = model()->itemFromIndex( proxyModel()->mapToSource( contextMenuIndex() ) );
if ( item && !item->query().isNull() )
{
GlobalActionManager::instance()->copyToClipboard( item->query() );
}
}
void
TrackView::startDrag( Qt::DropActions supportedActions )
{
@@ -419,3 +389,49 @@ TrackView::startDrag( Qt::DropActions supportedActions )
m_proxyModel->removeIndexes( pindexes );
}
}
void
TrackView::onCustomContextMenu( const QPoint& pos )
{
m_contextMenu->clear();
QModelIndex idx = indexAt( pos );
idx = idx.sibling( idx.row(), 0 );
setContextMenuIndex( idx );
if ( !idx.isValid() )
return;
if ( model() && !model()->isReadOnly() )
m_contextMenu->setSupportedActions( m_contextMenu->supportedActions() | ContextMenu::ActionDelete );
QList<query_ptr> queries;
foreach ( const QModelIndex& index, selectedIndexes() )
{
if ( index.column() )
continue;
TrackModelItem* item = proxyModel()->itemFromIndex( proxyModel()->mapToSource( index ) );
if ( item && !item->query().isNull() )
queries << item->query();
}
m_contextMenu->setQueries( queries );
m_contextMenu->exec( mapToGlobal( pos ) );
}
void
TrackView::onMenuTriggered( int action )
{
switch ( action )
{
case ContextMenu::ActionPlay:
onItemActivated( m_contextMenuIndex );
break;
default:
break;
}
}

View File

@@ -22,6 +22,7 @@
#include <QTreeView>
#include <QSortFilterProxyModel>
#include "contextMenu.h"
#include "playlistitemdelegate.h"
#include "dllmacro.h"
@@ -53,6 +54,7 @@ explicit TrackView( QWidget* parent = 0 );
PlaylistItemDelegate* delegate() const { return m_delegate; }
TrackHeader* header() const { return m_header; }
OverlayWidget* overlay() const { return m_overlay; }
Tomahawk::ContextMenu* contextMenu() const { return m_contextMenu; }
QModelIndex contextMenuIndex() const { return m_contextMenuIndex; }
void setContextMenuIndex( const QModelIndex& idx ) { m_contextMenuIndex = idx; }
@@ -61,7 +63,7 @@ public slots:
void onItemActivated( const QModelIndex& index );
void playItem();
void addItemsToQueue();
void onMenuTriggered( int action );
protected:
virtual void resizeEvent( QResizeEvent* event );
@@ -77,10 +79,9 @@ protected:
private slots:
void onItemResized( const QModelIndex& index );
void onFilterChanged( const QString& filter );
void copyLink();
void onCustomContextMenu( const QPoint& pos );
private:
QString m_guid;
@@ -96,6 +97,7 @@ private:
QRect m_dropRect;
QModelIndex m_contextMenuIndex;
Tomahawk::ContextMenu* m_contextMenu;
};
#endif // TRACKVIEW_H

View File

@@ -22,6 +22,7 @@
#include <QDebug>
#include <QPainter>
#include <QAbstractItemView>
#include <QHeaderView>
#include "query.h"
#include "result.h"
@@ -30,13 +31,15 @@
#include "treemodelitem.h"
#include "treeproxymodel.h"
#include "artistview.h"
TreeItemDelegate::TreeItemDelegate( QAbstractItemView* parent, TreeProxyModel* proxy )
TreeItemDelegate::TreeItemDelegate( ArtistView* parent, TreeProxyModel* proxy )
: QStyledItemDelegate( (QObject*)parent )
, m_view( parent )
, m_model( proxy )
{
m_nowPlayingIcon = QPixmap( RESPATH "images/now-playing-speaker.png" );
}
@@ -74,8 +77,35 @@ TreeItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
{
QStyleOptionViewItemV4 o( *vioption );
o.palette.setColor( QPalette::Text, textColor );
return QStyledItemDelegate::paint( painter, o, index );
if ( item->isPlaying() )
{
o.palette.setColor( QPalette::Highlight, o.palette.color( QPalette::Mid ) );
o.palette.setColor( QPalette::Text, o.palette.color( QPalette::HighlightedText ) );
o.state |= QStyle::State_Selected;
}
qApp->style()->drawControl( QStyle::CE_ItemViewItem, &o, painter );
{
QRect r = o.rect.adjusted( 3, 0, 0, 0 );
// Paint Now Playing Speaker Icon
if ( item->isPlaying() && m_view->header()->visualIndex( index.column() ) == 0 )
{
r.adjust( 0, 0, 0, -3 );
painter->drawPixmap( r.adjusted( 3, 1, 18 - r.width(), 1 ), m_nowPlayingIcon );
r.adjust( 25, 0, 0, 3 );
}
painter->setPen( o.palette.text().color() );
QTextOption to( Qt::AlignVCenter );
QString text = painter->fontMetrics().elidedText( index.data().toString(), Qt::ElideRight, r.width() - 3 );
painter->drawText( r.adjusted( 0, 1, 0, 0 ), text, to );
}
}
return;
}
else
return;

View File

@@ -23,6 +23,7 @@
#include "dllmacro.h"
class ArtistView;
class TreeProxyModel;
class DLLEXPORT TreeItemDelegate : public QStyledItemDelegate
@@ -30,7 +31,7 @@ class DLLEXPORT TreeItemDelegate : public QStyledItemDelegate
Q_OBJECT
public:
TreeItemDelegate( QAbstractItemView* parent = 0, TreeProxyModel* proxy = 0 );
TreeItemDelegate( ArtistView* parent = 0, TreeProxyModel* proxy = 0 );
protected:
void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
@@ -39,8 +40,10 @@ protected:
// QWidget* createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
private:
QAbstractItemView* m_view;
ArtistView* m_view;
TreeProxyModel* m_model;
QPixmap m_nowPlayingIcon;
};
#endif // TREEITEMDELEGATE_H

Some files were not shown because too many files have changed in this diff Show More