1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-09-20 19:01:34 +02:00

Compare commits

..

124 Commits

Author SHA1 Message Date
Christian Muehlhaeuser
a05972e9ce * Fixed merge. 2011-11-24 02:47:15 +01:00
Christian Muehlhaeuser
5157e13ba1 * Updated ChangeLog. 2011-11-24 01:48:58 +01:00
Christian Muehlhaeuser
9f97afc148 * Updated ChangeLog. 2011-11-24 01:47:48 +01:00
Christian Muehlhaeuser
8b1b0091c6 * Updated ChangeLog. 2011-11-24 01:46:42 +01:00
Christian Muehlhaeuser
3e9aee3687 * Use default locale if translation can't be found. 2011-11-24 01:35:10 +01:00
Christian Muehlhaeuser
48bb0a82f9 * Disable UbuntuUnityHack until it's working properly. 2011-11-24 01:35:03 +01:00
Christian Muehlhaeuser
1efdf38085 * Disable german translation for 0.3.2 release. Needs be updated. 2011-11-24 01:20:01 +01:00
Christian Muehlhaeuser
3e4f4d2f38 * Updated verison to 0.3.2. 2011-11-23 23:31:02 +01:00
Jason Herskowitz
a2f870f2b8 Update changelog 2011-11-23 23:26:35 +01:00
Christian Muehlhaeuser
2ac167d438 * Support .oga files (ogg mimetype). 2011-11-23 23:26:21 +01:00
Christian Muehlhaeuser
c218695a3d * Prevent stuck now playing indicator. 2011-11-23 23:26:13 +01:00
Christian Muehlhaeuser
fae5f1dbbe * Should hopefully fix Windows SettingsDialog. 2011-11-23 23:25:57 +01:00
Christian Muehlhaeuser
54d29cc05d * Try fixing SettingsDialog on Windows. 2011-11-23 23:25:45 +01:00
Christian Muehlhaeuser
5aea02def2 * Forgot to rename crash reporter in one more place. 2011-11-23 23:25:35 +01:00
Christian Muehlhaeuser
368aa20b75 * Updated new crash reporter binary name in release scripts. 2011-11-23 23:25:26 +01:00
Christian Muehlhaeuser
d2a07f2b6c * Call ensurePolished before creating buttons in SettingsDialog. 2011-11-23 23:25:08 +01:00
Christian Muehlhaeuser
14253a9c66 * DRY: Cleaned up DropJob / ShortenedLinkParser & handling spoti.fi urls now. 2011-11-23 23:25:02 +01:00
Christian Muehlhaeuser
6881f4218a * Moved charts & spotify parser to port 80. 2011-11-23 23:23:57 +01:00
Christian Muehlhaeuser
17badb972e * Prevented over-zealous assert in PlaylistModel. 2011-11-23 23:23:50 +01:00
Christian Muehlhaeuser
2ea09dd60d * Merged version check. 2011-11-23 23:22:00 +01:00
Christian Muehlhaeuser
87f7b6b2c6 * Made sure we don't duplicate connections in WelcomeWidget. 2011-11-23 23:15:52 +01:00
Christian Muehlhaeuser
01986a4129 * Use the proper color for selected playlist items on the Dashboard. 2011-11-23 23:15:43 +01:00
Christian Muehlhaeuser
2b404b517f * Use the proper highlight color for painting hovered artist names in the AlbumItemDelegate. 2011-11-23 23:15:32 +01:00
Christian Muehlhaeuser
b21b2d10f7 * Update SourceInfoWidget when collection changes. 2011-11-23 23:15:22 +01:00
Christian Muehlhaeuser
04deaba788 * Less furious logging. 2011-11-23 23:15:10 +01:00
Christian Muehlhaeuser
5cabc62733 * Update recent additions on welcome page whenever a collection changes. 2011-11-23 23:15:02 +01:00
Kuba Serafinowski
01c6c3f0b6 moar strings to translate! 2011-11-23 23:14:42 +01:00
Kuba Serafinowski
b1a5cd4dcb remove unneeded strings 2011-11-23 23:14:28 +01:00
Kuba Serafinowski
58f78725db tiny typo fix 2011-11-23 23:14:11 +01:00
Jeff Mitchell
4210e8eab8 Hopefully fix a case where the seek slider travels on when Phonon is
buffering
2011-11-23 23:13:49 +01:00
Thierry Goeckel
115492d1cc Enhance version upgrading to include a third point. 2011-11-23 23:13:21 +01:00
Leo Franchi
edadbb0c95 Fix loading XSPFs with spaces in their name. 2011-11-23 23:13:11 +01:00
Christian Muehlhaeuser
6c67dfcab7 * Revert back to using system locale. 2011-11-23 23:12:50 +01:00
Christian Muehlhaeuser
b9453ab77b * Add a default english translation. Fallback to 'en' if locale is set to 'C'. 2011-11-23 23:12:39 +01:00
Christian Muehlhaeuser
9507ffdd86 * Fixed translation issue in TomahawkUtils. 2011-11-23 23:12:26 +01:00
Christian Muehlhaeuser
ff768954f6 * Fixed window title in AudioControls. 2011-11-23 23:12:17 +01:00
Christian Muehlhaeuser
15729bb66a * Increased size of Get-New-Resolvers dialog. 2011-11-23 23:12:01 +01:00
Christian Muehlhaeuser
41f46aaeea * Cleanup scanner if there were no new and no obsolete tracks found. 2011-11-23 23:11:53 +01:00
Christian Muehlhaeuser
9e0d884f80 * Merge musicscanner changes into stable. 2011-11-23 23:11:16 +01:00
Christian Muehlhaeuser
d34491b85f * Re-enable grouping of dynamic playlist revisions. 2011-11-23 23:10:34 +01:00
Christian Muehlhaeuser
45070fb4e1 * Remove bottom label of steering controls. Changes now take effect on clicking the apply button. 2011-11-23 23:10:27 +01:00
Christian Muehlhaeuser
18612b48d3 * Don't remove current index when restarting a track by activating it directly.
* Don't create new playlist revisions for a list that doesn't belong to you.
2011-11-23 23:10:18 +01:00
Christian Muehlhaeuser
a38c0a544d * Fixed crashing on playing from queue. 2011-11-23 23:10:06 +01:00
Christian Muehlhaeuser
d38c9730fb * Merge into stable. 2011-11-23 23:09:32 +01:00
Christian Muehlhaeuser
d25320833c * Merged into stable. 2011-11-23 23:06:02 +01:00
Christian Muehlhaeuser
d38600dd6a * Don't overwrite friendlyname with an empty one. 2011-11-23 23:05:23 +01:00
Christian Muehlhaeuser
6fa48587e1 * Assert on empty friendlynames. 2011-11-23 23:05:12 +01:00
Leo Franchi
8da0f3e9a3 * Merged into stable. 2011-11-23 23:04:58 +01:00
Kilian Lackhove
ab402c0867 fix xspf import QFileDialog filter 2011-11-23 23:00:43 +01:00
Kuba Serafinowski
545a915439 fix TWK-583 for jabber too 2011-11-23 23:00:31 +01:00
Kuba Serafinowski
d026902d91 fix for TWK-583 2011-11-23 23:00:25 +01:00
Hugo Lindström
ff72157c5f Fix for broken compile 2011-11-23 23:00:05 +01:00
Christian Muehlhaeuser
faab306dbe * Merged friendlyname fixes. 2011-11-23 22:59:57 +01:00
Christian Muehlhaeuser
57fef9f3f2 * Fixed WelcomeWidget. 2011-11-23 22:57:44 +01:00
Leo Franchi
89fac77951 Fix one compile error 2011-11-23 22:57:36 +01:00
Christian Muehlhaeuser
ef02e9b4ac * Refactored Track-, Collection-, PlaylistModel. 2011-11-23 22:57:24 +01:00
Leo Franchi
99b09c1faa Increment job count when creating a new xspf job 2011-11-23 22:55:17 +01:00
Kuba Serafinowski
d66e86f5c6 make the string extract with lupdate 2011-11-23 22:54:59 +01:00
Kuba Serafinowski
9bd46984e0 match the text with buttons in the dialog 2011-11-23 22:54:51 +01:00
Hugo Lindström
3992392245 * Merge appending XSPFs. 2011-11-23 22:54:32 +01:00
Hugo Lindström
198e92bc2c Fix for local xspf dropjob, also allow remotes 2011-11-23 22:53:22 +01:00
Kuba Serafinowski
2f899eed2a fix misleading cmake message 2011-11-23 22:52:49 +01:00
Jeff Mitchell
8cdd4bdea3 Do the connection name fixing in a different way; always end up with a
QHostAddress.
2011-11-23 22:52:39 +01:00
Jeff Mitchell
3d53b0c251 Remove some debugging 2011-11-23 22:52:23 +01:00
Jeff Mitchell
0ac9512eb9 Lots of debug and half the fixes for fixing hostnames 2011-11-23 22:52:15 +01:00
Jeff Mitchell
3f0ac7c666 * Merge application proxy factory. 2011-11-23 22:52:13 +01:00
Christian Muehlhaeuser
faf7d00fdd * Fixed TWK-579: Proper default width for the sidebar. 2011-11-23 22:50:32 +01:00
Christian Muehlhaeuser
b31abb0979 * This should fix sources being stuck in 'Parsing'. 2011-11-23 22:50:25 +01:00
Thierry Göckel
f2009cf99b Fix returning of external IP address for some routers. 2011-11-23 22:49:29 +01:00
Hugo Lindström
0d97a47cc5 Add cache for all charts. Later on move spotify and hypem to charts api. 2011-11-23 22:49:17 +01:00
Hugo Lindström
7db6beb896 Adding cache for charts 2011-11-23 22:48:54 +01:00
Christian Muehlhaeuser
e56a629ad7 * Fixed negative time values showing up in GUI. 2011-11-23 22:48:28 +01:00
Christian Muehlhaeuser
ef918bbbcf * Make SetPlaylistRevision DBCmds groupable. 2011-11-23 22:48:13 +01:00
Christian Muehlhaeuser
60911ab887 * Set stats for the right collection. 2011-11-23 22:47:49 +01:00
Christian Muehlhaeuser
e10a96ecd5 * Merged groupable db-commands. 2011-11-23 22:47:17 +01:00
Christian Muehlhaeuser
e99973925a * Merged improved collection syncing. 2011-11-23 22:45:52 +01:00
Dominik Schmidt
949c6f6341 Unbreak FindCLucene for Fedora 16 and openSUSE Factory. 2011-11-23 06:35:39 +01:00
Dominik Schmidt
e041723ffc Install CrashReporter 2011-11-23 06:07:54 +01:00
Christian Muehlhaeuser
89919928da * Look for CrashReporter in local and global dirs. 2011-11-23 05:49:34 +01:00
Leo Franchi
d4fc504f3d Add a 0.3.2 changelog 2011-11-20 22:52:11 -05:00
Leo Franchi
05924b8deb TWK-531: Show (-) on new item after deleting an item 2011-11-20 22:43:20 -05:00
Leo Franchi
6d4aa50596 Clear upcoming station tracks when steering, and re-fetch two 2011-11-20 22:43:08 -05:00
Leo Franchi
7ee2755617 use QFileSystemModel instead of deprecated QDirModel, and show /Volumes on mac 2011-11-20 22:43:00 -05:00
Leo Franchi
35406ceb5a Use plugins/ instead of PlugIns/ as vlc hard-codes it internally. 2011-11-20 22:42:52 -05:00
Leo Franchi
9efb536e55 Show tooltip with full text in job view 2011-11-20 22:42:30 -05:00
Leo Franchi
b8d27f1811 Make clicking back to current track work on dashboard, charts, and artist/album pages 2011-11-20 22:42:23 -05:00
Leo Franchi
0939ba0705 Don't show speaker next to a playlist if not paused or playing 2011-11-20 22:42:03 -05:00
Leo Franchi
3788bc7cbf Always clear spinner when no albums found to load in albumview 2011-11-20 22:41:52 -05:00
Leo Franchi
54723abc07 Only show JS errors in tomahawk debug builds 2011-11-20 22:41:36 -05:00
Leo Franchi
900f57437f Put delcaration in ifdef 2011-11-20 22:40:51 -05:00
Leo Franchi
300c9d5d68 Automatically upgrade resolvers 2011-11-20 22:40:44 -05:00
Leo Franchi
96c9996284 Set the timer with track duration calculated in 2011-11-17 09:49:43 -05:00
Leo Franchi
8a15bcaa66 fix rdio track loading 2011-11-17 09:49:16 -05:00
Leo Franchi
d17d67869c Add an "apply steering" button to make it clearer how to steer
Remove some super spammy debug
2011-11-17 09:49:11 -05:00
Leo Franchi
c491f33ce4 Manually replace + with " " as QUrl::queryItems doesn't do it for us... 2011-11-17 09:49:06 -05:00
Leo Franchi
1dee5c809c Don't hook up signals twice for loading xspf 2011-11-17 09:49:00 -05:00
Leo Franchi
924ede61b4 Make surer to show playlist once loaded 2011-11-17 09:48:52 -05:00
Leo Franchi
0d64d9c42d Don't show drop indicator for playlists in sidebar and always create new ones 2011-11-17 09:48:44 -05:00
Leo Franchi
6b6fb909cd Make source visible in audiocontrols on os x 2011-11-17 09:48:35 -05:00
Leo Franchi
b51ff46085 Don't create QNRs for null urls, let audioengine handle it properly 2011-11-17 09:48:07 -05:00
Leo Franchi
46ec23990f Revert "Skip to next track if we have a QNR and it emits a failed signal"
This reverts commit 9418fd0fb8.
2011-11-17 09:47:59 -05:00
Jeff Mitchell
eb46feac2c Handle the worker/cache threads better in InfoSystem, and re-enable
deletion on shutdown, so we can test in windows nightlies.
2011-11-16 20:19:13 -05:00
Leo Franchi
2c206f4193 Shrink font for playlist author 2011-11-14 18:07:56 -05:00
Leo Franchi
c1bd19b35b Don't accept button press events as well as release when handling latches 2011-11-14 18:06:58 -05:00
Jeff Mitchell
370154cc46 hacky fix for Jreen needing the application proxy set. Really we need to
get them to accept their own QNAM
2011-11-14 18:06:50 -05:00
Leo Franchi
9a81ce8b89 Add 0.3.1 fixes to Changelog 2011-11-13 14:07:37 -05:00
Christian Muehlhaeuser
c805d283d4 * Updated ChangeLog and bumped version to 0.3.1. 2011-11-13 19:25:53 +01:00
Christian Muehlhaeuser
03379f361c * Force an index update after 0.3.1 upgrade. 2011-11-13 19:19:36 +01:00
Christian Muehlhaeuser
c671c0e898 * 'Fixed' Windows shutdown crash. 2011-11-13 19:19:25 +01:00
Christian Muehlhaeuser
edaf49b4c5 * Fixed creating index when there is only a local source. 2011-11-13 19:19:02 +01:00
Christian Muehlhaeuser
682903b0cb * Prevent watch for changes interfering with running scan. 2011-11-13 19:18:49 +01:00
Dominik Schmidt
53f7f599d5 Update ChangeLog 2011-11-13 17:31:16 +01:00
Dominik Schmidt
cc669fc20f Remove unneccessary toString conversion 2011-11-13 17:26:43 +01:00
Dominik Schmidt
4e7496a38a Search for *_tomahawkresolver in CMAKE_INSTALL_LIBEXECDIR 2011-11-13 15:40:39 +01:00
Leo Franchi
5842cdceee Only do setenv on linux, that's theonly time we'll have unity anyway
(cherry picked from commit 09a7d790ad)
2011-11-12 10:04:31 -05:00
Leo Franchi
b7e0be8d9d Hide red latch headphones on local source if the source you are latched on to goes offline
(cherry picked from commit d49a43709d)
2011-11-12 10:04:25 -05:00
Leo Franchi
a203b60cbb Add Unity systray hack from Clementine.
(cherry picked from commit 96fe10cc9f)
2011-11-12 10:04:20 -05:00
Leo Franchi
2be08af321 Draw the author name as well as avatar in recent playlists
(cherry picked from commit 2a27cbde0d)
2011-11-12 10:04:12 -05:00
Leo Franchi
ad4c229a6b Don't show in global menu in unity. Thanks davidsansome :)
(cherry picked from commit 1f10444d5c)
2011-11-12 10:04:06 -05:00
Leo Franchi
b2e0206e34 Be a bit more resilient in setting the playlist to rename after creating
(cherry picked from commit 1bb8ff97d4)
2011-11-12 10:04:00 -05:00
Leo Franchi
743ae013ea Don't select a temp item when deleting it
(cherry picked from commit 518546b525)
2011-11-12 10:03:54 -05:00
Leo Franchi
767cf7c1b9 Hide warning
(cherry picked from commit 17e1003714)
2011-11-12 10:03:47 -05:00
Leo Franchi
6be94ab81c Stop the timer on new track starting
(cherry picked from commit 3c024ab7ac)
2011-11-12 10:02:03 -05:00
Leo Franchi
b1ed304a61 Fix crash on Sparkle update when binary is replaced.
(cherry picked from commit f9b5bda925)
2011-11-11 11:04:30 -05:00
872 changed files with 23340 additions and 99441 deletions

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "thirdparty/jreen"]
path = thirdparty/jreen
url = git://github.com/euroelessar/jreen.git

View File

@@ -1,9 +0,0 @@
[main]
host = https://www.transifex.net
[tomahawk.tomahawk-master]
file_filter = lang/tomahawk_<lang>.ts
source_file = lang/tomahawk_en.ts
source_lang = en
type = QT

View File

@@ -1,7 +1,10 @@
PROJECT( tomahawk )
CMAKE_MINIMUM_REQUIRED( VERSION 2.8.6 )
CMAKE_MINIMUM_REQUIRED( VERSION 2.8 )
SET( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules" )
CMAKE_POLICY(SET CMP0017 NEW)
IF( ${CMAKE_VERSION} VERSION_GREATER 2.8.3 )
CMAKE_POLICY(SET CMP0017 NEW)
ENDIF( ${CMAKE_VERSION} VERSION_GREATER 2.8.3 )
###
### Tomahawk application info
@@ -12,31 +15,15 @@ SET( TOMAHAWK_APPLICATION_NAME "Tomahawk" )
SET( TOMAHAWK_DESCRIPTION_SUMMARY "The social media player" )
SET( TOMAHAWK_VERSION_MAJOR 0 )
SET( TOMAHAWK_VERSION_MINOR 4 )
SET( TOMAHAWK_VERSION_PATCH 99 )
SET( TOMAHAWK_VERSION_MINOR 3 )
SET( TOMAHAWK_VERSION_PATCH 2 )
#SET( TOMAHAWK_VERSION_RC 0 )
# enforce proper symbol exporting on all platforms
add_definitions( "-fvisibility=hidden" )
# build options
option(BUILD_GUI "Build Tomahawk with GUI" ON)
option(BUILD_RELEASE "Generate TOMAHAWK_VERSION without GIT info" OFF)
option(WITH_BREAKPAD "Build with breakpad integration" ON)
option(WITH_CRASHREPORTER "Build with CrashReporter" ON)
option(LEGACY_KDE_INTEGRATION "Install tomahawk.protocol file, deprecated since 4.6.0" OFF)
IF( CMAKE_SYSTEM_PROCESSOR MATCHES "arm" )
message(STATUS "Build of breakpad library disabled on this platform.")
SET(WITH_BREAKPAD OFF)
SET(WITH_CRASHREPORTER OFF)
ENDIF()
# add definitions based on build options
IF(WITH_BREAKPAD)
message(STATUS "Build with support for breakpad.")
ENDIF()
# generate version string
@@ -50,7 +37,7 @@ ENDIF()
IF( NOT BUILD_RELEASE )
INCLUDE( CMakeDateStamp )
SET( TOMAHAWK_VERSION_DATE "${CMAKE_DATESTAMP_YEAR}${CMAKE_DATESTAMP_MONTH}${CMAKE_DATESTAMP_DAY}" )
IF( TOMAHAWK_VERSION_DATE GREATER 0)
IF( ${TOMAHAWK_VERSION_DATE} GREATER 0)
SET( TOMAHAWK_VERSION ${TOMAHAWK_VERSION}.${TOMAHAWK_VERSION_DATE} )
ENDIF()
@@ -67,9 +54,6 @@ SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" )
SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" )
SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" )
# make predefined install dirs available everywhere
INCLUDE(GNUInstallDirs)
# installer creation
INCLUDE( TomahawkCPack.cmake )
@@ -84,7 +68,7 @@ IF( NOT BUILD_GUI )
MESSAGE( STATUS "Building Tomahawk ${TOMAHAWK_VERSION} in HEADLESS mode ***" )
ELSE()
MESSAGE( STATUS "Building Tomahawk ${TOMAHAWK_VERSION} full GUI version ***" )
LIST(APPEND NEEDED_QT4_COMPONENTS "QtGui" "QtWebkit" "QtUiTools" )
LIST(APPEND NEEDED_QT4_COMPONENTS "QtGui" "QtWebkit" )
ENDIF()
IF( BUILD_GUI AND UNIX AND NOT APPLE )
@@ -92,7 +76,7 @@ IF( BUILD_GUI AND UNIX AND NOT APPLE )
ENDIF()
macro_optional_find_package(Qt4 4.7.0 COMPONENTS ${NEEDED_QT4_COMPONENTS} )
macro_log_feature(QT4_FOUND "Qt" "A cross-platform application and UI framework" "http://qt.nokia.com" TRUE "" "If you see this, although libqt4-devel is installed, check whether the \n qtwebkit-devel package and whatever contains QtUiTools is installed too")
macro_log_feature(QT4_FOUND "Qt" "A cross-platform application and UI framework" "http://qt.nokia.com" TRUE "" "If you see this, although libqt4-devel is installed, check whether \n the qtwebkit-devel package is installed as well")
macro_optional_find_package(Phonon 4.5.0)
macro_log_feature(PHONON_FOUND "Phonon" "The Phonon multimedia library" "http://phonon.kde.org" TRUE "" "")
@@ -121,16 +105,22 @@ macro_optional_find_package(QCA2)
macro_log_feature(QCA2_FOUND "QCA2" "Provides encryption and signing functions required for Grooveshark resolver" "http://delta.affinix.com/qca/" FALSE "" "")
macro_optional_find_package(LibAttica)
macro_log_feature(LIBATTICA_FOUND "libattica" "Provides support for automatic fetching and managing of resolvers from the tomahawk website" "https://projects.kde.org/projects/kdesupport/attica" TRUE "" "")
macro_log_feature(LIBATTICA_FOUND "libattica" "Provides support for automatic fetching and managing of resolvers from the tomahawk website" "https://projects.kde.org/projects/kdesupport/attica" FALSE "" "")
macro_optional_find_package(QuaZip)
macro_log_feature(QuaZip_FOUND "QuaZip" "Provides support for extracting downloaded resolvers automatically." "http://quazip.sourceforge.net/" TRUE "" "")
macro_log_feature(QuaZip_FOUND "QuaZip" "Provides support for extracting downloaded resolvers automatically." "http://quazip.sourceforge.net/" FALSE "" "")
macro_optional_find_package(Jreen 1.0.5)
macro_log_feature(JREEN_FOUND "Jreen" "Qt XMPP Library" "http://qutim.org/jreen / https://github.com/euroelessar/jreen" FALSE "" "Jreen is needed for the Jabber SIP plugin.\n")
IF( NOT QuaZip_FOUND )
add_subdirectory( ${CMAKE_SOURCE_DIR}/src/libtomahawk/thirdparty/quazip )
SET( QuaZip_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/libtomahawk/thirdparty/quazip )
SET( QuaZip_LIBRARY quazip )
SET( QuaZip_LIBRARIES ${QuaZip_LIBRARY} )
SET( QuaZip_FOUND true )
macro_log_feature(QuaZip_FOUND "QuaZip" "Provides support for extracting downloaded resolvers automatically. Building internal copy" "http://quazip.sourceforge.net/" FALSE "" "")
macro_optional_find_package(QTweetLib)
macro_log_feature(QTWEETLIB_FOUND "QTweetLib" "Qt Twitter Library" "https://github.com/minimoog/QTweetLib" FALSE "" "QTweetLib is needed for the Twitter SIP plugin.\n")
# copy headers to build/quazip so we can use proper includes inside the code
FILE( COPY ${CMAKE_SOURCE_DIR}/src/libtomahawk/thirdparty/quazip/quazip/ DESTINATION ${CMAKE_BINARY_DIR}/libtomahawk/thirdparty/quazip )
ENDIF()
# required
#While we distribute our own liblastfm2, don't need to look for it
@@ -139,17 +129,29 @@ macro_log_feature(QTWEETLIB_FOUND "QTweetLib" "Qt Twitter Library" "https://gith
set(LIBLASTFM_FOUND true)
#### submodules start
# automatically init submodules here, don't delete this code we may add submodules again
# this installs headers and such and should really be handled in a separate package by packagers
IF( INTERNAL_JREEN )
IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.gitmodules)
EXECUTE_PROCESS(COMMAND git submodule init WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
EXECUTE_PROCESS(COMMAND git submodule update WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
ENDIF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.gitmodules)
ENDIF()
# IF( FALSE )
# IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.gitmodules)
# EXECUTE_PROCESS(COMMAND git submodule init WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
# EXECUTE_PROCESS(COMMAND git submodule update WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} )
# ENDIF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.gitmodules)
# ENDIF()
IF( INTERNAL_JREEN )
ADD_SUBDIRECTORY( ${THIRDPARTY_DIR}/jreen )
SET( LIBJREEN_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/thirdparty/jreen/include )
SET( LIBJREEN_LIBRARY jreen )
SET( LIBJREEN_LIBRARIES ${LIBJREEN_LIBRARY} )
SET( LIBJREEN_FOUND true )
MESSAGE(STATUS "INTERNAL libjreen: ${LIBJREEN_INCLUDE_DIR}, ${LIBJREEN_LIBRARY}")
ELSE( INTERNAL_JREEN )
macro_optional_find_package(Jreen)
ENDIF( INTERNAL_JREEN )
macro_log_feature(LIBJREEN_FOUND "Jreen" "Qt XMPP Library" "https://github.com/euroelessar/jreen" FALSE "" "Jreen is needed for the Jabber SIP plugin. \n\n Use -DINTERNAL_JREEN=ON to build the git submodule inside Tomahawk \n Be aware this installs a full jreen with headers and everything!\n")
macro_optional_find_package(QTweetLib)
macro_log_feature(QTWEETLIB_FOUND "QTweetLib" "Qt Twitter Library" "https://github.com/minimoog/QTweetLib" FALSE "" "QTweetLib is needed for the Twitter SIP plugin.\n")
#### submodules end
### libportfwd
@@ -210,3 +212,7 @@ ADD_SUBDIRECTORY( src/libtomahawk )
SET( TOMAHAWK_LIBRARIES tomahawklib )
ADD_SUBDIRECTORY( src )
ADD_SUBDIRECTORY( admin )
IF( NOT DISABLE_CRASHREPORTER )
ADD_SUBDIRECTORY( src/breakpad/CrashReporter )
ENDIF()

View File

@@ -1,99 +0,0 @@
MACRO(PARSE_ARGUMENTS prefix arg_names option_names)
SET(DEFAULT_ARGS)
FOREACH(arg_name ${arg_names})
SET(${prefix}_${arg_name})
ENDFOREACH(arg_name)
FOREACH(option ${option_names})
SET(${prefix}_${option} FALSE)
ENDFOREACH(option)
SET(current_arg_name DEFAULT_ARGS)
SET(current_arg_list)
FOREACH(arg ${ARGN})
SET(larg_names ${arg_names})
LIST(FIND larg_names "${arg}" is_arg_name)
IF (is_arg_name GREATER -1)
SET(${prefix}_${current_arg_name} ${current_arg_list})
SET(current_arg_name ${arg})
SET(current_arg_list)
ELSE (is_arg_name GREATER -1)
SET(loption_names ${option_names})
LIST(FIND loption_names "${arg}" is_option)
IF (is_option GREATER -1)
SET(${prefix}_${arg} TRUE)
ELSE (is_option GREATER -1)
SET(current_arg_list ${current_arg_list} ${arg})
ENDIF (is_option GREATER -1)
ENDIF (is_arg_name GREATER -1)
ENDFOREACH(arg)
SET(${prefix}_${current_arg_name} ${current_arg_list})
ENDMACRO(PARSE_ARGUMENTS)
MACRO(CAR var)
SET(${var} ${ARGV1})
ENDMACRO(CAR)
MACRO(CDR var junk)
SET(${var} ${ARGN})
ENDMACRO(CDR)
macro(add_tomahawk_plugin)
parse_arguments(PLUGIN
"SOURCES;UI;LINK_LIBRARIES;TYPE;EXPORT_MACRO;COMPILE_DEFINITIONS"
"NO_INSTALL"
${ARGN}
)
car(PLUGIN_NAME ${PLUGIN_DEFAULT_ARGS})
# message("*** Arguments for ${PLUGIN_NAME}")
# message("Sources: ${PLUGIN_SOURCES}")
# message("Link libraries: ${PLUGIN_LINK_LIBRARIES}")
# message("UI: ${PLUGIN_UI}")
# message("TYPE: ${PLUGIN_TYPE}")
# message("EXPORT_MACRO: ${PLUGIN_EXPORT_MACRO}")
# create target name once for convenience
set(target "tomahawk_${PLUGIN_TYPE}_${PLUGIN_NAME}")
# qt stuff
include_directories(${CMAKE_CURRENT_BINARY_DIR})
if(PLUGIN_UI)
qt4_wrap_ui(PLUGIN_UI_SOURCES ${PLUGIN_UI})
list(APPEND PLUGIN_SOURCES ${PLUGIN_UI_SOURCES})
endif()
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/resources.qrc")
qt4_add_resources(PLUGIN_RC_SOURCES "resources.qrc")
list(APPEND PLUGIN_SOURCES ${PLUGIN_RC_SOURCES})
unset(PLUGIN_RC_SOURCES)
endif()
# add target
add_library(${target} MODULE ${PLUGIN_SOURCES})
# definitions - can this be moved into set_target_properties below?
add_definitions(${QT_DEFINITIONS})
set_target_properties(${target} PROPERTIES AUTOMOC TRUE COMPILE_DEFINITIONS ${PLUGIN_EXPORT_MACRO})
if(PLUGIN_COMPILE_DEFINITIONS)
# Dear CMake, i hate you! Sincerely, domme
# At least in CMake 2.8.8, you CANNOT set more than one COMPILE_DEFINITIONS value
# only takes the first one if called multiple times or bails out with wrong number of arguments
# when passing in a list, thus i redefine the export macro here in hope it won't mess up other targets
add_definitions( "-D${PLUGIN_EXPORT_MACRO}" )
set_target_properties(${target} PROPERTIES COMPILE_DEFINITIONS ${PLUGIN_COMPILE_DEFINITIONS})
endif()
# add link targets
target_link_libraries(${target} tomahawklib)
if(PLUGIN_LINK_LIBRARIES)
target_link_libraries(${target} ${PLUGIN_LINK_LIBRARIES})
endif()
# make installation optional, maybe useful for dummy plugins one day
if(NOT PLUGIN_NO_INSTALL)
include(GNUInstallDirs)
install(TARGETS ${target} DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
endmacro()

View File

@@ -5,32 +5,40 @@
# LIBJREEN_LIBRARY, the path to libjreen
# LIBJREEN_FOUND, whether libjreen was found
FIND_PACKAGE(PkgConfig QUIET)
PKG_CHECK_MODULES(PC_JREEN QUIET libjreen)
FIND_PATH(JREEN_INCLUDE_DIR NAMES jreen/jreen.h
HINTS
${PC_JREEN_INCLUDEDIR}
${PC_JREEN_INCLUDE_DIRS}
${CMAKE_INSTALL_INCLUDEDIR}
${KDE4_INCLUDE_DIR}
find_path(LIBJREEN_INCLUDE_DIR NAMES jreen/jreen.h
HINTS
~/usr/include
/opt/local/include
/usr/include
/usr/local/include
/opt/kde4/include
${CMAKE_INSTALL_PREFIX}/include
${KDE4_INCLUDE_DIR}
)
FIND_LIBRARY(JREEN_LIBRARIES NAMES jreen
HINTS
${PC_JREEN_LIBDIR}
${PC_JREEN_LIBRARY_DIRS}
${CMAKE_INSTALL_LIBDIR}
${KDE4_LIB_DIR}
find_library( LIBJREEN_LIBRARY NAMES jreen
PATHS
~/usr/lib
/opt/local/lib
/usr/lib
/usr/lib64
/usr/local/lib
/opt/kde4/lib
${CMAKE_INSTALL_PREFIX}/lib
${CMAKE_INSTALL_PREFIX}/lib64
${KDE4_LIB_DIR}
)
IF(JREEN_LIBRARIES AND JREEN_INCLUDE_DIR AND NOT PC_JREEN_VERSION)
MESSAGE(WARNING "You don't have pkg-config and so the Jreen version check does not work!")
ENDIF()
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Jreen
REQUIRED_VARS JREEN_LIBRARIES JREEN_INCLUDE_DIR
VERSION_VAR PC_JREEN_VERSION)
if(LIBJREEN_INCLUDE_DIR AND LIBJREEN_LIBRARY)
set(LIBJREEN_FOUND TRUE)
message(STATUS "Found libjreen: ${LIBJREEN_INCLUDE_DIR}, ${LIBJREEN_LIBRARY}")
else(LIBJREEN_INCLUDE_DIR AND LIBJREEN_LIBRARY)
set(LIBJREEN_FOUND FALSE)
if (LIBJREEN_FIND_REQUIRED)
message(FATAL_ERROR "Could NOT find required package libjreen")
endif(LIBJREEN_FIND_REQUIRED)
endif(LIBJREEN_INCLUDE_DIR AND LIBJREEN_LIBRARY)
MARK_AS_ADVANCED(JREEN_INCLUDE_DIR JREEN_LIBRARIES)
mark_as_advanced(LIBJREEN_INCLUDE_DIR LIBJREEN_LIBRARY)

View File

@@ -38,9 +38,7 @@ else (QCA2_INCLUDE_DIR AND QCA2_LIBRARIES)
find_path(QCA2_INCLUDE_DIR qca.h
HINTS ${PC_QCA2_INCLUDEDIR} ${PC_QCA2_INCLUDE_DIRS}
PATH_SUFFIXES QtCrypto
PATHS /usr/local/lib/qca.framework/Headers/
)
PATH_SUFFIXES QtCrypto)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(QCA2 DEFAULT_MSG QCA2_LIBRARIES QCA2_INCLUDE_DIR)

View File

@@ -56,7 +56,7 @@ ELSE()
include(FindLibraryWithDebug)
include(FindPackageHandleStandardArgs)
find_path(TAGLIB_INCLUDES
find_path(TAGLIB_CFLAGS
NAMES
tag.h
PATH_SUFFIXES taglib

View File

@@ -28,8 +28,8 @@
; We use official release plugins
; mingw32-vlc from obs misses a lot and has even broken ones probably
!define VLC_PATH "${SOURCE_PATH}\admin\win\vlc\" ; SIC! ^
!define VLC_BIN "${VLC_PATH}"
!define VLC_PATH "${SOURCE_PATH}\admin\win\vlc\prefix" ; SIC! ^
!define VLC_BIN "${VLC_PATH}\bin"
!define VLC_PLUGIN_PATH "${VLC_BIN}\plugins"
!define NSI_PATH "${SOURCE_PATH}/admin/win/nsi"
@@ -279,9 +279,9 @@ Section "Tomahawk Player" SEC_TOMAHAWK_PLAYER
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\libquazip.dll"
File "${INSTALL_PATH}\bin\libtomahawklib.dll"
; plugins
File "${INSTALL_PATH}\lib\libtomahawk_*_*.dll"
File "${INSTALL_PATH}\lib\libtomahawk_sip*.dll"
!endif
!ifndef INSTALL_PATH
;Main executable.
@@ -294,8 +294,8 @@ Section "Tomahawk Player" SEC_TOMAHAWK_PLAYER
File "${BUILD_PATH}\libqxtweb-standalone.dll"
File "${BUILD_PATH}\libtomahawk_portfwd.dll"
File "${BUILD_PATH}\libtomahawk_lastfm2.dll"
; plugins
File "${BUILD_PATH}\libtomahawk_*_*.dll"
File "${BUILD_PATH}\libquazip.dll"
File "${BUILD_PATH}\libtomahawk_sip*.dll"
!endif
;License & release notes.
@@ -307,10 +307,8 @@ Section "Tomahawk Player" SEC_TOMAHAWK_PLAYER
File "${QT_DLL_PATH}\QtGui4.dll"
File "${QT_DLL_PATH}\QtNetwork4.dll"
File "${QT_DLL_PATH}\QtSql4.dll"
File "${QT_DLL_PATH}\QtScript4.dll"
File "${QT_DLL_PATH}\QtUiTools4.dll"
File "${QT_DLL_PATH}\QtWebKit4.dll"
File "${QT_DLL_PATH}\QtXml4.dll"
File "${QT_DLL_PATH}\QtWebKit4.dll"
;SQLite driver
SetOutPath "$INSTDIR\sqldrivers"
@@ -331,17 +329,30 @@ Section "Tomahawk Player" SEC_TOMAHAWK_PLAYER
File "${MING_BIN}\libstdc++-6.dll"
;Phonon stuff
File "${MING_BIN}\libphonon.dll"
;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 "${VLC_BIN}\libphonon.dll"
SetOutPath "$INSTDIR\phonon_backend"
File "${VLC_BIN}\phonon_backend\phonon_vlc.dll"
SetOutPath "$INSTDIR"
;VLC
;SetOutPath "$INSTDIR\phonon_backend"
File "${VLC_BIN}\libvlc.dll"
File "${VLC_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"
@@ -352,7 +363,6 @@ Section "Tomahawk Player" SEC_TOMAHAWK_PLAYER
File "${MING_BIN}\libechonest.dll"
File "${MING_BIN}\libQTweetLib.dll"
File "${MING_BIN}\libquazip.dll"
; Jabber
File "${MING_BIN}\libjreen.dll"
@@ -457,8 +467,7 @@ Section -post
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Tomahawk" "NoRepair" "1"
; Register tomahawk:// protocol handler
WriteRegStr HKCR "tomahawk" "" "URL:Tomahawk Protocol"
WriteRegStr HKCR "tomahawk" "URL Protocol" ""
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"'

View File

@@ -1,78 +1,3 @@
Version 0.5.0:
* Added "Stop playback after this track" context menu items.
* You can now import your entire Last.fm playback history into Tomahawk.
* Support for multimedia keys (Play, Pause, Next etc.) on Windows & Linux.
* When listening privately scrobbling to Last.fm is now disabled.
* Added a toolbar with page back / forward buttons and the global search.
* New grid view with direct playback controls.
* Added a track page showing a song's lyrics and other similar tracks.
* Separate Loved Tracks and Recently Played views per source.
Version 0.4.2:
* Fix ZeroConf protocol showing IP addresses instead of host names.
* Updated translations for various languages.
* Resuming playback restores correct volume settings.
* Reduced CPU usage during playback.
* Fixed not starting up due to case sensitivity issue on OS X.
* Fixed volume issue (too quiet) on Windows.
Version 0.4.1:
* Fixed various crashes.
* Fixed issues with auto-updating XSPF playlists.
* Double-clicking a playlist starts playing it.
* Resolvers can now return disc number and album position for results.
* Fixed sorting playlists by track number.
* Fixed issues with changing proxy.
* Fixed Twitter authentication issues.
* Fixed Grooveshark support on Windows.
Version 0.4.0:
* Added visual notification for database indexing job.
* Fixed icons not appearing in resolvers list.
* Fixed various UI glitches and stray error messages in stations.
* Fixed bug where album page would resolve bottom-to-top.
* Fixed bug where Footnotes would not update when changing selected album.
* Fixed dragging albums and artists from charts, album, and artist views.
* Fixed bug where filter text would be one step behind filter value.
* Fixed bug where resolvers would enable themselves after auto-updating.
* Fixed occasional crash when dropping tracks onto New Station item.
* Added jump-to-current-track support for search results page.
* Fixed non-resolving tracks when dragging from album view.
* Fixed fetching album covers for albums with special characters.
* Show errors and continue gracefully when resolved audio is not available.
* Fixed various crashes on exit.
* Added basic command-line options for playback control.
* Bumped up web api timeouts to allow web clients to finish resolving.
* Added filename suggestion when exporting a playlist.
* Cleaned up highlighting of artist names in album view.
* Cleaned up alignment of playlist items.
* Fixed potential crash when searching.
* Added support for disc number.
* Added SoundCloudWall.com charts.
* Added ability to "lock on" to a user when listening along, to skip along.
* Fixed bug where loved tracks would be refreshed much too often.
* Fixed some font size issues.
* Sped up Tomahawk startup by moving chart loading into a separate thread.
* Added support for parsing Grooveshark and Tinysong tracks and playlists.
* Reorganized sidebar to follow more logical item groupings.
* Added artist and album results to global searches.
* Fixed style and contrast issues when using GTK styles.
* Fixed paths to artwork when using MPRIS2 interface.
* Fixed out of sync Show/Hide menu items on OS X when hidden with cmd-h.
* Fixed /Volumes directory not showing up on OS X.
* Fixed startup crash on OS X.
Version 0.3.3:
* Automatically load Super Collection tracks when no official release
information is available.
* Fixed stations not fetching new tracks under certain circumstances.
* Fixed Footnotes not always updating when selecting a new track.
* Added support for ow.ly, fb.me, itun.es and tinyurl.com URL shorteners.
* Fixed playback issues with non-latin filenames on Windows.
* Fixed tomahawk:// protocol not working properly on Windows.
* Fixed dupe menu entry appearing on OS X.
* Fixed invisible sidebar items on Linux.
Version 0.3.2:
* Improved syncing process, it's faster and more reliable now.
* Fixed UPnP issues.
@@ -127,7 +52,7 @@ Version 0.3.0:
* Added YouTube resolver.
* Fixed bug where going offline then online would not re-connect to many
peers.
* Added support for auto-updating live XSPF playlists.
* Added support for auto-updating live XSPF playlists.
* Don't show an age of 41 years for tracks that have no age information.
* Show config UI for resolvers that have them as soon as you add them.
* Add support for Echo Nest Personal Catalogs and User Radio. Synchronize
@@ -143,7 +68,7 @@ Version 0.3.0:
* Added new job status view in the bottom of the source list that displays
current jobs such as resolving, parsing playlists, and loading from
database.
* Parse and convert a Spotify playlist URL when dropped anywhere on the
* Parse and convert a Spotify playlist url when dropped anywhere on the
sidebar.
* Convert resolvers to use asynchronous calls to avoid blocking Tomahawk's
UI, greatly increasing responsiveness of Tomahawk while resolving.

12
README
View File

@@ -13,7 +13,7 @@ Compiling Tomahawk
Detailed building instructions for Ubuntu
-----------------------------------------
See: http://wiki.tomahawk-player.org/mediawiki/index.php/Building_Ubuntu_Binary_on_Precise_(12.04)
See: http://wiki.tomahawk-player.org/mediawiki/index.php/Building_Ubuntu_Binary_on_Maverick_(10.10)
Detailed building instructions for OS X
---------------------------------------
@@ -27,7 +27,7 @@ Doxygen Documentation
Dependencies
------------
CMake 2.8.6 - http://www.cmake.org/
CMake 2.8.0 - http://www.cmake.org/
Qt 4.7.0 - http://qt.nokia.com/
QJson 0.7.1 - http://qjson.sourceforge.net/
SQLite 3.6.22 - http://www.sqlite.org/
@@ -38,14 +38,14 @@ Dependencies
The following dependencies are optional, but recommended:
Attica 0.3.0 - ftp://ftp.kde.org/pub/kde/stable/attica/
QuaZip 0.4.3 - http://quazip.sourceforge.net/
Jreen 1.0.5 - http://qutim.org/jreen / https://github.com/euroelessar/jreen
QTweetLib 0.5.0 - https://github.com/minimoog/QTweetLib
Attica 0.2.0 - ftp://ftp.kde.org/pub/kde/stable/attica/
jreen (Git) - https://github.com/euroelessar/jreen
QTweetLib 0.3.0 - https://github.com/minimoog/QTweetLib
Third party libraries that we ship with our source:
MiniUPnP 1.6 - http://miniupnp.free.fr/
liblastfm 0.4.0 - http://github.com/jonocole/liblastfm/
QuaZip 0.4.3 - http://quazip.sourceforge.net/
Enjoy!

View File

@@ -1,6 +1,6 @@
#!/usr/bin/python
# This file is part of Tomahawk.
# It was inspired in large part by the macdeploy script in Clementine.
# This file is part of Clementine.
#
# Clementine is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -199,10 +199,11 @@ QT_PLUGINS = [
]
TOMAHAWK_PLUGINS = [
'libtomahawk_account_xmpp.so',
'libtomahawk_account_google.so',
'libtomahawk_account_twitter.so',
'libtomahawk_account_zeroconf.so',
'libtomahawk_sipjabber.dylib',
'libtomahawk_sipgoogle.dylib',
'libtomahawk_siptwitter.dylib',
'libtomahawk_sipzeroconf.dylib',
'libtomahawk_qtweetlib.dylib',
]
QT_PLUGINS_SEARCH_PATH=[
@@ -249,7 +250,7 @@ frameworks_dir = os.path.join(bundle_dir, 'Contents', 'Frameworks')
commands.append(['mkdir', '-p', frameworks_dir])
resources_dir = os.path.join(bundle_dir, 'Contents', 'Resources')
commands.append(['mkdir', '-p', resources_dir])
plugins_dir = os.path.join(bundle_dir, 'Contents', 'PlugIns')
plugins_dir = os.path.join(bundle_dir, 'Contents', 'plugins')
binary = os.path.join(bundle_dir, 'Contents', 'MacOS', bundle_name)
fixed_libraries = []
@@ -490,11 +491,16 @@ def FindVLCPlugin(name):
FixBinary(binary)
for plugin in VLC_PLUGINS:
FixVLCPlugin(FindVLCPlugin(plugin), '../Frameworks/vlc/plugins')
FixVLCPlugin(FindVLCPlugin(plugin), '.')
for plugin in TOMAHAWK_PLUGINS:
FixPlugin(plugin, '../MacOS')
try:
FixPlugin('spotify_tomahawkresolver', '../MacOS')
except:
print 'Failed to find spotify resolver'
try:
FixPlugin('tomahawk_crash_reporter', '../MacOS')
except:

View File

@@ -4,9 +4,8 @@ Version=1.0
Name=Tomahawk
GenericName=Music Player
TryExec=tomahawk
Exec=tomahawk %u
Exec=tomahawk
Comment=Tomahawk - Social Music Player
Icon=tomahawk
Terminal=false
Categories=Qt;AudioVideo;Audio;Player;
MimeType=x-scheme-handler/tomahawk;

View File

@@ -3,12 +3,9 @@ SET(MINGW_PREFIX "i686-w64-mingw32")
# this one is important
SET(CMAKE_SYSTEM_NAME Windows)
# specify the cross compiler
SET(CMAKE_C_COMPILER ccache ${MINGW_PREFIX}-gcc)
SET(CMAKE_C_FLAGS "-fno-keep-inline-dllexport")
SET(CMAKE_CXX_COMPILER ccache ${MINGW_PREFIX}-g++)
SET(CMAKE_CXX_FLAGS ${CMAKE_C_FLAGS})
SET(CMAKE_RC_COMPILER /usr/bin/${MINGW_PREFIX}-windres)
# where is the target environment containing libraries
@@ -18,6 +15,13 @@ SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# configure qt variables
SET(QT_LIBRARY_DIR /usr/${MINGW_PREFIX}/bin)
# libs with broken find modules
SET(TAGLIB_FOUND true)
SET(TAGLIB_LIBRARIES ${CMAKE_FIND_ROOT_PATH}/lib/libtag.dll.a)
SET(TAGLIB_INCLUDES ${CMAKE_FIND_ROOT_PATH}/include/taglib)
SET(QT_PLUGINS_DIR ${CMAKE_FIND_ROOT_PATH}/lib/qt4/plugins/)
SET(QT_QTUITOOLS_LIBRARY_RELEASE ${CMAKE_FIND_ROOT_PATH}/lib/libQtUiTools.a)
SET(QT_QTUITOOLS_LIBRARY_DEBUG ${CMAKE_FIND_ROOT_PATH}/lib/libQtUiToolsd.a)
SET(QT_QTUITOOLS_LIBRARY ${QT_QTUITOOLS_LIBRARY_RELEASE})

View File

@@ -1,52 +1,42 @@
#!/bin/bash
echo "Remove old vlc dir..."
if [ "$1" = "-c" ] ; then
echo "Continuing last download.."
rm -rvf vlc/
else
echo "Update archive..."
fi
mkdir -p vlc/
cd vlc/
rm -rvf vlc/
#rm -vf vlc-*.7z
#rm -rf vlc/
echo "Download phonon archive..."
# wget -c "http://downloads.sourceforge.net/project/vlc/1.1.9/win32/vlc-1.1.9-win32.7z?r=http%3A%2F%2Fwww.videolan.org%2Fvlc%2Fdownload-windows.html&ts=1306272584&use_mirror=leaseweb"
# wget -c "http://download.tomahawk-player.org/tomahawk-vlc-0.1.zip"
# wget -c http://people.videolan.org/~jb/phonon/phonon-vlc-last.7z
# wget -c http://people.videolan.org/~jb/phonon/phonon_phonon-vlc_20111128.7z
wget -c http://download.tomahawk-player.org/test/pvlc.tar.bz2
echo "Download specified binary..."
#wget -c "http://downloads.sourceforge.net/project/vlc/1.1.9/win32/vlc-1.1.9-win32.7z?r=http%3A%2F%2Fwww.videolan.org%2Fvlc%2Fdownload-windows.html&ts=1306272584&use_mirror=leaseweb"
#wget -c "http://download.tomahawk-player.org/tomahawk-vlc-0.1.zip"
wget -c http://people.videolan.org/~jb/phonon/phonon-vlc-last.7z
echo "Extract binary..."
# 7z x phonon*.7z
# mv -v vlc-*/ vlc/
# unzip tomahawk-vlc-0.1.zip
tar xvjf pvlc.tar.bz2
7z x phonon-vlc-last.7z
#mv -v vlc-*/ vlc/
#unzip tomahawk-vlc-0.1.zip
# echo "Download phonon_vlc_no_video.dll..."
# wget -c http://people.videolan.org/~jb/phonon/phonon_vlc_no_video.dll
# cp -v phonon_vlc_no_video.dll prefix/bin/phonon_backend/phonon_vlc.dll
# echo "Strip unneeded plugins from vlc/plugins..."
# cd prefix/bin/plugins
# rm -rvf libold* libvcd* libdvd* liblibass* libx264* libschroe* liblibmpeg2* \
# libstream_out_* libmjpeg_plugin* libh264_plugin* libzvbi_plugin* lib*sub* \
# *qt4* *skins2* libaccess_bd_plugin.dll \
# libaudiobargraph_* libball_plugin.dll \
# libdirac_plugin.dll \
# libgnutls_plugin.dll \
# libcaca_plugin.dll \
# libfreetype_plugin.dll \
# libaccess_output_shout_plugin.dll \
# libremoteosd_plugin.dll \
# libsdl_image_plugin.dll \
# libvout_sdl_plugin.dll \
# libpng_plugin.dll \
# libgoom_plugin.dll \
# libatmo_plugin.dll \
# libmux_ts_plugin.dll \
# libkate_plugin.dll \
# libtaglib_plugin.dll
echo "Strip unneeded plugins from vlc/plugins..."
cd prefix/bin/plugins
rm -rvf libold* libvcd* libdvd* liblibass* libx264* libschroe* liblibmpeg2* \
libstream_out_* libmjpeg_plugin* libh264_plugin* libzvbi_plugin* lib*sub* \
*qt4* *skins2* libaccess_bd_plugin.dll \
libaudiobargraph_* libball_plugin.dll \
libdirac_plugin.dll \
libgnutls_plugin.dll \
libcaca_plugin.dll \
libfreetype_plugin.dll \
libaccess_output_shout_plugin.dll \
libremoteosd_plugin.dll \
libsdl_image_plugin.dll \
libvout_sdl_plugin.dll \
libpng_plugin.dll \
libgoom_plugin.dll \
libatmo_plugin.dll \
libmux_ts_plugin.dll \
libkate_plugin.dll \
libtaglib_plugin.dll
# this is for vlc-1.2

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 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: 68 KiB

After

Width:  |  Height:  |  Size: 4.9 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: 68 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 356 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

BIN
data/images/avatar-dude.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

BIN
data/images/collapse.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

BIN
data/images/home.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 1.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: 1.0 MiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -2,7 +2,7 @@
// if run in phantomjs add fake Tomahawk environment
if(window.Tomahawk === undefined)
{
// alert("PHANTOMJS ENVIRONMENT");
alert("PHANTOMJS ENVIRONMENT");
var Tomahawk = {
fakeEnv: function()
{

View File

@@ -1,20 +0,0 @@
-----BEGIN PUBLIC KEY-----
MIIDOzCCAi0GByqGSM44BAEwggIgAoIBAQDRltnNbKWFroVCsG1nTSdlTDmo7fjl
tgOuQ0YB2s0a1bcqgQ5YJRE59pFvF/z2pkHEHdyBA6USd9N7/T9lolwNcJoByJpO
MobUNs04elqZXliriaAdoSb2g6ZpxiedppbbyNP/BlK6o+zpyn0LVYXDI/OwJFzS
xjGXM+rBEWdUJnogZxV31gF9W3yD1Quz6icBulT9V/Soo6me9Mc60ooKSYj4Zgqd
3ln8tG90RFnWfbb0nbrITvR3ll6XXLfn081tjhymcXqHcgvaaqcmpKWL6ZWwX1mH
3t1pImnif/tSSZPG21KGE3FtuQ/+YFo19apQ6U6l8kaSFxqcDLAYzBy9AhUA/QfN
8WEIvzOEZ9uSWT7lYy64mUkCggEABsUmcs3kwjrmszIAAmPIowA0DBrxWZL03JBV
bDKT6tNHZaFFlCufVSjiL1EFZjRARC16OWYaDcElUsZYFMcsNIIa8LyDQaq6+SSm
quhMO5heeJiYPrutDiJzbJr0+HoY77Ll+Q4/cEkl0UAN4Ovp18WKwaq6GpHAvBnv
71LunLGAKsVb5joXBQ8In6zQkibJhgiBJwzLK90/j0OTiDaaOwM3PsAegORBVlVE
TAk4AQmawmF8nBGLzTyKXl83J571ku1Mm2JTl16jMYziKARKXYBmkcP1at0YddVK
WWpAwRKSxOucVJYfV58JqmjZqst8BBeH6esQKr5dklUvvDMaEwOCAQYAAoIBAQCw
5mo+8/R3S9cNYg9o8JNJGdSbMhSkurILHh9WNElsIC3RNtPcpijmAnWtXTVDhe6w
77wLj37tUuFGbsu2qPXtZoup35emf9DDshZ5w5UOclPaZ9HYjlC1H64c6d66Rllk
fY6FRDv9qVfjT84APbvMDrk6csJ5YHxFPDaqeQaFB0nxFiCMVwjEx+ZSvQNK1jJ2
o2gtuOvSPVSphsMeJ72DDNxO+SRRVnOmWaxg9rlmFuGle6Z+UJ2FItfmPEvhSBMY
hzndUbC7Wi4sIpBzbm9O5MiPYMv0VmN+0t1156EiC9uR4f7AKH2S94dnQob/YeY0
jMH+XxU/wzGUCmsOx1lx
-----END PUBLIC KEY-----

View File

@@ -1,4 +1,4 @@
-- Script to migate from db version 26 to 27
-- Script to migate from db version 6 to 27
-- Nothing to do
CREATE TABLE IF NOT EXISTS collection_attributes (

View File

@@ -1,7 +0,0 @@
-- Script to migate from db version 27 to 28.
-- Added albumartist and discnumber to file_join
ALTER TABLE file_join ADD COLUMN composer INTEGER REFERENCES artist(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE file_join ADD COLUMN discnumber INTEGER;
UPDATE settings SET v = '28' WHERE k == 'schema_version';

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/lang">
<file>tomahawk_en.qm</file>
<file>tomahawk_bg.qm</file>
<file>tomahawk_de.qm</file>
<file>tomahawk_fr.qm</file>
<file>tomahawk_pl.qm</file>
<file>tomahawk_pt_BR.qm</file>
<file>tomahawk_ru.qm</file>
<file>tomahawk_es.qm</file>
<file>tomahawk_sv.qm</file>
<file>tomahawk_ja.qm</file>
</qresource>
</RCC>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,7 @@
<RCC>
<qresource prefix="/">
<file>data/images/avatar-dude-plus.png</file>
<file>data/images/avatar-dude.png</file>
<file>data/images/back-pressed.png</file>
<file>data/images/back-rest.png</file>
<file>data/images/filter.png</file>
@@ -7,8 +9,6 @@
<file>data/images/not-loved.png</file>
<file>data/images/no-album-art-placeholder.png</file>
<file>data/images/no-artist-image-placeholder.png</file>
<file>data/images/artist-placeholder-grid.png</file>
<file>data/images/album-placeholder-grid.png</file>
<file>data/images/track-placeholder.png</file>
<file>data/images/now-playing-panel.png</file>
<file>data/images/now-playing-speaker.png</file>
@@ -66,10 +66,12 @@
<file>data/images/echonest_logo.png</file>
<file>data/images/loading-animation.gif</file>
<file>data/images/info.png</file>
<file>data/images/home.png</file>
<file>data/images/back.png</file>
<file>data/images/forward.png</file>
<file>data/images/music-icon.png</file>
<file>data/images/configure.png</file>
<file>data/images/create-playlist.png</file>
<file>data/images/private-listening.png</file>
<file>data/images/add.png</file>
<file>data/images/recently-played.png</file>
@@ -85,7 +87,6 @@
<file>data/images/station.png</file>
<file>data/images/new-additions.png</file>
<file>data/images/charts.png</file>
<file>data/images/new-releases.png</file>
<file>data/images/loved_playlist.png</file>
<file>data/images/dashboard.png</file>
<file>data/images/artist-icon.png</file>
@@ -127,20 +128,8 @@
<file>data/images/headphones.png</file>
<file>data/images/headphones-off.png</file>
<file>data/images/headphones-sidebar.png</file>
<file>data/images/closed-padlock.png</file>
<file>data/images/open-padlock.png</file>
<file>data/images/headphones-bigger.png</file>
<file>data/images/no-album-no-case.png</file>
<file>data/images/rdio.png</file>
<file>data/images/grooveshark.png</file>
<file>data/images/lastfm-icon.png</file>
<file>data/images/spotifycore-logo.png</file>
<file>data/images/playlist-header-tiled.png</file>
<file>data/images/share.png</file>
<file>data/sql/dbmigrate-27_to_28.sql</file>
<file>data/images/process-stop.png</file>
<file>data/icons/tomahawk-icon-128x128-grayscale.png</file>
<file>data/images/collection.png</file>
<file>data/misc/tomahawk_pubkey.pem</file>
</qresource>
</RCC>

View File

@@ -1,784 +0,0 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011-2012 Leo Franchi <lfranchi@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AccountDelegate.h"
#include <QApplication>
#include <QPainter>
#include <QMouseEvent>
#include "accounts/AccountModel.h"
#include "accounts/Account.h"
#include "accounts/AccountManager.h"
#include "utils/TomahawkUtils.h"
#include "utils/Logger.h"
#include "utils/AnimatedSpinner.h"
#include "utils/Closure.h"
#include "Source.h"
#define CHILD_ACCOUNT_HEIGHT 24
#define PADDING 4
#define PADDING_BETWEEN_STARS 2
#define STAR_SIZE 12
#ifdef Q_OS_MAC
#define ROW_HEIGHT_MULTIPLIER 4.9
#else
#define ROW_HEIGHT_MULTIPLIER 5.7
#endif
#define ICONSIZE 40
#define WRENCH_SIZE 24
#define SMALL_WRENCH_SIZE 16
#define STATUS_ICON_SIZE 13
#define CHECK_LEFT_EDGE 8
#define REMOVE_ICON_SIZE 12
using namespace Tomahawk;
using namespace Accounts;
AccountDelegate::AccountDelegate( QObject* parent )
: QStyledItemDelegate ( parent )
, m_accountRowHeight( -1 )
, m_model( 0 )
{
m_defaultCover.load( RESPATH "images/sipplugin-online.png" );
m_ratingStarPositive.load( RESPATH "images/starred.png" );
m_ratingStarNegative.load( RESPATH "images/star-unstarred.png" );
m_onHoverStar.load( RESPATH "images/star-hover.png" );
m_onlineIcon.load( RESPATH "images/sipplugin-online.png" );
m_offlineIcon.load( RESPATH "images/sipplugin-offline.png" );
m_removeIcon.load( RESPATH "images/list-remove.png" );
m_ratingStarPositive = m_ratingStarPositive.scaled( STAR_SIZE, STAR_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
m_ratingStarNegative = m_ratingStarNegative.scaled( STAR_SIZE, STAR_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
m_onlineIcon = m_onlineIcon.scaled( STATUS_ICON_SIZE, STATUS_ICON_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
m_offlineIcon = m_offlineIcon.scaled( STATUS_ICON_SIZE, STATUS_ICON_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
m_onHoverStar = m_onHoverStar.scaled( STAR_SIZE, STAR_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
m_removeIcon = m_removeIcon.scaled( REMOVE_ICON_SIZE, REMOVE_ICON_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
m_defaultCover = m_defaultCover.scaled( ICONSIZE, ICONSIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
}
QSize
AccountDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
AccountModel::RowType rowType = static_cast< AccountModel::RowType >( index.data( AccountModel::RowTypeRole ).toInt() );
if ( m_accountRowHeight < 0 )
{
// Haven't calculated normal item height yet, do it once and save it
QStyleOptionViewItemV4 opt( option );
initStyleOption( &opt, index );
m_accountRowHeight = ROW_HEIGHT_MULTIPLIER * opt.fontMetrics.height();
}
if ( rowType == AccountModel::TopLevelAccount || rowType == AccountModel::UniqueFactory || rowType == AccountModel::CustomAccount )
{
return QSize( 200, m_accountRowHeight );
}
else if ( rowType == AccountModel::TopLevelFactory )
{
// Make more space for each account we have to show.
AccountFactory* fac = qobject_cast< AccountFactory* >( index.data( AccountModel::AccountData ).value< QObject* >() );
if ( fac->isUnique() )
return QSize( 200, m_accountRowHeight );
const QList< Account* > accts = index.data( AccountModel::ChildrenOfFactoryRole ).value< QList< Tomahawk::Accounts::Account* > >();
const QSize s = QSize( 200, m_accountRowHeight + 12 * accts.size()-1 );
if ( s != m_sizeHints[ index ] )
const_cast< AccountDelegate* >( this )->sizeHintChanged( index ); // FU KTHBBQ
m_sizeHints[ index ] = s;
return s;
}
return QSize();
}
void
AccountDelegate::paint ( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
QStyleOptionViewItemV4 opt = option;
initStyleOption( &opt, index );
// draw the background
const QWidget* w = opt.widget;
QStyle* style = w ? w->style() : QApplication::style();
style->drawPrimitive( QStyle::PE_PanelItemViewItem, &opt, painter, w );
painter->setRenderHint( QPainter::Antialiasing );
if ( m_model == 0 || m_model != index.model() )
m_model = const_cast<QAbstractItemModel*>( index.model() );
QFont titleFont = opt.font;
titleFont.setBold( true );
titleFont.setPointSize( titleFont.pointSize() + 2 );
const QFontMetrics titleMetrics( titleFont );
QFont authorFont = opt.font;
authorFont.setItalic( true );
authorFont.setPointSize( authorFont.pointSize() - 1 );
#ifdef Q_OS_MAC
authorFont.setPointSize( authorFont.pointSize() - 1 );
#endif
const QFontMetrics authorMetrics( authorFont );
QFont descFont = authorFont;
descFont.setItalic( false );
const QFontMetrics descMetrics( descFont );
QFont installFont = opt.font;
installFont.setPointSize( installFont.pointSize() - 1 );
const QFontMetrics installMetrics( descFont );
const int height = opt.rect.height();
const int center = height / 2 + opt.rect.top();
// Left account enable/disable checkbox
const AccountModel::RowType rowType = static_cast< AccountModel::RowType >( index.data( AccountModel::RowTypeRole ).toInt() );
int leftEdge = PADDING;
// draw checkbox first
const int checkboxYPos = ( center ) - ( WRENCH_SIZE / 2 );
QRect checkRect = QRect( leftEdge, checkboxYPos, WRENCH_SIZE, WRENCH_SIZE );
QStyleOptionViewItemV4 opt2 = opt;
opt2.rect = checkRect;
if ( !m_loadingSpinners.contains( index ) )
{
drawCheckBox( opt2, painter, opt.widget );
}
else
{
Q_ASSERT( m_loadingSpinners[ index ] );
if ( m_loadingSpinners[ index ] )
{
const QPixmap pm = m_loadingSpinners[index]->pixmap();
painter->drawPixmap( checkRect, pm );
}
}
leftEdge += WRENCH_SIZE + PADDING / 2;
// Pixmap
QPixmap p = index.data( Qt::DecorationRole ).value< QPixmap >();
QRect pixmapRect( leftEdge + PADDING, center - ICONSIZE/2, ICONSIZE, ICONSIZE );
if ( p.isNull() ) // default image... TODO
p = m_defaultCover;
else
p = p.scaled( pixmapRect.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation );
painter->drawPixmap( pixmapRect, p );
// Draw config wrench if there is one
const bool hasConfigWrench = index.data( AccountModel::HasConfig ).toBool();
int rightEdge = opt.rect.right();
m_cachedConfigRects[ index ] = QRect();
if ( hasConfigWrench )
{
const QRect confRect = QRect( rightEdge - 2*PADDING - WRENCH_SIZE, center - WRENCH_SIZE / 2, WRENCH_SIZE, WRENCH_SIZE );
QStyleOptionToolButton topt;
topt.rect = confRect;
topt.pos = confRect.topLeft();
drawConfigWrench( painter, opt, topt );
m_cachedConfigRects[ index ] = confRect;
rightEdge = confRect.left();
}
// Draw individual accounts and add account button for factories
m_cachedButtonRects[ index ] = QRect();
bool canDelete = index.data( AccountModel::CanDeleteRole ) .toBool();
if ( rowType == Tomahawk::Accounts::AccountModel::TopLevelFactory )
{
const QList< Account* > accts = index.data( AccountModel::ChildrenOfFactoryRole ).value< QList< Tomahawk::Accounts::Account* > >();
QRect btnRect;
const QString btnText = tr( "Add Account" );
const int btnWidth = installMetrics.width( btnText ) + 2*PADDING;
if ( accts.isEmpty() )
{
Q_ASSERT( !hasConfigWrench );
// Draw button in center of row
btnRect= QRect( opt.rect.right() - PADDING - btnWidth, center - ( installMetrics.height() + 4 ) / 2, btnWidth, installMetrics.height() + 2*PADDING );
rightEdge = btnRect.left();
}
else
{
painter->save();
painter->setFont( installFont );
rightEdge = drawAccountList( painter, opt, accts, rightEdge );
painter->restore();
btnRect = QRect( opt.rect.right() - PADDING - btnWidth, opt.rect.bottom() - installMetrics.height() - 3*PADDING, btnWidth, installMetrics.height() + 2*PADDING );
#ifdef Q_WS_MAC
btnRect.adjust( -4, 0, 4, 0 );
#endif
}
leftEdge = btnRect.left();
m_cachedButtonRects[ index ] = btnRect;
painter->save();
painter->setPen( opt.palette.color( QPalette::Active, QPalette::AlternateBase ) );
drawRoundedButton( painter, btnRect );
painter->setFont( installFont );
painter->drawText( btnRect, Qt::AlignCenter, btnText );
painter->restore();
}
else if ( rowType == AccountModel::UniqueFactory )
{
// Display as usual, except if it has an account, show the status.
const QList< Account* > accts = index.data( AccountModel::ChildrenOfFactoryRole ).value< QList< Tomahawk::Accounts::Account* > >();
if ( !accts.isEmpty() )
{
Q_ASSERT( accts.size() == 1 );
rightEdge = drawStatus( painter, QPointF( rightEdge, center - painter->fontMetrics().height()/2 ), accts.first(), true );
}
}
else if ( canDelete )
{
const QString btnText = tr( "Remove Account" );
const int btnWidth = installMetrics.width( btnText ) + 2*PADDING;
QRect btnRect;
if ( hasConfigWrench )
btnRect = QRect( opt.rect.right() - PADDING - btnWidth, opt.rect.bottom() - installMetrics.height() - 3*PADDING, btnWidth, installMetrics.height() + 2*PADDING );
else
btnRect = QRect( opt.rect.right() - PADDING - btnWidth, center - ( installMetrics.height() + 4 ) / 2, btnWidth, installMetrics.height() + 2*PADDING );
#ifdef Q_WS_MAC
btnRect.adjust( -4, 2, 4, -2 );
#endif
leftEdge = btnRect.left();
m_cachedButtonRects[ index ] = btnRect;
painter->save();
painter->setPen( opt.palette.color( QPalette::Active, QPalette::AlternateBase ) );
drawRoundedButton( painter, btnRect, true );
painter->setFont( installFont );
painter->drawText( btnRect, Qt::AlignCenter, btnText );
painter->restore();
}
// Draw the title and description
// title
QString title = index.data( Qt::DisplayRole ).toString();
const int rightTitleEdge = rightEdge - PADDING;
const int leftTitleEdge = pixmapRect.right() + PADDING;
painter->setFont( titleFont );
QRect textRect;
const bool canRate = index.data( AccountModel::CanRateRole ).toBool();
if ( canRate )
{
textRect = QRect( leftTitleEdge, opt.rect.top() + PADDING, rightTitleEdge - leftTitleEdge, painter->fontMetrics().height() );
}
else
{
textRect = QRect( leftTitleEdge, opt.rect.top() + PADDING, rightTitleEdge - leftTitleEdge, center - opt.rect.top() - PADDING );
}
painter->drawText( textRect, Qt::AlignVCenter | Qt::AlignLeft, title );
// author
QString author = index.data( AccountModel::AuthorRole ).toString();
int runningBottom = textRect.bottom();
if ( !author.isEmpty() && canRate )
{
painter->save();
painter->setFont( authorFont );
painter->setPen( QColor( Qt::gray ).darker( 150 ) );
const int authorWidth = authorMetrics.width( author );
const QRect authorRect( textRect.left(), textRect.bottom() + PADDING/2, authorWidth + 6, authorMetrics.height() );
painter->drawText( authorRect, Qt::AlignLeft | Qt::AlignVCenter, author );
painter->restore();
runningBottom = authorRect.bottom();
}
// description
QString desc = index.data( AccountModel::DescriptionRole ).toString();
const int descWidth = rightEdge - leftTitleEdge - PADDING;
painter->setFont( descFont );
const QRect descRect( leftTitleEdge, runningBottom + PADDING, descWidth, painter->fontMetrics().height() );
desc = painter->fontMetrics().elidedText( desc, Qt::ElideRight, descWidth );
painter->drawText( descRect, Qt::AlignLeft | Qt::TextWordWrap | Qt::AlignTop, desc );
runningBottom = descRect.bottom();
if ( index.data( AccountModel::CanRateRole ).toBool() )
{
// rating stars
const int rating = index.data( AccountModel::RatingRole ).toInt();
// int runningEdge = opt.rect.right() - 2*PADDING - ratingWidth;
int runningEdge = textRect.left();
// int starsTop = opt.rect.bottom() - 3*PADDING - m_ratingStarNegative.height();
int starsTop = runningBottom + PADDING;
for ( int i = 1; i < 6; i++ )
{
QRect r( runningEdge, starsTop, m_ratingStarPositive.width(), m_ratingStarPositive.height() );
// QRect r( runningEdge, opt.rect.top() + PADDING, m_ratingStarPositive.width(), m_ratingStarPositive.height() );
if ( i == 1 )
m_cachedStarRects[ index ] = r;
const bool userHasRated = index.data( AccountModel::UserHasRatedRole ).toBool();
if ( !userHasRated && // Show on-hover animation if the user hasn't rated it yet, and is hovering over it
m_hoveringOver > -1 &&
m_hoveringItem == index )
{
if ( i <= m_hoveringOver ) // positive star
painter->drawPixmap( r, m_onHoverStar );
else
painter->drawPixmap( r, m_ratingStarNegative );
}
else
{
if ( i <= rating ) // positive or rated star
{
if ( userHasRated )
painter->drawPixmap( r, m_onHoverStar );
else
painter->drawPixmap( r, m_ratingStarPositive );
}
else
painter->drawPixmap( r, m_ratingStarNegative );
}
runningEdge += m_ratingStarPositive.width() + PADDING_BETWEEN_STARS;
}
// downloaded num times
QString count = tr( "%1 downloads" ).arg( index.data( AccountModel::DownloadCounterRole ).toInt() );
painter->setFont( descFont );
const int countW = painter->fontMetrics().width( count );
const QRect countRect( runningEdge + 50, starsTop, countW, painter->fontMetrics().height() );
count = painter->fontMetrics().elidedText( count, Qt::ElideRight, rightEdge - PADDING - countRect.left() );
painter->drawText( countRect, Qt::AlignLeft | Qt::TextWordWrap, count );
// runningEdge = authorRect.x();
}
// Title and description!
return;
}
int
AccountDelegate::drawAccountList( QPainter* painter, QStyleOptionViewItemV4& opt, const QList< Account* > accts, int rightEdge ) const
{
// list each account name, and show the online, offline icon
const int textHeight = painter->fontMetrics().height() + 1;
const int mid = opt.rect.bottom() - opt.rect.height() / 2;
int runningRightEdge = rightEdge;
int current = 0;
int leftOfAccounts = rightEdge;
if ( accts.size() % 2 == 1 )
{
// If there's an odd number, the center one is centered
current = mid - ((textHeight + PADDING/2) * (accts.size()/2) ) - textHeight / 2;
}
else
{
// Even number, center between the middle ones
current = mid - ((textHeight + PADDING/2) * (accts.size()/2) );
}
for ( int i = 0; i < accts.size(); i++ )
{
// draw lightbulb and text
runningRightEdge = drawStatus( painter, QPointF( rightEdge - PADDING, current), accts.at( i ) );
const QString label = accts.at( i )->accountFriendlyName();
const QPoint textTopLeft( runningRightEdge - PADDING - painter->fontMetrics().width( label ), current);
painter->drawText( QRect( textTopLeft, QSize( painter->fontMetrics().width( label ) + 1, textHeight ) ), label );
current += textHeight + PADDING/2;
leftOfAccounts = qMin( leftOfAccounts, textTopLeft.x() );
}
return leftOfAccounts;
}
bool
AccountDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index )
{
if ( event->type() != QEvent::MouseButtonPress &&
event->type() != QEvent::MouseButtonRelease &&
event->type() != QEvent::MouseButtonDblClick &&
event->type() != QEvent::MouseMove )
return false;
if ( event->type() == QEvent::MouseButtonPress )
{
// Show the config wrench as depressed on click
QMouseEvent* me = static_cast< QMouseEvent* >( event );
if ( me->button() == Qt::LeftButton && m_cachedConfigRects.contains( index ) && m_cachedConfigRects[ index ].contains( me->pos() ) )
{
m_configPressed = index;
const AccountModel::RowType rowType = static_cast< AccountModel::RowType >( index.data( AccountModel::RowTypeRole ).toInt() );
if ( rowType == AccountModel::TopLevelAccount ||
rowType == AccountModel::CustomAccount )
{
Account* acct = qobject_cast< Account* >( index.data( AccountModel::AccountData ).value< QObject* >() );
Q_ASSERT( acct ); // Should not be showing a config wrench if there is no account!
emit openConfig( acct );
}
else if ( rowType == AccountModel::TopLevelFactory )
{
AccountFactory* fac = qobject_cast< AccountFactory* >( index.data( AccountModel::AccountData ).value< QObject* >() );
Q_ASSERT( fac ); // Should not be showing a config wrench if there is no account!
emit openConfig( fac );
}
else if ( rowType == AccountModel::UniqueFactory )
{
const QList< Account* > accts = index.data( AccountModel::ChildrenOfFactoryRole ).value< QList< Tomahawk::Accounts::Account* > >();
Q_ASSERT( !accts.isEmpty() ); // If there's no account, why is there a config widget for this factory?
Q_ASSERT( accts.size() == 1 );
emit openConfig( accts.first() );
}
return true;
}
} else if ( event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::MouseButtonDblClick )
{
QMouseEvent* me = static_cast< QMouseEvent* >( event );
if ( m_configPressed.isValid() )
emit update( m_configPressed );
m_configPressed = QModelIndex();
if ( checkRectForIndex( option, index ).contains( me->pos() ) )
{
// Check box for this row
// eat the double click events inside the check rect
if( event->type() == QEvent::MouseButtonDblClick ) {
return true;
}
Qt::CheckState curState = static_cast< Qt::CheckState >( index.data( Qt::CheckStateRole ).toInt() );
Qt::CheckState newState = curState == Qt::Checked ? Qt::Unchecked : Qt::Checked;
return model->setData( index, newState, AccountModel::CheckboxClickedRole );
}
else if ( m_cachedButtonRects.contains( index ) && m_cachedButtonRects[ index ].contains( me->pos() ) )
{
// Install/create/etc button for this row
model->setData( index, true, AccountModel::CustomButtonRole );
}
}
if ( m_cachedStarRects.contains( index ) )
{
QRect fullStars = m_cachedStarRects[ index ];
const int starsWidth = 5 * ( m_ratingStarPositive.width() + PADDING_BETWEEN_STARS );
fullStars.setWidth( starsWidth );
QMouseEvent* me = static_cast< QMouseEvent* >( event );
if ( fullStars.contains( me->pos() ) )
{
const int eachStar = starsWidth / 5;
const int clickOffset = me->pos().x() - fullStars.x();
const int whichStar = (clickOffset / eachStar) + 1;
if ( event->type() == QEvent::MouseButtonRelease )
{
model->setData( index, whichStar, AccountModel::RatingRole );
}
else if ( event->type() == QEvent::MouseMove )
{
// 0-indexed
m_hoveringOver = whichStar;
m_hoveringItem = index;
}
return true;
}
}
if ( m_hoveringOver > -1 )
{
emit update( m_hoveringItem );
m_hoveringOver = -1;
m_hoveringItem = QPersistentModelIndex();
}
return false;
}
void
AccountDelegate::drawRoundedButton( QPainter* painter, const QRect& btnRect, bool red ) const
{
QPainterPath btnPath;
const int radius = 3;
// draw top half gradient
const int btnCenter = btnRect.bottom() - ( btnRect.height() / 2 );
btnPath.moveTo( btnRect.left(), btnCenter );
btnPath.lineTo( btnRect.left(), btnRect.top() + radius );
btnPath.quadTo( QPoint( btnRect.topLeft() ), QPoint( btnRect.left() + radius, btnRect.top() ) );
btnPath.lineTo( btnRect.right() - radius, btnRect.top() );
btnPath.quadTo( QPoint( btnRect.topRight() ), QPoint( btnRect.right(), btnRect.top() + radius ) );
btnPath.lineTo( btnRect.right(),btnCenter );
btnPath.lineTo( btnRect.left(), btnCenter );
QLinearGradient g;
if ( !red )
{
g.setColorAt( 0, QColor(54, 127, 211) );
g.setColorAt( 0.5, QColor(43, 104, 182) );
}
else
{
g.setColorAt( 0, QColor(206, 63, 63) );
g.setColorAt( 0.5, QColor(170, 52, 52) );
}
//painter->setPen( bg.darker() );
painter->fillPath( btnPath, g );
//painter->drawPath( btnPath );
btnPath = QPainterPath();
btnPath.moveTo( btnRect.left(), btnCenter );
btnPath.lineTo( btnRect.left(), btnRect.bottom() - radius );
btnPath.quadTo( QPoint( btnRect.bottomLeft() ), QPoint( btnRect.left() + radius, btnRect.bottom() ) );
btnPath.lineTo( btnRect.right() - radius, btnRect.bottom() );
btnPath.quadTo( QPoint( btnRect.bottomRight() ), QPoint( btnRect.right(), btnRect.bottom() - radius ) );
btnPath.lineTo( btnRect.right(), btnCenter );
btnPath.lineTo( btnRect.left(), btnCenter );
if ( !red )
{
g.setColorAt( 0, QColor(34, 85, 159) );
g.setColorAt( 0.5, QColor(35, 79, 147) );
}
else
{
g.setColorAt( 0, QColor(150, 50, 50) );
g.setColorAt( 0.5, QColor(130, 40, 40) );
}
painter->fillPath( btnPath, g );
}
int
AccountDelegate::drawStatus( QPainter* painter, const QPointF& rightTopEdge, Account* acct, bool drawText ) const
{
QPixmap p;
QString statusText;
const Account::ConnectionState state = acct->connectionState();
if ( state == Account::Connected )
{
p = m_onlineIcon;
statusText = tr( "Online" );
}
else if ( state == Account::Connecting )
{
p = m_offlineIcon;
statusText = tr( "Connecting..." );
}
else
{
p = m_offlineIcon;
statusText = tr( "Offline" );
}
const int yPos = rightTopEdge.y();
const QRect connectIconRect( rightTopEdge.x() - STATUS_ICON_SIZE, yPos, STATUS_ICON_SIZE, STATUS_ICON_SIZE );
if ( state == Account::Connecting )
{
if ( !m_connectingSpinners.contains( acct ) )
{
AnimatedSpinner* anim = new AnimatedSpinner( connectIconRect.size(), true );
_detail::Closure* closure = new _detail::Closure( anim, SIGNAL( requestUpdate() ), const_cast<AccountDelegate*>(this), SLOT( doUpdateIndexWithAccount( Tomahawk::Accounts::Account* ) ), C_ARG( Tomahawk::Accounts::Account*, acct ) );
closure->setAutoDelete( false );
m_connectingSpinners[ acct ] = anim;
}
const QPixmap pm = m_connectingSpinners[acct]->pixmap();
painter->drawPixmap( connectIconRect, pm );
}
else
{
if ( m_connectingSpinners.contains( acct ) )
delete m_connectingSpinners.take( acct );
painter->drawPixmap( connectIconRect, p );
}
int leftEdge = connectIconRect.x();
if ( drawText )
{
int width = painter->fontMetrics().width( statusText );
int statusTextX = connectIconRect.x() - PADDING - width;
painter->drawText( QRect( statusTextX, yPos, width, painter->fontMetrics().height() ), statusText );
leftEdge = statusTextX;
}
return leftEdge;
}
void
AccountDelegate::drawCheckBox( QStyleOptionViewItemV4& opt, QPainter* p, const QWidget* w ) const
{
QStyle* style = w ? w->style() : QApplication::style();
opt.checkState == Qt::Checked ? opt.state |= QStyle::State_On : opt.state |= QStyle::State_Off;
style->drawPrimitive( QStyle::PE_IndicatorViewItemCheck, &opt, p, w );
}
void
AccountDelegate::drawConfigWrench ( QPainter* painter, QStyleOptionViewItemV4& opt, QStyleOptionToolButton& topt ) const
{
const QWidget* w = opt.widget;
QStyle* style = w ? w->style() : QApplication::style();
// draw it the same size as the check belox
topt.font = opt.font;
topt.icon = QIcon( RESPATH "images/configure.png" );
topt.iconSize = QSize( 14, 14 );
topt.subControls = QStyle::SC_ToolButton;
topt.activeSubControls = QStyle::SC_None;
topt.features = QStyleOptionToolButton::None;
bool pressed = ( m_configPressed == opt.index );
topt.state = pressed ? QStyle::State_On : QStyle::State_Raised;
if( opt.state & QStyle::State_MouseOver || pressed )
topt.state |= QStyle::State_HasFocus;
style->drawComplexControl( QStyle::CC_ToolButton, &topt, painter, w );
}
QRect
AccountDelegate::checkRectForIndex( const QStyleOptionViewItem& option, const QModelIndex& idx ) const
{
QStyleOptionViewItemV4 opt = option;
initStyleOption( &opt, idx );
// Top level item, return the corresponding rect
const int ypos = ( opt.rect.top() + opt.rect.height() / 2 ) - ( WRENCH_SIZE / 2 );
const QRect checkRect = QRect( PADDING, ypos, WRENCH_SIZE, WRENCH_SIZE );
return checkRect;
}
void
AccountDelegate::startInstalling( const QPersistentModelIndex& idx )
{
qDebug() << "START INSTALLING:" << idx.data( Qt::DisplayRole ).toString();
QStyleOptionViewItemV4 opt;
initStyleOption( &opt, idx );
AnimatedSpinner* anim = new AnimatedSpinner( checkRectForIndex( opt, idx ).size(), true );
_detail::Closure* closure = NewClosure( anim, SIGNAL( requestUpdate() ), this, SLOT( doUpdateIndex( const QPersistentModelIndex& ) ), idx );
closure->setAutoDelete( false );
m_loadingSpinners[ idx ] = anim;
update( idx );
}
void
AccountDelegate::doneInstalling ( const QPersistentModelIndex& idx )
{
qDebug() << "STOP INSTALLING:" << idx.data( Qt::DisplayRole ).toString();
Q_ASSERT( m_loadingSpinners.contains( idx ) );
if ( !m_loadingSpinners.contains( idx ) )
return;
delete m_loadingSpinners.take( idx );
update( idx );
}
void
AccountDelegate::errorInstalling( const QPersistentModelIndex& idx )
{
// Just hide the loading spinner as we do after a successful install
qDebug() << "ERROR INSTALLING index:" << idx;
doneInstalling( idx );
}
void
AccountDelegate::doUpdateIndex( const QPersistentModelIndex& idx )
{
emit update( idx );
}
void
AccountDelegate::doUpdateIndexWithAccount( Account* account )
{
// Urgh, have to go through the list and check based on the type
for ( int i = 0; i < m_model->rowCount(); i++ )
{
const QModelIndex index = m_model->index( i, 0, QModelIndex() );
const AccountModel::RowType rowType = static_cast< AccountModel::RowType >( index.data( AccountModel::RowTypeRole ).toInt() );
if ( rowType == AccountModel::TopLevelAccount ||
rowType == AccountModel::CustomAccount )
{
Account* acct = qobject_cast< Account* >( index.data( AccountModel::AccountData ).value< QObject* >() );
if ( account == acct )
{
emit update( index );
return;
}
}
else if ( rowType == AccountModel::TopLevelFactory || rowType == AccountModel::UniqueFactory )
{
const QList< Account* > accts = index.data( AccountModel::ChildrenOfFactoryRole ).value< QList< Tomahawk::Accounts::Account* > >();
if ( accts.contains( account ) )
{
emit update( index );
return;
}
}
}
}

View File

@@ -1,90 +0,0 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011-2012 Leo Franchi <lfranchi@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ACCOUNTDELEGATE_H
#define ACCOUNTDELEGATE_H
#include <QStyledItemDelegate>
#include "accounts/AccountModel.h"
class AnimatedSpinner;
namespace Tomahawk
{
namespace Accounts
{
class Account;
class AccountDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
AccountDelegate( QObject* parent = 0);
virtual void paint ( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
virtual QSize sizeHint ( const QStyleOptionViewItem& option, const QModelIndex& index ) const;
public slots:
void startInstalling( const QPersistentModelIndex& idx );
void doneInstalling ( const QPersistentModelIndex& idx );
void errorInstalling ( const QPersistentModelIndex& idx );
void doUpdateIndex( const QPersistentModelIndex& idx );
protected:
virtual bool editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index );
signals:
void update( const QModelIndex& idx );
void openConfig( Tomahawk::Accounts::Account* );
void openConfig( Tomahawk::Accounts::AccountFactory* );
private slots:
void doUpdateIndexWithAccount( Tomahawk::Accounts::Account* account );
private:
void drawRoundedButton( QPainter* painter, const QRect& buttonRect, bool red = false ) const;
// Returns new left edge
int drawStatus( QPainter* painter, const QPointF& rightTopEdge, Account* acct, bool drawText = false ) const;
void drawCheckBox( QStyleOptionViewItemV4& opt, QPainter* p, const QWidget* w ) const;
void drawConfigWrench( QPainter* painter, QStyleOptionViewItemV4& option, QStyleOptionToolButton& topt ) const;
// returns new left edge
int drawAccountList( QPainter* painter, QStyleOptionViewItemV4& option, const QList< Account* > accounts, int rightEdge ) const;
QRect checkRectForIndex( const QStyleOptionViewItem &option, const QModelIndex &idx ) const;
QPixmap m_offlineIcon, m_onlineIcon, m_defaultCover, m_onHoverStar, m_ratingStarPositive, m_ratingStarNegative, m_removeIcon;
int m_hoveringOver;
QPersistentModelIndex m_hoveringItem, m_configPressed;
mutable QHash< QPersistentModelIndex, QRect > m_cachedButtonRects;
mutable QHash< QPersistentModelIndex, QRect > m_cachedStarRects;
mutable QHash< QPersistentModelIndex, QRect > m_cachedConfigRects;
mutable QHash< QPersistentModelIndex, QSize > m_sizeHints;
mutable QHash< QPersistentModelIndex, AnimatedSpinner* > m_loadingSpinners;
mutable QHash< Account*, AnimatedSpinner* > m_connectingSpinners;
mutable int m_accountRowHeight;
mutable QAbstractItemModel* m_model;
};
}
}
#endif // ACCOUNTDELEGATE_H

View File

@@ -1,138 +0,0 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AccountFactoryWrapper.h"
#include "accounts/Account.h"
#include "accounts/AccountManager.h"
#include "GuiHelpers.h"
#include "AccountFactoryWrapperDelegate.h"
#include "DelegateConfigWrapper.h"
#include "ui_AccountFactoryWrapper.h"
#include "Source.h"
using namespace Tomahawk::Accounts;
AccountFactoryWrapper::AccountFactoryWrapper( AccountFactory* factory, QWidget* parent )
: QDialog( parent, Qt::Sheet )
, m_factory( factory )
, m_ui( new Ui_AccountFactoryWrapper )
{
m_ui->setupUi( this );
setWindowTitle( factory->prettyName() );
m_ui->factoryIcon->setPixmap( factory->icon() );
m_ui->factoryDescription->setText( factory->description() );
m_addButton = m_ui->buttonBox->addButton( tr( "Add Account" ), QDialogButtonBox::ActionRole );
AccountFactoryWrapperDelegate* del = new AccountFactoryWrapperDelegate( m_ui->accountsList );
m_ui->accountsList->setItemDelegate( del );
connect( del, SIGNAL( openConfig( Tomahawk::Accounts::Account* ) ), this, SLOT( openAccountConfig( Tomahawk::Accounts::Account* ) ) );
connect( del, SIGNAL( removeAccount( Tomahawk::Accounts::Account* ) ), this, SLOT( removeAccount( Tomahawk::Accounts::Account* ) ) );
connect( del, SIGNAL( checkOrUncheck( QModelIndex, Tomahawk::Accounts::Account* , Qt::CheckState ) ), this, SLOT( accountCheckedOrUnchecked( QModelIndex ,Tomahawk::Accounts::Account* ,Qt::CheckState ) ) );
load();
connect( m_ui->buttonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
connect( m_ui->buttonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
connect( m_ui->buttonBox, SIGNAL( clicked( QAbstractButton*) ), this, SLOT( buttonClicked( QAbstractButton* ) ) );
connect ( AccountManager::instance(), SIGNAL( added( Tomahawk::Accounts::Account* ) ), this, SLOT( load() ) );
connect ( AccountManager::instance(), SIGNAL( removed( Tomahawk::Accounts::Account* ) ), this, SLOT( load() ) );
#ifdef Q_OS_MAC
setContentsMargins( 0, 0, 0, 0 );
m_ui->verticalLayout->setSpacing( 6 );
#endif
}
void
AccountFactoryWrapper::load()
{
m_ui->accountsList->clear();
foreach ( Account* acc, AccountManager::instance()->accounts() )
{
if ( AccountManager::instance()->factoryForAccount( acc ) == m_factory )
{
QTreeWidgetItem* item = new QTreeWidgetItem( m_ui->accountsList );
item->setData( 0, AccountRole, QVariant::fromValue< QObject *>( acc ) );
item->setCheckState( 0, acc->enabled() ? Qt::Checked : Qt::Unchecked );
}
}
if ( m_ui->accountsList->model()->rowCount() == 0 )
accept();
#ifndef Q_OS_MAC
const int padding = 7;
#else
const int padding = 8;
#endif
const int height = m_ui->accountsList->model()->rowCount( QModelIndex() ) * ACCOUNT_ROW_HEIGHT + padding;
m_ui->accountsList->setFixedHeight( height );
}
void
AccountFactoryWrapper::openAccountConfig( Account* account )
{
TomahawkUtils::openAccountConfig( account, this, false );
}
void
AccountFactoryWrapper::removeAccount( Tomahawk::Accounts::Account* acct )
{
AccountManager::instance()->removeAccount( acct );
load();
}
void
AccountFactoryWrapper::accountCheckedOrUnchecked( const QModelIndex& index, Account* acct, Qt::CheckState newstate )
{
QTreeWidgetItem* item = m_ui->accountsList->topLevelItem( index.row() );
Q_ASSERT( item );
if ( newstate == Qt::Checked )
{
item->setCheckState( 0, Qt::Checked );
AccountManager::instance()->enableAccount( acct );
}
else if ( newstate == Qt::Unchecked )
{
item->setCheckState( 0, Qt::Unchecked );
AccountManager::instance()->disableAccount( acct );
}
}
void
AccountFactoryWrapper::buttonClicked( QAbstractButton* button )
{
if ( button == m_addButton )
{
TomahawkUtils::createAccountFromFactory( m_factory, this );
}
else
reject();
}

View File

@@ -1,62 +0,0 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ACCOUNTFACTORYWRAPPER_H
#define ACCOUNTFACTORYWRAPPER_H
#include <QDialog>
#include <QModelIndex>
class QAbstractButton;
namespace Tomahawk {
namespace Accounts {
class AccountFactory;
class Account;
}
}
class Ui_AccountFactoryWrapper;
// class AccountFactoryWrapper_
class AccountFactoryWrapper : public QDialog
{
Q_OBJECT
public:
enum ExtraRoles {
AccountRole = Qt::UserRole + 140
};
explicit AccountFactoryWrapper( Tomahawk::Accounts::AccountFactory* factory, QWidget* parent = 0 );
virtual ~AccountFactoryWrapper() {}
public slots:
void openAccountConfig( Tomahawk::Accounts::Account* );
void removeAccount( Tomahawk::Accounts::Account* );
void accountCheckedOrUnchecked( const QModelIndex& , Tomahawk::Accounts::Account* , Qt::CheckState );
private slots:
void buttonClicked( QAbstractButton* );
void load();
private:
Tomahawk::Accounts::AccountFactory* m_factory;
Ui_AccountFactoryWrapper* m_ui;
QPushButton* m_addButton;
};
#endif // ACCOUNTFACTORYWRAPPER_H

View File

@@ -1,110 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AccountFactoryWrapper</class>
<widget class="QDialog" name="AccountFactoryWrapper">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>507</width>
<height>150</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="factoryIcon">
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="factoryDescription">
<property name="text">
<string>Description goes here</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QTreeWidget" name="accountsList">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="autoScroll">
<bool>false</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::NoSelection</enum>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerItem</enum>
</property>
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<property name="headerHidden">
<bool>true</bool>
</property>
<property name="expandsOnDoubleClick">
<bool>false</bool>
</property>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -1,187 +0,0 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AccountFactoryWrapperDelegate.h"
#include "accounts/Account.h"
#include "AccountFactoryWrapper.h"
#include "utils/TomahawkUtils.h"
#include "Source.h"
#include <QApplication>
#include <QPainter>
#include <QMouseEvent>
using namespace Tomahawk::Accounts;
#define ICON_SIZE 15
#define CONFIG_WRENCH_SIZE 20
#define PADDING 4
AccountFactoryWrapperDelegate::AccountFactoryWrapperDelegate( QObject* parent )
: QStyledItemDelegate( parent )
{
m_removePixmap.load( RESPATH "images/list-remove.png" );
m_onlineIcon.load( RESPATH "images/sipplugin-online.png" );
m_offlineIcon.load( RESPATH "images/sipplugin-offline.png" );
m_removePixmap = m_removePixmap.scaled( ICON_SIZE, ICON_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
m_onlineIcon = m_onlineIcon.scaled( ICON_SIZE, ICON_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
m_offlineIcon = m_offlineIcon.scaled( ICON_SIZE, ICON_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
m_configIcon.addFile( RESPATH "images/configure.png", QSize( CONFIG_WRENCH_SIZE - 8, CONFIG_WRENCH_SIZE - 8 ) );
}
void
AccountFactoryWrapperDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
QStyleOptionViewItemV4 opt = option;
initStyleOption( &opt, index );
const int center = opt.rect.height() / 2 + opt.rect.top();
const int topIcon = center - ICON_SIZE/2;
// draw the background
const QWidget* w = opt.widget;
QStyle* style = w ? w->style() : QApplication::style();
style->drawPrimitive( QStyle::PE_PanelItemViewItem, &opt, painter, w );
Account* acc = qobject_cast< Account* >( index.data( AccountFactoryWrapper::AccountRole ).value< QObject* >() );
Q_ASSERT( acc );
// Checkbox on left edge, then text
const QRect checkRect( PADDING/4, PADDING/4 + opt.rect.top(), opt.rect.height() - PADDING/4, opt.rect.height() - PADDING/4 );
m_cachedCheckRects[ index ] = checkRect;
QStyleOptionViewItemV4 opt2 = opt;
opt2.rect = checkRect;
opt.checkState == Qt::Checked ? opt2.state |= QStyle::State_On : opt2.state |= QStyle::State_Off;
style->drawPrimitive( QStyle::PE_IndicatorViewItemCheck, &opt2, painter, w );
// name on left
painter->drawText( opt.rect.adjusted( checkRect.right() + PADDING, PADDING, -PADDING, -PADDING ), Qt::AlignLeft | Qt::AlignVCenter, acc->accountFriendlyName() );
// remove, config, status on right
const QRect pmRect( opt.rect.right() - PADDING - m_removePixmap.width(), topIcon, ICON_SIZE, ICON_SIZE );
painter->drawPixmap( pmRect, m_removePixmap );
m_cachedButtonRects[ index ] = pmRect;
const QRect confRect( pmRect.left() - PADDING - CONFIG_WRENCH_SIZE, center - CONFIG_WRENCH_SIZE/2, CONFIG_WRENCH_SIZE, CONFIG_WRENCH_SIZE );
QStyleOptionToolButton topt;
topt.rect = confRect;
topt.pos = confRect.topLeft();
topt.font = opt.font;
topt.icon = m_configIcon;
topt.iconSize = QSize( CONFIG_WRENCH_SIZE - 8, CONFIG_WRENCH_SIZE - 8 );
topt.subControls = QStyle::SC_ToolButton;
topt.activeSubControls = QStyle::SC_None;
topt.features = QStyleOptionToolButton::None;
bool pressed = ( m_configPressed == opt.index );
topt.state = pressed ? QStyle::State_On : QStyle::State_Raised;
if( opt.state & QStyle::State_MouseOver || pressed )
topt.state |= QStyle::State_HasFocus;
style->drawComplexControl( QStyle::CC_ToolButton, &topt, painter, w );
m_cachedConfigRects[ index ] = confRect;
QPixmap p;
QString statusText;
Account::ConnectionState state = acc->connectionState();
if ( state == Account::Connected )
{
p = m_onlineIcon;
statusText = tr( "Online" );
}
else if ( state == Account::Connecting )
{
p = m_offlineIcon;
statusText = tr( "Connecting..." );
}
else
{
p = m_offlineIcon;
statusText = tr( "Offline" );
}
const QRect connectIconRect( confRect.left() - PADDING - ICON_SIZE, topIcon, ICON_SIZE, ICON_SIZE );
painter->drawPixmap( connectIconRect, p );
int width = painter->fontMetrics().width( statusText );
painter->drawText( QRect( connectIconRect.left() - PADDING - width, center - painter->fontMetrics().height()/2, width, painter->fontMetrics().height() ), statusText );
}
QSize
AccountFactoryWrapperDelegate::sizeHint(const QStyleOptionViewItem&, const QModelIndex&) const
{
return QSize( 200, ACCOUNT_ROW_HEIGHT );
}
bool
AccountFactoryWrapperDelegate::editorEvent( QEvent* event, QAbstractItemModel*, const QStyleOptionViewItem&, const QModelIndex& index )
{
if ( event->type() != QEvent::MouseButtonPress &&
event->type() != QEvent::MouseButtonRelease &&
event->type() != QEvent::MouseButtonDblClick &&
event->type() != QEvent::MouseMove )
return false;
if ( event->type() == QEvent::MouseButtonPress )
{
// Show the config wrench as depressed on click
QMouseEvent* me = static_cast< QMouseEvent* >( event );
if ( me->button() == Qt::LeftButton && m_cachedConfigRects.contains( index ) && m_cachedConfigRects[ index ].contains( me->pos() ) )
{
m_configPressed = index;
Account* acct = qobject_cast< Account* >( index.data( AccountFactoryWrapper::AccountRole ).value< QObject* >() );
Q_ASSERT( acct ); // Should not be showing a config wrench if there is no account!
emit openConfig( acct );
return true;
}
} else if ( event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::MouseButtonDblClick )
{
QMouseEvent* me = static_cast< QMouseEvent* >( event );
if ( m_configPressed.isValid() )
emit update( m_configPressed );
m_configPressed = QModelIndex();
Account* acct = qobject_cast< Account* >( index.data( AccountFactoryWrapper::AccountRole ).value< QObject* >() );
if ( m_cachedCheckRects.contains( index ) && m_cachedCheckRects[ index ].contains( me->pos() ) )
{
// Check box for this row
// eat the double click events inside the check rect
if( event->type() == QEvent::MouseButtonDblClick ) {
return true;
}
Qt::CheckState curState = static_cast< Qt::CheckState >( index.data( Qt::CheckStateRole ).toInt() );
Qt::CheckState newState = curState == Qt::Checked ? Qt::Unchecked : Qt::Checked;
emit checkOrUncheck( index, acct, newState );
}
if ( m_cachedButtonRects.contains( index ) && m_cachedButtonRects[ index ].contains( me->pos() ) )
{
emit removeAccount( acct );
return true;
}
}
return false;
}

View File

@@ -1,61 +0,0 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2012, Leo Franchi <lfranchi@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ACCOUNTFACTORYWRAPPERDELEGATE_H
#define ACCOUNTFACTORYWRAPPERDELEGATE_H
#include <QStyledItemDelegate>
#define ACCOUNT_ROW_HEIGHT 20
namespace Tomahawk {
namespace Accounts {
class Account;
}
}
class AccountFactoryWrapperDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit AccountFactoryWrapperDelegate( QObject* parent = 0 );
virtual void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
virtual QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const;
virtual bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index);
signals:
void update( const QModelIndex& );
void openConfig( Tomahawk::Accounts::Account* );
void removeAccount( Tomahawk::Accounts::Account* );
void checkOrUncheck( const QModelIndex& row, Tomahawk::Accounts::Account* account, Qt::CheckState newState );
private:
QPixmap m_removePixmap, m_offlineIcon, m_onlineIcon;
QIcon m_configIcon;
QModelIndex m_configPressed;
mutable QHash< QPersistentModelIndex, QRect > m_cachedCheckRects;
mutable QHash< QPersistentModelIndex, QRect > m_cachedButtonRects;
mutable QHash< QPersistentModelIndex, QRect > m_cachedConfigRects;
};
#endif // ACCOUNTFACTORYWRAPPERDELEGATE_H

View File

@@ -2,9 +2,9 @@ FILE( GLOB _icons "${CMAKE_SOURCE_DIR}/data/icons/tomahawk-icon-*.png" )
FOREACH( _file ${_icons} )
STRING( REPLACE "${CMAKE_SOURCE_DIR}/data/icons/tomahawk-icon-" "" _res ${_file} )
STRING( REPLACE ".png" "" _res ${_res} )
INSTALL( FILES ${_file} RENAME tomahawk.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/${_res}/apps )
INSTALL( FILES ${_file} RENAME tomahawk.png DESTINATION share/icons/hicolor/${_res}/apps )
ENDFOREACH( _file )
INSTALL( FILES ${CMAKE_SOURCE_DIR}/data/icons/tomahawk-icon.svg RENAME tomahawk.svg DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps )
INSTALL( FILES ${CMAKE_SOURCE_DIR}/data/icons/tomahawk-icon.svg RENAME tomahawk.svg DESTINATION share/icons/hicolor/scalable/apps )
INSTALL( FILES ${CMAKE_SOURCE_DIR}/admin/unix/tomahawk.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications )
INSTALL( FILES ${CMAKE_SOURCE_DIR}/admin/unix/tomahawk.desktop DESTINATION share/applications )

View File

@@ -58,7 +58,4 @@ if (APPLE)
FILE(COPY ${CMAKE_SOURCE_DIR}/admin/mac/sparkle_pub.pem
DESTINATION "${CMAKE_BINARY_DIR}/tomahawk.app/Contents/Resources")
FILE(COPY /usr/bin/SetFile DESTINATION "${CMAKE_BINARY_DIR}/tomahawk.app/Contents/MacOS")
FILE(COPY /usr/bin/GetFileInfo DESTINATION "${CMAKE_BINARY_DIR}/tomahawk.app/Contents/MacOS")
endif (APPLE)

View File

@@ -13,8 +13,6 @@ SET( QT_USE_QTNETWORK TRUE )
SET( QT_USE_QTXML TRUE )
SET( QT_USE_QTWEBKIT TRUE )
add_definitions( -DQT_SHAREDPOINTER_TRACK_POINTERS )
INCLUDE( ${QT_USE_FILE} )
INCLUDE( AddAppIconMacro )
@@ -37,78 +35,111 @@ ENDIF()
#ENDFOREACH( moddir )
SET( tomahawkSources ${tomahawkSources}
web/Api_v1.cpp
web/api_v1.cpp
MusicScanner.cpp
ShortcutHandler.cpp
ScanManager.cpp
UbuntuUnityHack.cpp
TomahawkApp.cpp
musicscanner.cpp
shortcuthandler.cpp
scanmanager.cpp
ubuntuunityhack.cpp
tomahawkapp.cpp
main.cpp
)
IF(LIBLASTFM_FOUND)
SET(tomahawkSources ${tomahawkSources}
Scrobbler.cpp
scrobbler.cpp
)
ENDIF(LIBLASTFM_FOUND)
SET( tomahawkSourcesGui ${tomahawkSourcesGui}
sourcetree/SourcesModel.cpp
sourcetree/SourcesProxyModel.cpp
sourcetree/SourceTreeView.cpp
sourcetree/SourceDelegate.cpp
sourcetree/AnimationHelper.cpp
sourcetree/items/SourceTreeItem.cpp
sourcetree/items/SourceItem.cpp
sourcetree/items/PlaylistItems.cpp
sourcetree/items/CategoryItems.cpp
sourcetree/items/GenericPageItems.cpp
sourcetree/items/TemporaryPageItem.cpp
sourcetree/items/GroupItem.cpp
sourcetree/items/HistoryItem.cpp
sourcetree/sourcesmodel.cpp
sourcetree/sourcesproxymodel.cpp
sourcetree/sourcetreeview.cpp
sourcetree/sourcedelegate.cpp
sourcetree/animationhelper.cpp
sourcetree/items/sourcetreeitem.cpp
sourcetree/items/collectionitem.cpp
sourcetree/items/playlistitems.cpp
sourcetree/items/categoryitems.cpp
sourcetree/items/genericpageitems.cpp
sourcetree/items/temporarypageitem.cpp
utils/GuiHelpers.cpp
breakpad/BreakPad.cpp
accounts/lastfm/LastFmAccount.cpp
accounts/lastfm/LastFmConfig.cpp
accounts/lastfm/LastFmInfoPlugin.cpp
accounts/spotify/SpotifyAccount.cpp
accounts/spotify/SpotifyAccountConfig.cpp
accounts/spotify/SpotifyPlaylistUpdater.cpp
TomahawkTrayIcon.cpp
AudioControls.cpp
SettingsDialog.cpp
DiagnosticsDialog.cpp
AccountDelegate.cpp
SettingsListDelegate.cpp
DelegateConfigWrapper.cpp
TomahawkWindow.cpp
tomahawktrayicon.cpp
audiocontrols.cpp
settingsdialog.cpp
diagnosticsdialog.cpp
configdelegatebase.cpp
sipconfigdelegate.cpp
resolverconfigdelegate.cpp
settingslistdelegate.cpp
resolversmodel.cpp
tomahawkwindow.cpp
LoadXSPFDialog.cpp
AccountFactoryWrapper.cpp
AccountFactoryWrapperDelegate.cpp
SocialWidget.cpp
)
IF( WITH_BREAKPAD )
LIST(APPEND tomahawkSourcesGui breakpad/BreakPad.cpp)
ENDIF()
SET( tomahawkHeaders ${tomahawkHeaders}
tomahawkapp.h
web/api_v1.h
musicscanner.h
scanmanager.h
ubuntuunityhack.h
shortcuthandler.h
)
IF(LIBLASTFM_FOUND)
SET(tomahawkHeaders ${tomahawkHeaders}
scrobbler.h
)
ENDIF(LIBLASTFM_FOUND)
IF(LIBATTICA_FOUND)
SET( tomahawkSources ${tomahawkSources} GetNewStuffDialog.cpp GetNewStuffDelegate.cpp GetNewStuffModel.cpp )
SET( tomahawkHeaders ${tomahawkHeaders} GetNewStuffDialog.h GetNewStuffDelegate.h GetNewStuffModel.h )
INCLUDE_DIRECTORIES( ${LIBATTICA_INCLUDE_DIR} )
ENDIF(LIBATTICA_FOUND)
SET( tomahawkHeadersGui ${tomahawkHeadersGui}
sourcetree/sourcesmodel.h
sourcetree/sourcesproxymodel.h
sourcetree/sourcetreeview.h
sourcetree/sourcedelegate.h
sourcetree/animationhelper.h
sourcetree/items/sourcetreeitem.h
sourcetree/items/collectionitem.h
sourcetree/items/playlistitems.h
sourcetree/items/categoryitems.h
sourcetree/items/genericpageitems.h
sourcetree/items/temporarypageitem.h
tomahawktrayicon.h
audiocontrols.h
settingsdialog.h
diagnosticsdialog.h
configdelegatebase.h
resolverconfigdelegate.h
sipconfigdelegate.h
settingslistdelegate.h
resolversmodel.h
delegateconfigwrapper.h
tomahawkwindow.h
LoadXSPFDialog.h
)
SET( tomahawkUI ${tomahawkUI}
TomahawkWindow.ui
DiagnosticsDialog.ui
StackedSettingsDialog.ui
ProxyDialog.ui
tomahawkwindow.ui
diagnosticsdialog.ui
stackedsettingsdialog.ui
proxydialog.ui
accounts/lastfm/LastFmConfig.ui
accounts/spotify/SpotifyAccountConfig.ui
audiocontrols.ui
AudioControls.ui
GetNewStuffDialog.ui
LoadXSPFDialog.ui
AccountFactoryWrapper.ui
SocialWidget.ui
)
INCLUDE_DIRECTORIES(
@@ -134,7 +165,6 @@ INCLUDE_DIRECTORIES(
${TAGLIB_INCLUDES}
${PHONON_INCLUDES}
${QJSON_INCLUDE_DIR}
${LIBATTICA_INCLUDE_DIR}
${LIBECHONEST_INCLUDE_DIR}
${LIBECHONEST_INCLUDE_DIR}/..
)
@@ -142,65 +172,64 @@ INCLUDE_DIRECTORIES(
SET( OS_SPECIFIC_LINK_LIBRARIES "" )
IF( WIN32 )
INCLUDE( "CMakeLists.win32.cmake" )
INCLUDE( "CMakeLists.win32.txt" )
ENDIF( WIN32 )
IF( UNIX )
INCLUDE( "CMakeLists.unix.cmake" )
INCLUDE( "CMakeLists.unix.txt" )
ENDIF( UNIX )
IF( APPLE )
INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/thirdparty/SPMediaKeyTap )
SET( tomahawkSources ${tomahawkSources} mac/TomahawkApp_Mac.mm mac/MacShortcutHandler.cpp )
SET( tomahawkHeaders ${tomahawkHeaders} mac/tomahawkapp_mac.h mac/macshortcuthandler.h )
SET( tomahawkSources ${tomahawkSources} mac/tomahawkapp_mac.mm mac/macshortcuthandler.cpp )
IF(HAVE_SPARKLE)
SET( tomahawkHeaders ${tomahawkHeaders} ${SPARKLE}/Headers )
ENDIF(HAVE_SPARKLE)
ENDIF( APPLE )
IF(GLOOX_FOUND)
INCLUDE_DIRECTORIES( ${GLOOX_INCLUDE_DIR} )
SET( tomahawkSources ${tomahawkSources} xmppbot/XmppBot.cpp )
SET( tomahawkHeaders ${tomahawkHeaders} xmppbot/xmppbot.h )
SET( tomahawkSources ${tomahawkSources} xmppbot/xmppbot.cpp )
ENDIF(GLOOX_FOUND)
ADD_SUBDIRECTORY( accounts )
ADD_SUBDIRECTORY( infoplugins )
ADD_SUBDIRECTORY( sip )
IF(QCA2_FOUND)
INCLUDE_DIRECTORIES( ${QCA2_INCLUDE_DIR} )
ENDIF(QCA2_FOUND)
INCLUDE(GNUInstallDirs)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.h.in
kde4_add_app_icon( tomahawkSources "${CMAKE_SOURCE_DIR}/data/icons/tomahawk-icon-*.png" )
qt4_add_resources( RC_SRCS "../resources.qrc" )
qt4_wrap_cpp( tomahawkMoc ${tomahawkHeaders} )
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/config.h)
include( ${CMAKE_SOURCE_DIR}/lang/translations.cmake )
SET( final_src ${final_src} ${tomahawkMoc} ${tomahawkSources} ${trans_outfile})
SET( final_src ${final_src} ${tomahawkMoc} ${tomahawkSources} ${tomahawkHeaders} ${trans_outfile})
IF( BUILD_GUI )
LIST(APPEND tomahawkSources ${tomahawkSourcesGui})
IF( "${gui}" STREQUAL "no" )
ELSE()
qt4_wrap_ui( tomahawkUI_H ${tomahawkUI} )
IF( WITH_CRASHREPORTER )
ADD_SUBDIRECTORY( breakpad/CrashReporter )
ENDIF()
qt4_wrap_cpp( tomahawkMocGui ${tomahawkHeadersGui} )
SET( final_src ${final_src} ${tomahawkUI_H} ${tomahawkMocGui} ${tomahawkSourcesGui} ${RC_SRCS} )
ENDIF()
kde4_add_app_icon( tomahawkSources "${CMAKE_SOURCE_DIR}/data/icons/tomahawk-icon-*.png" )
qt4_add_resources( RC_SRCS "../resources.qrc" )
SET( final_src ${final_src} ${tomahawkUI_H} ${tomahawkMoc} ${tomahawkSources} ${RC_SRCS} )
IF( UNIX AND NOT APPLE )
ADD_EXECUTABLE( tomahawk ${final_src} )
ENDIF( UNIX AND NOT APPLE )
IF( APPLE )
ADD_EXECUTABLE( tomahawk MACOSX_BUNDLE ${final_src} )
SET_TARGET_PROPERTIES(tomahawk PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_BINARY_DIR}/Info.plist")
SET_TARGET_PROPERTIES(tomahawk PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_BINARY_DIR}/Info.plist"
)
ENDIF( APPLE )
IF( WIN32 )
ADD_EXECUTABLE( tomahawk WIN32 ${final_src} )
ENDIF( WIN32 )
SET_TARGET_PROPERTIES(tomahawk PROPERTIES AUTOMOC TRUE)
MESSAGE( STATUS "OS_SPECIFIC_LINK_LIBRARIES: ${OS_SPECIFIC_LINK_LIBRARIES}" )
SET(LINK_LIBRARIES "")
@@ -213,11 +242,9 @@ ENDIF(GLOOX_FOUND)
IF(QCA2_FOUND)
SET(LINK_LIBRARIES ${LINK_LIBRARIES} ${QCA2_LIBRARIES} )
ENDIF(QCA2_FOUND)
IF(WITH_BREAKPAD)
SET(LINK_LIBRARIES ${LINK_LIBRARIES} tomahawk_breakpad)
ENDIF()
TARGET_LINK_LIBRARIES( tomahawk
tomahawk_breakpad
${LINK_LIBRARIES}
${TOMAHAWK_LIBRARIES}
${PHONON_LIBS}
@@ -238,12 +265,12 @@ IF( APPLE )
ENDIF(HAVE_SPARKLE)
ENDIF( APPLE )
INSTALL( TARGETS tomahawk BUNDLE DESTINATION . RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} )
INSTALL( TARGETS tomahawk BUNDLE DESTINATION . RUNTIME DESTINATION bin )
IF( UNIX AND NOT APPLE AND KDE4_INSTALLED AND LEGACY_KDE_INTEGRATION ) #install protocol file
IF( UNIX AND NOT APPLE AND KDE4_INSTALLED ) #install protocol file
FILE( READ ${CMAKE_SOURCE_DIR}/admin/unix/tomahawk.protocol protocol )
STRING( REPLACE "/path/to/binary" # match this
"${CMAKE_INSTALL_FULL_BINDIR}/tomahawk" # this is linux (kde) so pretty safe I think
"${CMAKE_INSTALL_PREFIX}/bin/tomahawk" # this is linux (kde) so pretty safe I think
edited_protocol # save in this variable
"${protocol}" # from the contents of this var
)
@@ -251,7 +278,7 @@ IF( UNIX AND NOT APPLE AND KDE4_INSTALLED AND LEGACY_KDE_INTEGRATION ) #install
IF( ${SERVICES_INSTALL_DIR} )
SET( PROTOCOL_INSTALL_DIR ${SERVICES_INSTALL_DIR} )
ELSE()
SET( PROTOCOL_INSTALL_DIR "${CMAKE_INSTALL_FULL_DATADIR}/kde4/services" )
SET( PROTOCOL_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/share/kde4/services" )
ENDIF()
INSTALL( FILES ${CMAKE_BINARY_DIR}/tomahawk.protocol DESTINATION ${PROTOCOL_INSTALL_DIR} )
ENDIF()

View File

@@ -7,9 +7,9 @@ ADD_DEFINITIONS( -fPIC )
SET( QXTWEB_LIBRARIES qxtweb-standalone )
IF( APPLE )
INCLUDE( "CMakeLists.osx.cmake" )
INCLUDE( "CMakeLists.osx.txt" )
ENDIF( APPLE )
IF( UNIX AND NOT APPLE )
INCLUDE( "CMakeLists.linux.cmake" )
INCLUDE( "CMakeLists.linux.txt" )
ENDIF( UNIX AND NOT APPLE )

View File

@@ -1,158 +0,0 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "DelegateConfigWrapper.h"
#include <QMessageBox>
DelegateConfigWrapper::DelegateConfigWrapper( QWidget* conf, QWidget* aboutWidget, const QString& title, QWidget* parent, Qt::WindowFlags flags )
: QDialog( parent, flags )
, m_widget( conf )
, m_aboutW( aboutWidget )
, m_deleted( false )
{
m_widget->setWindowFlags( Qt::Sheet );
#ifdef Q_WS_MAC
m_widget->setVisible( true );
#endif
setWindowTitle( title );
QVBoxLayout* v = new QVBoxLayout( this );
v->setContentsMargins( 0, 0, 0, 0 );
v->addWidget( m_widget );
QDialogButtonBox::StandardButtons buttons = QDialogButtonBox::Ok | QDialogButtonBox::Cancel;
if ( m_aboutW )
{
m_aboutW->hide();
buttons |= QDialogButtonBox::Help;
}
m_buttons = new QDialogButtonBox( buttons, Qt::Horizontal, this );
m_okButton = m_buttons->button( QDialogButtonBox::Ok );
connect( m_buttons, SIGNAL( clicked( QAbstractButton*) ), this, SLOT( closed( QAbstractButton* ) ) );
connect( this, SIGNAL( rejected() ), this, SLOT( rejected() ) );
if ( m_aboutW )
{
connect( m_buttons->button( QDialogButtonBox::Help ), SIGNAL( clicked( bool ) ), this, SLOT( aboutClicked( bool ) ) );
m_buttons->button( QDialogButtonBox::Help )->setText( tr( "About" ) );
}
v->addWidget( m_buttons );
setLayout( v );
#ifdef Q_WS_MAC
setSizeGripEnabled( false );
setMinimumSize( sizeHint() );
setMaximumSize( sizeHint() ); // to remove the resize grip on osx this is the only way
if( conf->metaObject()->indexOfSignal( "sizeHintChanged()" ) > -1 )
connect( conf, SIGNAL( sizeHintChanged() ), this, SLOT( updateSizeHint() ) );
#else
m_widget->setVisible( true );
#endif
}
void
DelegateConfigWrapper::setShowDelete( bool del )
{
if ( del )
m_deleteButton = m_buttons->addButton( tr( "Delete Account" ), QDialogButtonBox::DestructiveRole );
}
void
DelegateConfigWrapper::toggleOkButton( bool dataError )
{
// if dataError is True we want to set the button enabled to false
m_okButton->setEnabled( !dataError );
}
void
DelegateConfigWrapper::closed( QAbstractButton* b )
{
QDialogButtonBox* buttons = qobject_cast< QDialogButtonBox* >( sender() );
if ( buttons->standardButton( b ) == QDialogButtonBox::Help )
return;
// let the config widget live to see another day
layout()->removeWidget( m_widget );
m_widget->setParent( 0 );
m_widget->setVisible( false );
if ( buttons->standardButton( b ) == QDialogButtonBox::Ok )
done( QDialog::Accepted );
else if ( b == m_deleteButton )
{
m_deleted = true;
emit closedWithDelete();
reject();
}
else
done( QDialog::Rejected );
}
void
DelegateConfigWrapper::rejected()
{
layout()->removeWidget( m_widget );
m_widget->setParent( 0 );
m_widget->setVisible( false );
}
void
DelegateConfigWrapper::updateSizeHint()
{
hide();
setSizeGripEnabled( false );
setMinimumSize( sizeHint() );
setMaximumSize( sizeHint() );
show();
}
void
DelegateConfigWrapper::aboutClicked( bool )
{
Q_ASSERT( m_aboutW );
m_aboutW->show();
QDialog d( this );
d.setWindowTitle( tr( "About this Account" ) );
QVBoxLayout* v = new QVBoxLayout( &d );
v->addWidget( m_aboutW );
QDialogButtonBox* bbox = new QDialogButtonBox( QDialogButtonBox::Ok, Qt::Horizontal, &d );
v->addWidget( bbox );
d.setLayout( v );
connect( bbox, SIGNAL( clicked( QAbstractButton* ) ), &d, SLOT( accept() ) );
d.exec();
v->removeWidget( m_aboutW );
m_aboutW->setParent( 0 );
m_aboutW->hide();
}

View File

@@ -1,61 +0,0 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef RESOLVER_CONFIG_WRAPPER
#define RESOLVER_CONFIG_WRAPPER
#include <QDialog>
#include <QDialogButtonBox>
#include <QVBoxLayout>
#include <QPushButton>
#include <QDebug>
class DelegateConfigWrapper : public QDialog
{
Q_OBJECT
public:
DelegateConfigWrapper( QWidget* conf, QWidget* aboutWidget, const QString& title, QWidget* parent, Qt::WindowFlags flags = 0 );
~DelegateConfigWrapper() {}
void setShowDelete( bool del );
bool deleted() const { return m_deleted; }
public slots:
void toggleOkButton( bool dataError );
void closed( QAbstractButton* b );
// we get a rejected() signal emitted if the user presses escape (and no clicked() signal )
void rejected();
void updateSizeHint();
signals:
void closedWithDelete();
private slots:
void aboutClicked( bool );
private:
QDialogButtonBox* m_buttons;
QWidget* m_widget, *m_aboutW;
QPushButton *m_okButton, *m_deleteButton;
bool m_deleted;
};
#endif

323
src/GetNewStuffDelegate.cpp Normal file
View File

@@ -0,0 +1,323 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "GetNewStuffDelegate.h"
#include "GetNewStuffModel.h"
#include "utils/tomahawkutils.h"
#include "utils/logger.h"
#include <QtGui/QPainter>
#include <QApplication>
#include <QMouseEvent>
#include "AtticaManager.h"
#define PADDING 4
#define PADDING_BETWEEN_STARS 2
#define STAR_SIZE 12
#ifdef Q_WS_MAC
#define SIZEHINT_HEIGHT 70
#else
#define SIZEHINT_HEIGHT 60
#endif
GetNewStuffDelegate::GetNewStuffDelegate( QObject* parent )
: QStyledItemDelegate ( parent )
, m_widestTextWidth( 0 )
, m_hoveringOver( -1 )
{
m_defaultCover.load( RESPATH "images/sipplugin-online.png" );
m_ratingStarPositive.load( RESPATH "images/starred.png" );
m_ratingStarNegative.load( RESPATH "images/star-unstarred.png" );
m_onHoverStar.load( RESPATH "images/star-hover.png" );
m_ratingStarPositive = m_ratingStarPositive.scaled( STAR_SIZE, STAR_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
m_ratingStarNegative = m_ratingStarNegative.scaled( STAR_SIZE, STAR_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
m_onHoverStar = m_onHoverStar.scaled( STAR_SIZE, STAR_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
const int w = SIZEHINT_HEIGHT - 2*PADDING;
m_defaultCover = m_defaultCover.scaled( w, w, Qt::KeepAspectRatio, Qt::SmoothTransformation );
// save the widest wifth
QFont f( QApplication::font() );
f.setPointSize( f.pointSize() - 1 );
QFontMetrics fm( f );
QStringList l = QStringList() << tr( "Installed" ) << tr( "Installing" ) << tr( "Failed" ) << tr( "Uninstalling" );
foreach ( const QString& str, l )
{
if ( fm.width( str ) > m_widestTextWidth )
m_widestTextWidth = fm.width( str );
}
}
void
GetNewStuffDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
QStyleOptionViewItemV4 opt = option;
initStyleOption( &opt, index );
QApplication::style()->drawPrimitive( QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget );
painter->setRenderHint( QPainter::Antialiasing );
QFont titleFont = opt.font;
titleFont.setBold( true );
titleFont.setPointSize( titleFont.pointSize() + 2 );
QFontMetrics titleMetrics( titleFont );
QFont authorFont = opt.font;
authorFont.setItalic( true );
authorFont.setPointSize( authorFont.pointSize() - 1 );
QFontMetrics authorMetrics( authorFont );
QFont descFont = authorFont;
descFont.setItalic( false );
QFontMetrics descMetrics( descFont );
QFont installFont = opt.font;
installFont.setPointSize( installFont.pointSize() - 1 );
QFontMetrics installMetrics( descFont );
const int height = opt.rect.height();
const int center = height / 2 + opt.rect.top();
// Pixmap
QPixmap p = index.data( Qt::DecorationRole ).value< QPixmap >();
const int pixmapWidth = height - 2*PADDING;
QRect pixmapRect( PADDING, PADDING + opt.rect.top(), pixmapWidth, pixmapWidth );
if ( p.isNull() ) // default image... TODO
p = m_defaultCover;
else
p = p.scaled( pixmapRect.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation );
painter->drawPixmap( pixmapRect, p );
// Go from right edge now, stars, install button, and downloaded info
// install / status button
AtticaManager::ResolverState state = static_cast< AtticaManager::ResolverState >( index.data( GetNewStuffModel::StateRole ).toInt() );
QString actionText;
switch( state )
{
case AtticaManager::Uninstalled:
actionText = tr( "Install" );
break;
case AtticaManager::Installing:
actionText = tr( "Installing" );
break;
case AtticaManager::Upgrading:
actionText = tr( "Upgrading" );
break;
case AtticaManager::Failed:
actionText = tr( "Failed" );
break;
case AtticaManager::Installed:
actionText = tr( "Uninstall" );
break;
case AtticaManager::NeedsUpgrade:
actionText = tr( "Upgrade" );
break;
}
const int btnWidth = m_widestTextWidth + 7;
const int leftEdge = opt.rect.width() - PADDING - btnWidth - 3;
const QRect btnRect( leftEdge, center - ( installMetrics.height() + 4 ) / 2, btnWidth, installMetrics.height() + 4 );
m_cachedButtonRects[ QPair<int, int>(index.row(), index.column()) ] = btnRect;
QPen saved = painter->pen();
painter->setPen( opt.palette.color( QPalette::Active, QPalette::AlternateBase ) );
QPainterPath btnPath;
const int radius = 3;
//btnPath.addRoundedRect( btnRect, 3, 3 );
// draw top half gradient
const int btnCenter = btnRect.bottom() - ( btnRect.height() / 2 );
btnPath.moveTo( btnRect.left(), btnCenter );
btnPath.lineTo( btnRect.left(), btnRect.top() + radius );
btnPath.quadTo( QPoint( btnRect.topLeft() ), QPoint( btnRect.left() + radius, btnRect.top() ) );
btnPath.lineTo( btnRect.right() - radius, btnRect.top() );
btnPath.quadTo( QPoint( btnRect.topRight() ), QPoint( btnRect.right(), btnRect.top() + radius ) );
btnPath.lineTo( btnRect.right(),btnCenter );
btnPath.lineTo( btnRect.left(), btnCenter );
QLinearGradient g;
g.setColorAt( 0, QColor(54, 127, 211) );
g.setColorAt( 0.5, QColor(43, 104, 182) );
//painter->setPen( bg.darker() );
painter->fillPath( btnPath, g );
//painter->drawPath( btnPath );
btnPath = QPainterPath();
btnPath.moveTo( btnRect.left(), btnCenter );
btnPath.lineTo( btnRect.left(), btnRect.bottom() - radius );
btnPath.quadTo( QPoint( btnRect.bottomLeft() ), QPoint( btnRect.left() + radius, btnRect.bottom() ) );
btnPath.lineTo( btnRect.right() - radius, btnRect.bottom() );
btnPath.quadTo( QPoint( btnRect.bottomRight() ), QPoint( btnRect.right(), btnRect.bottom() - radius ) );
btnPath.lineTo( btnRect.right(), btnCenter );
btnPath.lineTo( btnRect.left(), btnCenter );
g.setColorAt( 0, QColor(34, 85, 159) );
g.setColorAt( 0.5, QColor(35, 79, 147) );
painter->fillPath( btnPath, g );
painter->setFont( installFont );
painter->drawText( btnRect, Qt::AlignCenter, actionText );
painter->setPen( saved );
// rating stars
int rating = index.data( GetNewStuffModel::RatingRole ).toInt();
const int ratingWidth = 5 * ( m_ratingStarPositive.width() + PADDING_BETWEEN_STARS );
int runningEdge = ( btnRect.right() - btnRect.width() / 2 ) - ratingWidth / 2;
for ( int i = 1; i < 6; i++ )
{
QRect r( runningEdge, btnRect.top() - m_ratingStarPositive.height() - PADDING, m_ratingStarPositive.width(), m_ratingStarPositive.height() );
if ( i == 1 )
m_cachedStarRects[ QPair<int, int>(index.row(), index.column()) ] = r;
const bool userHasRated = index.data( GetNewStuffModel::UserHasRatedRole ).toBool();
if ( !userHasRated && // Show on-hover animation if the user hasn't rated it yet, and is hovering over it
m_hoveringOver > -1 &&
m_hoveringItem == index )
{
if ( i <= m_hoveringOver ) // positive star
painter->drawPixmap( r, m_onHoverStar );
else
painter->drawPixmap( r, m_ratingStarNegative );
}
else
{
if ( i <= rating ) // positive or rated star
{
if ( userHasRated )
painter->drawPixmap( r, m_onHoverStar );
else
painter->drawPixmap( r, m_ratingStarPositive );
}
else
painter->drawPixmap( r, m_ratingStarNegative );
}
runningEdge += m_ratingStarPositive.width() + PADDING_BETWEEN_STARS;
}
// downloaded num times, underneath button
QString count = tr( "%1 downloads" ).arg( index.data( GetNewStuffModel::DownloadCounterRole ).toInt() );
const QRect countRect( btnRect.left(), btnRect.bottom() + PADDING, btnRect.width(), opt.rect.bottom() - PADDING - btnRect.bottom() );
QFont countFont = descFont;
countFont.setPointSize( countFont.pointSize() - 2 );
countFont.setBold( true );
painter->setFont( countFont );
painter->drawText( countRect, Qt::AlignCenter | Qt::TextWordWrap, count );
// author and version
QString author = index.data( GetNewStuffModel::AuthorRole ).toString();
const int authorWidth = authorMetrics.width( author );
const int topTextLine = opt.rect.top() + PADDING;
const QRect authorRect( btnRect.x() - 3*PADDING - authorWidth, topTextLine, authorWidth + 6, authorMetrics.height() );
painter->setFont( authorFont );
painter->drawText( authorRect, Qt::AlignCenter, author );
const QRect versionRect = authorRect.translated( 0, authorRect.height() );
QString version = index.data( GetNewStuffModel::VersionRole ).toString();
painter->drawText( versionRect, Qt::AlignCenter, version );
// title
QString title = index.data( Qt::DisplayRole ).toString();
const int rightTitleEdge = authorRect.left() - PADDING;
const int leftTitleEdge = pixmapRect.right() + PADDING;
const QRect textRect( leftTitleEdge, topTextLine, rightTitleEdge - leftTitleEdge, versionRect.bottom() - opt.rect.top() - PADDING );
painter->setFont( titleFont );
painter->drawText( textRect, Qt::AlignVCenter | Qt::AlignLeft, title );
// description
QString desc = index.data( GetNewStuffModel::DescriptionRole ).toString();
const int descWidth = btnRect.left() - leftTitleEdge - PADDING;
const QRect descRect( leftTitleEdge, versionRect.bottom(), descWidth, opt.rect.bottom() - versionRect.bottom() + PADDING );
painter->setFont( descFont );
painter->drawText( descRect, Qt::AlignLeft | Qt::TextWordWrap, desc );
}
QSize
GetNewStuffDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
Q_UNUSED( option );
Q_UNUSED( index );
return QSize( 200, SIZEHINT_HEIGHT );
}
bool
GetNewStuffDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index )
{
Q_UNUSED( option );
if ( event->type() != QEvent::MouseButtonRelease &&
event->type() != QEvent::MouseMove )
return false;
if ( event->type() == QEvent::MouseButtonRelease && m_cachedButtonRects.contains( QPair<int, int>( index.row(), index.column() ) ) )
{
QRect rect = m_cachedButtonRects[ QPair<int, int>( index.row(), index.column() ) ];
QMouseEvent* me = static_cast< QMouseEvent* >( event );
if ( rect.contains( me->pos() ) )
{
model->setData( index, true );
return true;
}
}
if ( m_cachedStarRects.contains( QPair<int, int>( index.row(), index.column() ) ) )
{
QRect fullStars = m_cachedStarRects[ QPair<int, int>( index.row(), index.column() ) ];
const int starsWidth = 5 * ( m_ratingStarPositive.width() + PADDING_BETWEEN_STARS );
fullStars.setWidth( starsWidth );
QMouseEvent* me = static_cast< QMouseEvent* >( event );
if ( fullStars.contains( me->pos() ) )
{
const int eachStar = starsWidth / 5;
const int clickOffset = me->pos().x() - fullStars.x();
const int whichStar = (clickOffset / eachStar) + 1;
if ( event->type() == QEvent::MouseButtonRelease )
{
model->setData( index, whichStar, GetNewStuffModel::RatingRole );
}
else if ( event->type() == QEvent::MouseMove )
{
// 0-indexed
m_hoveringOver = whichStar;
m_hoveringItem = index;
}
return true;
}
}
if ( m_hoveringOver > -1 )
{
emit update( m_hoveringItem );
m_hoveringOver = -1;
m_hoveringItem = QPersistentModelIndex();
}
return false;
}

50
src/GetNewStuffDelegate.h Normal file
View File

@@ -0,0 +1,50 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GETNEWSTUFFDELEGATE_H
#define GETNEWSTUFFDELEGATE_H
#include <QStyledItemDelegate>
class
GetNewStuffDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit GetNewStuffDelegate( QObject* parent = 0 );
virtual void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
virtual QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const;
signals:
void update( const QModelIndex& idx );
protected:
virtual bool editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index );
private:
QPixmap m_defaultCover, m_onHoverStar, m_ratingStarPositive, m_ratingStarNegative;
int m_widestTextWidth;
int m_hoveringOver;
QPersistentModelIndex m_hoveringItem;
mutable QHash< QPair<int, int>, QRect > m_cachedButtonRects;
mutable QHash< QPair<int, int>, QRect > m_cachedStarRects;
};
#endif // GETNEWSTUFFDELEGATE_H

54
src/GetNewStuffDialog.cpp Normal file
View File

@@ -0,0 +1,54 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "GetNewStuffDialog.h"
#include "ui_GetNewStuffDialog.h"
#include "GetNewStuffDelegate.h"
#include "GetNewStuffModel.h"
GetNewStuffDialog::GetNewStuffDialog( QWidget* parent, Qt::WindowFlags f )
: QDialog( parent, f )
, ui( new Ui::GetNewStuffDialog )
, m_model( new GetNewStuffModel( this ) )
{
ui->setupUi( this );
ui->listView->setModel( m_model );
GetNewStuffDelegate* del = new GetNewStuffDelegate( ui->listView );
connect( del, SIGNAL( update( QModelIndex ) ), ui->listView, SLOT( update( QModelIndex ) ) );
ui->listView->setItemDelegate( del );
ui->listView->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel );
ui->listView->setMouseTracking( true );
setMinimumSize( 560, 350 );
#ifdef Q_WS_MAC
setMaximumSize( 560, 350 );
setSizeGripEnabled( false );
ui->listView->setAttribute( Qt::WA_MacShowFocusRect, false );
#endif
}
GetNewStuffDialog::~GetNewStuffDialog()
{
delete ui;
}

View File

@@ -1,6 +1,6 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Teo Mrnjavac <teo@kde.org>
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -16,25 +16,26 @@
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ID3V1TAG_H
#define ID3V1TAG_H
#ifndef GETNEWSTUFFDIALOG_H
#define GETNEWSTUFFDIALOG_H
#include "tag.h"
#include <taglib/id3v1tag.h>
namespace Tomahawk
{
class DLLEXPORT ID3v1Tag : public Tag
{
public:
ID3v1Tag( TagLib::Tag * );
virtual QString albumArtist() const { return QString(); }
virtual QString composer() const { return QString(); }
virtual unsigned int discNumber() const { return 0; }
};
#include <QDialog>
class GetNewStuffModel;
namespace Ui {
class GetNewStuffDialog;
}
#endif // ID3V1TAG_H
class GetNewStuffDialog : public QDialog
{
Q_OBJECT
public:
explicit GetNewStuffDialog( QWidget *parent = 0, Qt::WindowFlags f = 0 );
~GetNewStuffDialog();
private:
Ui::GetNewStuffDialog *ui;
GetNewStuffModel* m_model;
};
#endif // GETNEWSTUFFDIALOG_H

67
src/GetNewStuffDialog.ui Normal file
View File

@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GetNewStuffDialog</class>
<widget class="QDialog" name="GetNewStuffDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>449</width>
<height>282</height>
</rect>
</property>
<property name="windowTitle">
<string>Download New Resolvers</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QListView" name="listView"/>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>GetNewStuffDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>GetNewStuffDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

156
src/GetNewStuffModel.cpp Normal file
View File

@@ -0,0 +1,156 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "GetNewStuffModel.h"
#include "utils/tomahawkutils.h"
#include "utils/logger.h"
#include <QPixmap>
#include <QUrl>
#include "AtticaManager.h"
GetNewStuffModel::GetNewStuffModel( QObject* parent )
: QAbstractListModel ( parent )
{
if ( AtticaManager::instance()->resolversLoaded() )
m_contentList = AtticaManager::instance()->resolvers();
connect( AtticaManager::instance(), SIGNAL( resolversReloaded( Attica::Content::List ) ), this, SLOT( resolversReloaded( Attica::Content::List ) ) );
connect( AtticaManager::instance(), SIGNAL( resolverStateChanged( QString ) ), this, SLOT( resolverStateChanged( QString ) ) );
}
GetNewStuffModel::~GetNewStuffModel()
{
}
void
GetNewStuffModel::resolversReloaded( const Attica::Content::List& resolvers )
{
beginResetModel();
m_contentList = resolvers;
endResetModel();
}
void
GetNewStuffModel::resolverStateChanged( const QString& resolverId )
{
for ( int i = 0; i < m_contentList.count(); i++ )
{
const Attica::Content resolver = m_contentList[ i ];
if ( resolver.id() == resolverId )
{
QModelIndex idx = index( i, 0, QModelIndex() );
emit dataChanged( idx, idx );
}
}
}
QVariant
GetNewStuffModel::data( const QModelIndex& index, int role ) const
{
if ( !index.isValid() || !hasIndex( index.row(), index.column(), index.parent() ) )
return QVariant();
Attica::Content resolver = m_contentList[ index.row() ];
switch ( role )
{
case Qt::DisplayRole:
return resolver.name();
case Qt::DecorationRole:
return QVariant::fromValue< QPixmap >( AtticaManager::instance()->iconForResolver( resolver ) );
case DownloadUrlRole:
// TODO
return QUrl();
case RatingRole:
return resolver.rating() / 20; // rating is out of 100
case DownloadCounterRole:
return resolver.downloads();
case VersionRole:
return resolver.version();
case DescriptionRole:
return resolver.description();
case TypeRole:
return ResolverType;
case AuthorRole:
return resolver.author();
case StateRole:
return (int)AtticaManager::instance()->resolverState( resolver );
case UserHasRatedRole:
return AtticaManager::instance()->userHasRated( resolver );
}
return QVariant();
}
int
GetNewStuffModel::rowCount( const QModelIndex& parent ) const
{
Q_UNUSED( parent );
return m_contentList.count();
}
bool
GetNewStuffModel::setData( const QModelIndex &index, const QVariant &value, int role )
{
Q_UNUSED( value );
if ( !hasIndex( index.row(), index.column(), index.parent() ) )
return false;
Attica::Content resolver = m_contentList[ index.row() ];
AtticaManager::ResolverState state = AtticaManager::instance()->resolverState( resolver );
if ( role == Qt::EditRole )
{
switch( state )
{
case AtticaManager::Uninstalled:
// install
AtticaManager::instance()->installResolver( resolver );
break;
case AtticaManager::Installing:
case AtticaManager::Upgrading:
// Do nothing, busy
break;
case AtticaManager::Installed:
// Uninstall
AtticaManager::instance()->uninstallResolver( resolver );
break;
case AtticaManager::NeedsUpgrade:
AtticaManager::instance()->upgradeResolver( resolver );
break;
default:
//FIXME -- this handles e.g. Failed
break;
};
} else if ( role == RatingRole )
{
// For now only allow rating if a resolver is installed!
if ( state != AtticaManager::Installed && state != AtticaManager::NeedsUpgrade )
return false;
if ( AtticaManager::instance()->userHasRated( resolver ) )
return false;
m_contentList[ index.row() ].setRating( value.toInt() * 20 );
AtticaManager::instance()->uploadRating( m_contentList[ index.row() ] );
}
emit dataChanged( index, index );
return true;
}

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