Compare commits
308 Commits
0.2.3
...
touchmahaw
Author | SHA1 | Date | |
---|---|---|---|
|
45cc0652d9 | ||
|
6df1b9462f | ||
|
cbb44907f4 | ||
|
7185b4e778 | ||
|
a0c3806da7 | ||
|
0d0f9be3f2 | ||
|
048c82ac24 | ||
|
d49ce2f242 | ||
|
354f1f8f2e | ||
|
2472171e8e | ||
|
f5b0c35274 | ||
|
5ea4b28ad4 | ||
|
58f239b3a9 | ||
|
769be854fa | ||
|
a6013ef411 | ||
|
c16528763f | ||
|
b8d684fed8 | ||
|
1a2b7907d0 | ||
|
bcc5e01f8b | ||
|
3e8bcabfbc | ||
|
c2cd281445 | ||
|
9fdb0c9393 | ||
|
fca061d9bc | ||
|
700e53eb2c | ||
|
5968d6c903 | ||
|
c7317dbe54 | ||
|
031f52f6b7 | ||
|
fa6579f8f0 | ||
|
c9c99d58ab | ||
|
b9d6548243 | ||
|
914c02b7ab | ||
|
b83a7bed00 | ||
|
f3c19779cd | ||
|
9ef5894685 | ||
|
71117d3c42 | ||
|
079f758b66 | ||
|
dd83f121c8 | ||
|
8f326ee41b | ||
|
f32320fd67 | ||
|
0a7e49f6d5 | ||
|
33d8c0314c | ||
|
b73d5b4424 | ||
|
c4a450e5de | ||
|
b32ac0cf04 | ||
|
52c0e9993b | ||
|
1c3b3e9173 | ||
|
9690276079 | ||
|
58362883b3 | ||
|
5b8f35294b | ||
|
12c5b18b05 | ||
|
05315b14bd | ||
|
dd842a1393 | ||
|
a467b8f2e8 | ||
|
5dfb3ccc5c | ||
|
776a2deb91 | ||
|
c79985ad86 | ||
|
aeaf569eb1 | ||
|
e05b8b1843 | ||
|
a6452dbeee | ||
|
d15daf4a85 | ||
|
16a2f94816 | ||
|
7a7de39bf7 | ||
|
37530eeeed | ||
|
c2fe912277 | ||
|
0c3a9c61b5 | ||
|
e75e204007 | ||
|
098999ca8c | ||
|
14e6a7fce4 | ||
|
2bedc3bdd0 | ||
|
58bff6af4c | ||
|
bf03b7b756 | ||
|
7f324bc45c | ||
|
626f9acfac | ||
|
302dbd0224 | ||
|
57dea3061b | ||
|
3e12072dd9 | ||
|
be10085958 | ||
|
6e6ff2ae53 | ||
|
320e5a3252 | ||
|
f031d25741 | ||
|
a554ee0fa8 | ||
|
f774302623 | ||
|
0cea650181 | ||
|
47c515caa4 | ||
|
0319e5f2f5 | ||
|
39bbd128c2 | ||
|
a25d174f64 | ||
|
65709e92ff | ||
|
89104fc27d | ||
|
28e7413bdd | ||
|
d5a2e4b325 | ||
|
bde3d93f6a | ||
|
8ed476ccf6 | ||
|
5c5042769b | ||
|
6cca932bf4 | ||
|
3b832576af | ||
|
fa8746fc70 | ||
|
e44a78ba8d | ||
|
cf25f3c072 | ||
|
4fc7c6415b | ||
|
271e6c480d | ||
|
57e72e53f9 | ||
|
a9a9d11f97 | ||
|
4b4cecc027 | ||
|
e5f6f40289 | ||
|
d2af8a8a39 | ||
|
7166ba161f | ||
|
ea0fb3c099 | ||
|
ea6d892058 | ||
|
dffb3deebe | ||
|
c5876c0f9e | ||
|
89aff8bcbb | ||
|
71339862b6 | ||
|
9e4d320cff | ||
|
cca1ac1532 | ||
|
d8c09ff502 | ||
|
678eeb1232 | ||
|
644135c88a | ||
|
dc9f250322 | ||
|
33a63a45e8 | ||
|
50bce627a8 | ||
|
49373bdfd0 | ||
|
f39a982e00 | ||
|
6a12e9fe04 | ||
|
16e77cb144 | ||
|
eaca242277 | ||
|
851f9124ba | ||
|
01c2927339 | ||
|
9f6dd0a104 | ||
|
52037d8847 | ||
|
39af693de1 | ||
|
9cc919eb08 | ||
|
2e3e0afa7c | ||
|
f0a05acf01 | ||
|
a7d1275e52 | ||
|
232097b06b | ||
|
b1ed8d2419 | ||
|
2c5040c638 | ||
|
f1dfd84213 | ||
|
74fa941159 | ||
|
559433162f | ||
|
fbefe4185f | ||
|
71a5888cba | ||
|
e7cd5bddc4 | ||
|
b70810da9c | ||
|
4fe15984ce | ||
|
1d6c407003 | ||
|
a227ae4bcb | ||
|
13db62b71c | ||
|
bb72c3efb2 | ||
|
34c8c79ef5 | ||
|
6aa7531623 | ||
|
eea5fa2826 | ||
|
a14db5e7f2 | ||
|
42508b7917 | ||
|
6b865eb4f2 | ||
|
87c86b6349 | ||
|
4b5caaceef | ||
|
dccc4e6225 | ||
|
971cc742bb | ||
|
2bff9e9a27 | ||
|
6cba5c990e | ||
|
a2f2fc7867 | ||
|
ec2dec4faf | ||
|
e2fb440af4 | ||
|
ccc8d3b26a | ||
|
e43e45cd76 | ||
|
fc2de7721a | ||
|
65a50c5a85 | ||
|
cd78b77784 | ||
|
1c250b334b | ||
|
d06c43bfe6 | ||
|
1994ab33fe | ||
|
9208257c96 | ||
|
f479fd4e7c | ||
|
36486d10d1 | ||
|
c7e2a5c1c1 | ||
|
a32ff26401 | ||
|
b86f6301ff | ||
|
146eaa226f | ||
|
3fa9fa337e | ||
|
597fec4982 | ||
|
01b199c4a8 | ||
|
6dde11c89a | ||
|
3c30ebd4d6 | ||
|
ff10760838 | ||
|
c4fbb6e0a7 | ||
|
67acb25da0 | ||
|
3e0092d299 | ||
|
9801370a47 | ||
|
2010cb41c7 | ||
|
5f9f9481e7 | ||
|
6f639ecf10 | ||
|
50d00fc1bf | ||
|
def10a2e2b | ||
|
b7db4e0e6b | ||
|
92b612f44f | ||
|
d47cafbebf | ||
|
895d65a24e | ||
|
c9bf3035f2 | ||
|
41f3193355 | ||
|
924c1b3a72 | ||
|
ac317eb0a6 | ||
|
36768db7e4 | ||
|
97ee6f7d5e | ||
|
e0c5108fb4 | ||
|
fe77940545 | ||
|
51ae8fea77 | ||
|
c76c557ed1 | ||
|
4200975576 | ||
|
415d2e8ec7 | ||
|
612fd47293 | ||
|
ebb71321f6 | ||
|
fc235ccf1b | ||
|
a21992a99a | ||
|
573e36fdfd | ||
|
48aeddc0a9 | ||
|
c6a104af93 | ||
|
68d3783b26 | ||
|
228699863f | ||
|
a4a3c4fb17 | ||
|
13a93cfa45 | ||
|
3feee712bd | ||
|
99e3e06716 | ||
|
1653e16e7d | ||
|
977757cc7e | ||
|
71f6a3e81a | ||
|
43bf42df6f | ||
|
552a07eee7 | ||
|
97c694baba | ||
|
5d512c180f | ||
|
7f089714a6 | ||
|
9737f765e5 | ||
|
6521198127 | ||
|
498d7052de | ||
|
f0a6d4e8bb | ||
|
e7bd29d228 | ||
|
5fd7505f7f | ||
|
bc2ea013ac | ||
|
c1ecab349a | ||
|
2f4805c119 | ||
|
622150fca2 | ||
|
237de4f9a6 | ||
|
97d62b06c1 | ||
|
25f37d692e | ||
|
33e2c4f935 | ||
|
d24f2b2bb0 | ||
|
76bd0670d8 | ||
|
4abb53ccdf | ||
|
31d19196e2 | ||
|
77d60fa02d | ||
|
178095acc0 | ||
|
2c846c4ae2 | ||
|
ab462cd7b8 | ||
|
a88afe34c2 | ||
|
79356b9da8 | ||
|
b74cefd72f | ||
|
1d222064fb | ||
|
6b1d919518 | ||
|
016bd7eb47 | ||
|
ae9d6f8df4 | ||
|
8beb3173c6 | ||
|
0bddfe3f0d | ||
|
24febc1066 | ||
|
97b615da41 | ||
|
3ee5016230 | ||
|
dae9718e35 | ||
|
ec2164b77e | ||
|
35a7acd606 | ||
|
ac3d410559 | ||
|
b1d57df4fc | ||
|
b78e2dd8b6 | ||
|
c3419cb082 | ||
|
713243cc5d | ||
|
ee8da33e06 | ||
|
08f868c2ce | ||
|
4d012b156a | ||
|
4c5d34ceb7 | ||
|
8c4b4cd5a9 | ||
|
c1498bbae0 | ||
|
89daf243f4 | ||
|
5b0cd3b458 | ||
|
8aa18a7e03 | ||
|
e3b2c547d8 | ||
|
6cb2677c9b | ||
|
09de8c8387 | ||
|
e6778b5631 | ||
|
9653918a63 | ||
|
b7d231997d | ||
|
3326e375ae | ||
|
6d26361f4e | ||
|
611d2015f9 | ||
|
29f88e29ab | ||
|
58d65c8605 | ||
|
6947a59aa2 | ||
|
2dbf992e56 | ||
|
767602c0dc | ||
|
c1cbc3576c | ||
|
97e12f9b95 | ||
|
d243a5f70e | ||
|
7eaed053f5 | ||
|
7354896a86 | ||
|
ce396ab060 | ||
|
5f59b30a8c | ||
|
49dcd70dd2 | ||
|
6996c704eb | ||
|
d59dcda052 | ||
|
c90c0a261d |
1
.gitignore
vendored
@@ -16,3 +16,4 @@ thirdparty/qtweetlib/WARNING-twitter-api-keys
|
||||
clang/
|
||||
win/
|
||||
gcc/
|
||||
tags
|
||||
|
@@ -16,7 +16,7 @@ SET( TOMAHAWK_DESCRIPTION_SUMMARY "The social media player" )
|
||||
|
||||
SET( TOMAHAWK_VERSION_MAJOR 0 )
|
||||
SET( TOMAHAWK_VERSION_MINOR 2 )
|
||||
SET( TOMAHAWK_VERSION_PATCH 1 )
|
||||
SET( TOMAHAWK_VERSION_PATCH 99 )
|
||||
|
||||
#SET( TOMAHAWK_VERSION_RC 0 )
|
||||
|
||||
@@ -24,6 +24,8 @@ SET( TOMAHAWK_VERSION_PATCH 1 )
|
||||
# build options
|
||||
option(BUILD_GUI "Build Tomahawk with GUI" ON)
|
||||
option(BUILD_RELEASE "Generate TOMAHAWK_VERSION without GIT info" OFF)
|
||||
option(BUILD_GUI_QML"Build Tomahawk with QML Support" OFF)
|
||||
|
||||
|
||||
# generate version string
|
||||
|
||||
@@ -71,6 +73,15 @@ ELSE()
|
||||
MESSAGE( STATUS "Building Tomahawk ${TOMAHAWK_VERSION} full GUI version ***" )
|
||||
LIST(APPEND NEEDED_QT4_COMPONENTS "QtGui" "QtWebkit" )
|
||||
ENDIF()
|
||||
IF( BUILD_GUI_QML )
|
||||
MESSAGE( STATUS "Building Tomahawk QML version ***" )
|
||||
LIST(APPEND NEEDED_QT4_COMPONENTS "QtDeclarative" )
|
||||
ENDIF()
|
||||
|
||||
|
||||
IF( BUILD_GUI AND UNIX AND NOT APPLE )
|
||||
FIND_PACKAGE( X11 )
|
||||
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 \n the qtwebkit-devel package is installed as well")
|
||||
@@ -98,7 +109,8 @@ check_taglib_filename( COMPLEX_TAGLIB_FILENAME )
|
||||
macro_optional_find_package(Boost)
|
||||
macro_log_feature(Boost_FOUND "Boost" "Provides free peer-reviewed portable C++ source libraries" "http://www.boost.org" TRUE "" "") #FIXME: give useful explaination
|
||||
|
||||
|
||||
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 "" "")
|
||||
|
||||
# required
|
||||
#While we distribute our own liblastfm2, don't need to look for it
|
||||
@@ -153,9 +165,12 @@ macro_optional_find_package(KDE4Installed)
|
||||
|
||||
# macro_optional_find_package(KDE4)
|
||||
IF(KDE4_FOUND)
|
||||
#KDE4 adds and removes some compiler flags that we don't like
|
||||
STRING( REPLACE "-std=iso9899:1990" "" CLEAN_C_FLAGS ${CMAKE_C_FLAGS} )
|
||||
SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions" )
|
||||
IF( CMAKE_C_FLAGS )
|
||||
# KDE4 adds and removes some compiler flags that we don't like
|
||||
# (only for gcc not for clang e.g.)
|
||||
STRING( REPLACE "-std=iso9899:1990" "" CLEAN_C_FLAGS ${CMAKE_C_FLAGS} )
|
||||
SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions" )
|
||||
ENDIF()
|
||||
ELSE()
|
||||
SET( CLEAN_C_FLAGS ${CMAKE_C_FLAGS} )
|
||||
ENDIF()
|
||||
|
48
CMakeModules/FindQCA2.cmake
Normal file
@@ -0,0 +1,48 @@
|
||||
# - Try to find QCA2 (Qt Cryptography Architecture 2)
|
||||
# Once done this will define
|
||||
#
|
||||
# QCA2_FOUND - system has QCA2
|
||||
# QCA2_INCLUDE_DIR - the QCA2 include directory
|
||||
# QCA2_LIBRARIES - the libraries needed to use QCA2
|
||||
# QCA2_DEFINITIONS - Compiler switches required for using QCA2
|
||||
#
|
||||
# use pkg-config to get the directories and then use these values
|
||||
# in the FIND_PATH() and FIND_LIBRARY() calls
|
||||
|
||||
# Copyright (c) 2006, Michael Larouche, <michael.larouche@kdemail.net>
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
|
||||
|
||||
include(FindLibraryWithDebug)
|
||||
|
||||
if (QCA2_INCLUDE_DIR AND QCA2_LIBRARIES)
|
||||
|
||||
# in cache already
|
||||
set(QCA2_FOUND TRUE)
|
||||
|
||||
else (QCA2_INCLUDE_DIR AND QCA2_LIBRARIES)
|
||||
|
||||
|
||||
if (NOT WIN32)
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(PC_QCA2 qca2)
|
||||
set(QCA2_DEFINITIONS ${PC_QCA2_CFLAGS_OTHER})
|
||||
endif (NOT WIN32)
|
||||
|
||||
find_library_with_debug(QCA2_LIBRARIES
|
||||
WIN32_DEBUG_POSTFIX d
|
||||
NAMES qca
|
||||
HINTS ${PC_QCA2_LIBDIR} ${PC_QCA2_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
find_path(QCA2_INCLUDE_DIR qca.h
|
||||
HINTS ${PC_QCA2_INCLUDEDIR} ${PC_QCA2_INCLUDE_DIRS}
|
||||
PATH_SUFFIXES QtCrypto)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(QCA2 DEFAULT_MSG QCA2_LIBRARIES QCA2_INCLUDE_DIR)
|
||||
|
||||
mark_as_advanced(QCA2_INCLUDE_DIR QCA2_LIBRARIES)
|
||||
|
||||
endif (QCA2_INCLUDE_DIR AND QCA2_LIBRARIES)
|
@@ -203,7 +203,7 @@ Function PageReinstall
|
||||
IntCmp $R0 ${VER_MINOR} build_check new_version older_version
|
||||
build_check:
|
||||
ReadRegDWORD $R0 HKLM "Software\Tomahawk" "VersionBuild"
|
||||
IntCmp $R0 ${VER_BUILD} new_version older_version
|
||||
IntCmp $R0 ${VER_BUILD} same_version new_version older_version
|
||||
|
||||
new_version:
|
||||
!insertmacro INSTALLOPTIONS_WRITE "NSIS.InstallOptions.ini" "Field 1" "Text" "An older version of Tomahawk is installed on your system. It is recommended that you uninstall the current version before installing. Select the operation you want to perform and click Next to continue."
|
||||
|
32
ChangeLog
@@ -1,3 +1,35 @@
|
||||
Version 0.3.0:
|
||||
* Added Charts page, which shows various sources' top hits & artists.
|
||||
* The Collection tree-views can now be filtered.
|
||||
* Moved the song queue below to the left, below the sidebar.
|
||||
* Added Footnotes, a contextual view that you can slide it.
|
||||
* Show recently added playlists in dashboard rather than recently opened
|
||||
playlists.
|
||||
* Added MPRIS 2.1 support.
|
||||
|
||||
Version 0.2.3:
|
||||
* Fixed opening Rdio and Spotify links.
|
||||
* Fixed potential crash in sidebar during syncing of sources.
|
||||
* When Listening Along, the last song a peer plays is no longer duplicated.
|
||||
* Fixed an issue where the Twitter plugin could get out of sync if the
|
||||
database was cleared, leading to eventual crashes when re-connecting.
|
||||
* Fixed duplicate albums showing up on Dashboard.
|
||||
* Automatically sort search results by score.
|
||||
* Fixed stations being stuck not fetching more songs.
|
||||
* Fixed issue where artist bio could be referring to a different artist.
|
||||
* Opening a "tomahawk" URL (or other URL with Tomahawk) brings the Tomahawk
|
||||
window to the foreground.
|
||||
|
||||
Version 0.2.2:
|
||||
* Fixed crash pressing previous and next when playing a song from the Queue.
|
||||
* Fixed issue where wrench for newly added resolvers would not show up.
|
||||
* Fixed sidebar statistics not updating after collection scan finished.
|
||||
* Fixed omitting a few tracks in the Collection tree-view.
|
||||
* Fixed sidebar & track sorting issues.
|
||||
* Seek- & volume sliders now directly jump to the position you clicked on.
|
||||
* Added ability to drag artists and albums within Tomahawk.
|
||||
* (OS X) Fixed Ogg Vorbis support.
|
||||
|
||||
Version 0.2.1:
|
||||
* Fixed crashing trying to play an unavailable track.
|
||||
* Fixed a crash caused by using Javascript resolvers.
|
||||
|
@@ -1,60 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363) -->
|
||||
<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="841.89px" height="595.28px" viewBox="0 0 841.89 595.28" enable-background="new 0 0 841.89 595.28" xml:space="preserve">
|
||||
<path fill="#010101" d="M543.773,253.359c0-49.962-19.305-86.572-54.194-104.54C477.838,71.133,405.027,13.418,316.568,13.418
|
||||
c-86.917,0-159.483,56.481-172.605,132.58c-38.049,16.818-59.889,55.24-59.889,107.361c0,27.029,7.186,51.825,20.321,71.748
|
||||
c-1.816,1.566-3.444,3.283-4.768,5.24c0,0,2.582,2.36,3.689,3.374c-4.262,2.123-8.22,4.322-11.555,6.669
|
||||
c0,0,3.022,7.355,5.898,14.352c-11.991,9.687-21.314,18.92-27.553,27.51c0,0,1.612,1.789,2.011,2.224
|
||||
c-12.355,9.158-22.133,18.206-28.528,27.021c0,0,6.925,7.351,12.408,13.167c-17.824,28.759-43.348,74.85-43.348,102.987
|
||||
c0,3.281,0.346,6.318,1.093,9.054c1.764,6.442,5.752,11.437,11.229,14.058c15.255,7.311,39.648-6.364,72.589-40.434
|
||||
c-0.828,8.288-1.457,16.663-1.457,24.737c0,16.804,2.266,32.07,8.77,41.249c4.886,6.895,10.898,9.07,15.084,9.683
|
||||
c6.721,0.989,26.375,3.796,57.992-61.296c2.678,0.705,5.421,1.179,8.235,1.179c8.798,0,17.067-3.425,23.287-9.639
|
||||
c4.286-4.288,7.133-9.584,8.562-15.313c7.516-2.129,14.555-6.702,20.779-13.191c19.563,24.861,44.78,37.643,75.38,37.643
|
||||
c7.318,0,14.474-0.755,21.281-2.243c0.392-0.075,2.555-0.622,2.555-0.622l0.62-0.167c23.05-5.824,42.463-20.41,58-43.254
|
||||
c7.2,9.231,15.733,15.994,24.849,19.458c1.139,6.658,4.224,12.806,9.1,17.69c6.22,6.214,14.488,9.639,23.288,9.639
|
||||
c8.798,0,17.065-3.425,23.285-9.639c6.221-6.228,9.649-14.494,9.649-23.292s-3.429-17.066-9.649-23.294
|
||||
c-2.988-2.988-6.476-5.296-10.248-6.923c0.277-2.947,0.613-5.848,0.613-9.007c0-10.031-1.4-20.982-4.192-31.9
|
||||
c-1.196-4.672-2.757-8.745-4.511-12.567c2.838-6.467,4.805-13.268,4.805-20.426c0-7.317-1.74-14.422-4.706-21.011
|
||||
C509.263,358.346,543.773,313.068,543.773,253.359z M451.232,150.998c-33.395-54.619-88.048-93.359-134.569-85.472
|
||||
c-49.024-7.864-102.777,30.64-135.326,85.018c-2.648,0.208-5.278,0.497-7.875,0.88c8.694-54.414,69.429-111.108,143.107-111.108
|
||||
c74.113,0,135.141,57.197,143.269,112.08C457.013,151.799,454.137,151.348,451.232,150.998z"/>
|
||||
<path fill="#010101" stroke="#FFFFFF" stroke-width="4.8437" d="M110.937,367.38c-72.03,93.07-97.843,163.348-81.865,170.997
|
||||
c15.97,7.654,74.912-46.056,139.701-143.288c45.751-68.648,60.797-94.429,45.68-95.922l20.614-43.357l-10.685-6.644l-33.912,33.371
|
||||
width="600px" height="600px" viewBox="0 0 600 600" enable-background="new 0 0 600 600" xml:space="preserve">
|
||||
<path fill="#010101" d="M543.773,253.359c0-49.962-19.305-86.572-54.194-104.54C477.84,71.133,405.027,13.418,316.568,13.418
|
||||
c-86.917,0-159.483,56.481-172.605,132.58c-38.049,16.818-59.889,55.24-59.889,107.361c0,27.029,7.188,51.824,20.321,71.749
|
||||
c-1.816,1.565-3.444,3.282-4.77,5.239c0,0,2.582,2.359,3.689,3.373c-4.262,2.123-8.22,4.322-11.555,6.67
|
||||
c0,0,3.021,7.355,5.896,14.353c-11.991,9.688-21.312,18.92-27.553,27.51c0,0,1.611,1.789,2.011,2.225
|
||||
c-12.354,9.158-22.133,18.205-28.528,27.021c0,0,6.927,7.35,12.408,13.166c-17.824,28.76-43.348,74.85-43.348,102.988
|
||||
c0,3.278,0.346,6.315,1.093,9.053c1.764,6.443,5.752,11.438,11.229,14.059c15.255,7.312,39.646-6.362,72.589-40.434
|
||||
c-0.828,8.287-1.457,16.662-1.457,24.736c0,16.805,2.266,32.069,8.77,41.25c4.887,6.895,10.898,9.067,15.084,9.682
|
||||
c6.723,0.99,26.375,3.797,57.992-61.295c2.678,0.705,5.421,1.178,8.235,1.178c8.798,0,17.065-3.424,23.287-9.639
|
||||
c4.284-4.287,7.133-9.584,8.562-15.312c7.516-2.129,14.555-6.701,20.779-13.19c19.562,24.86,44.779,37.643,75.38,37.643
|
||||
c7.317,0,14.474-0.754,21.281-2.242c0.392-0.073,2.555-0.623,2.555-0.623l0.62-0.166c23.05-5.823,42.463-20.409,58-43.254
|
||||
c7.2,9.23,15.731,15.994,24.849,19.457c1.141,6.658,4.226,12.808,9.102,17.691c6.22,6.213,14.487,9.639,23.288,9.639
|
||||
c8.798,0,17.063-3.426,23.285-9.639c6.221-6.229,9.647-14.494,9.647-23.293c0-8.797-3.429-17.066-9.647-23.293
|
||||
c-2.988-2.988-6.478-5.297-10.248-6.924c0.275-2.947,0.611-5.849,0.611-9.009c0-10.028-1.398-20.979-4.19-31.897
|
||||
c-1.196-4.672-2.757-8.746-4.513-12.568c2.84-6.467,4.807-13.268,4.807-20.426c0-7.316-1.74-14.422-4.706-21.01
|
||||
C509.263,358.345,543.773,313.068,543.773,253.359z M451.232,150.998c-33.396-54.619-88.048-93.359-134.569-85.472
|
||||
c-49.022-7.864-102.775,30.64-135.326,85.018c-2.646,0.208-5.276,0.497-7.875,0.88c8.694-54.414,69.431-111.108,143.107-111.108
|
||||
c74.113,0,135.142,57.197,143.271,112.08C457.013,151.799,454.137,151.348,451.232,150.998z"/>
|
||||
<path fill="#010101" stroke="#FFFFFF" stroke-width="4.8437" d="M110.937,367.38c-72.03,93.07-97.843,163.349-81.865,170.996
|
||||
c15.97,7.654,74.912-46.055,139.701-143.287c45.751-68.647,60.797-94.43,45.68-95.922l20.614-43.357l-10.687-6.644l-33.91,33.371
|
||||
C179.323,272.615,166.073,296.146,110.937,367.38z"/>
|
||||
<path fill="#010101" stroke="#FFFFFF" stroke-width="4.8437" d="M140.932,379.755c-39.099,113.042-39.738,189.89-20.813,192.654
|
||||
c18.912,2.787,59.039-67.616,89.306-182.6c21.381-81.178,27.255-111.03,11.438-108.001l5.133-48.806l-13.207-3.354l-22.194,42.936
|
||||
<path fill="#010101" stroke="#FFFFFF" stroke-width="4.8437" d="M140.932,379.755c-39.101,113.041-39.738,189.89-20.813,192.654
|
||||
c18.912,2.787,59.039-67.617,89.306-182.603c21.383-81.178,27.257-111.029,11.438-108l5.133-48.806l-13.207-3.354l-22.192,42.936
|
||||
C175.736,266.142,170.865,293.244,140.932,379.755z"/>
|
||||
<circle fill="none" stroke="#010101" stroke-width="4.8437" cx="410.28" cy="388.831" r="37.801"/>
|
||||
<circle fill="none" stroke="#010101" stroke-width="4.8437" cx="410.28" cy="388.832" r="37.801"/>
|
||||
<path fill="#ED2224" stroke="#010101" stroke-width="4.8437" d="M475.237,157.792c-7.115-73.197-76.231-130.645-160.495-130.645
|
||||
c-83.402,0-152.009,56.27-160.306,128.393c-39.809,13.607-58.455,52.219-58.455,97.818c0,56.947,34.681,103.109,89.925,103.109
|
||||
c35.784,0,67.089-19.432,84.771-48.551c14.01,3.533,28.778,5.463,44.066,5.463c13.16,0,25.932-1.438,38.173-4.077
|
||||
c17.966,28.357,49.108,47.165,84.604,47.165c55.665,0,90.696-46.162,90.696-103.109
|
||||
C528.216,210.073,512.208,173.073,475.237,157.792z M314.742,274.908c-10.501,0-20.723-0.878-30.584-2.506
|
||||
c-83.402,0-152.009,56.27-160.306,128.393c-39.811,13.607-58.455,52.219-58.455,97.818c0,56.946,34.681,103.108,89.925,103.108
|
||||
c35.784,0,67.089-19.432,84.771-48.551c14.01,3.533,28.776,5.463,44.064,5.463c13.16,0,25.934-1.438,38.173-4.076
|
||||
c17.966,28.357,49.108,47.164,84.604,47.164c55.665,0,90.696-46.162,90.696-103.108
|
||||
C528.218,210.073,512.209,173.073,475.237,157.792z M314.742,274.908c-10.501,0-20.723-0.878-30.584-2.506
|
||||
c1.125-6.177,1.778-12.527,1.778-19.043c0-56.941-44.786-103.104-100.03-103.104c-4.858,0-9.597,0.478-14.271,1.169
|
||||
c8.694-54.414,69.43-111.108,143.107-111.108c74.113,0,135.142,57.197,143.268,112.08c-6.617-1.398-13.471-2.141-20.49-2.141
|
||||
c8.692-54.414,69.43-111.108,143.105-111.108c74.113,0,135.144,57.197,143.27,112.08c-6.617-1.398-13.473-2.141-20.49-2.141
|
||||
c-55.675,0-100.801,46.163-100.801,103.104c0,6.852,0.687,13.536,1.931,20.013C330.872,274.364,322.888,274.908,314.742,274.908z"/>
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-55.6953" y1="95.2363" x2="39.7773" y2="95.2363" gradientTransform="matrix(-0.3782 -0.8348 1.083 -0.4907 70.5233 338.0542)">
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-1087.6663" y1="191.4385" x2="-992.1917" y2="191.4385" gradientTransform="matrix(-0.3782 -0.8348 1.083 -0.4907 -423.9551 -476.2263)">
|
||||
<stop offset="0" style="stop-color:#010101"/>
|
||||
<stop offset="0.2606" style="stop-color:#3E221C"/>
|
||||
<stop offset="0.7732" style="stop-color:#B03126"/>
|
||||
<stop offset="1" style="stop-color:#ED2224"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_1_)" d="M153.69,260.35c31.322-14.19,65.739-18.887,77.129,6.254c11.391,25.14-4.763,57.027-36.091,71.213
|
||||
c-31.323,14.194-65.948,5.312-77.338-19.829C106,292.849,122.366,274.543,153.69,260.35z"/>
|
||||
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="-180.8516" y1="181.2642" x2="-85.3789" y2="181.2642" gradientTransform="matrix(-0.9008 -0.3607 0.555 -1.386 252.7537 479.2919)">
|
||||
<path fill="url(#SVGID_1_)" d="M153.69,260.35c31.322-14.19,65.739-18.887,77.129,6.254c11.391,25.14-4.763,57.026-36.091,71.214
|
||||
c-31.323,14.192-65.948,5.311-77.338-19.83C106,292.849,122.366,274.543,153.69,260.35z"/>
|
||||
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="-1275.886" y1="215.5034" x2="-1180.4114" y2="215.5034" gradientTransform="matrix(-0.9008 -0.3607 0.555 -1.386 -752.6548 131.7681)">
|
||||
<stop offset="0" style="stop-color:#B11F24"/>
|
||||
<stop offset="0.1017" style="stop-color:#B62024"/>
|
||||
<stop offset="1" style="stop-color:#ED2224"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_2_)" d="M427.738,265.165c16.043-40.085,41.342-74.985,68.473-64.122
|
||||
c27.122,10.86,36.111,52.165,20.056,92.248c-16.053,40.089-51.062,63.772-78.189,52.911
|
||||
<path fill="url(#SVGID_2_)" d="M427.738,265.165c16.043-40.085,41.342-74.985,68.475-64.122
|
||||
c27.121,10.86,36.109,52.165,20.056,92.248c-16.053,40.089-51.062,63.773-78.189,52.912
|
||||
C410.95,335.343,411.683,305.253,427.738,265.165z"/>
|
||||
<path fill="#010101" stroke="#010101" stroke-width="4.8437" d="M448.219,425.226c7.776,30.397,3.982,62.358-14.521,62.358
|
||||
c-16.301,0-34.904-17.333-42.675-47.733c-7.777-30.4,4.243-75.016,14.521-62.365C423.583,399.707,440.442,394.825,448.219,425.226z"
|
||||
/>
|
||||
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="217.0322" y1="557.499" x2="165.1699" y2="467.6709" gradientTransform="matrix(0.9868 0.0515 0.0515 0.7987 -5.5217 21.3475)">
|
||||
<path fill="#010101" stroke="#010101" stroke-width="4.8437" d="M448.219,425.226c7.774,30.396,3.98,62.357-14.521,62.357
|
||||
c-16.301,0-34.904-17.332-42.675-47.732c-7.777-30.399,4.243-75.016,14.521-62.364C423.584,399.707,440.442,394.826,448.219,425.226
|
||||
z"/>
|
||||
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-639.5422" y1="548.502" x2="-691.4051" y2="458.673" gradientTransform="matrix(0.9868 0.0515 0.0515 0.7987 840.2104 72.6462)">
|
||||
<stop offset="0" style="stop-color:#5B3E1D"/>
|
||||
<stop offset="0.1121" style="stop-color:#42301B"/>
|
||||
<stop offset="0.2377" style="stop-color:#2E2316"/>
|
||||
@@ -64,29 +64,30 @@
|
||||
<stop offset="1" style="stop-color:#000000"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_3_)" stroke="#010101" stroke-width="4.8437" d="M184.076,437.859c-6.111,23.875,1.745,46.508,17.54,50.549
|
||||
c15.79,4.039,33.552-12.045,39.658-35.924c6.101-23.881-9.153-57.129-24.947-61.17C200.537,387.275,190.178,413.973,184.076,437.859
|
||||
c15.79,4.039,33.552-12.045,39.658-35.924c6.101-23.882-9.153-57.129-24.947-61.17C200.537,387.275,190.178,413.972,184.076,437.859
|
||||
z"/>
|
||||
<path fill="#010101" stroke="#010101" stroke-width="4.8437" d="M314.837,65.525c72.755-12.333,165.503,89.311,165.503,187.528
|
||||
c0,98.215-74.305,162.834-165.707,162.834"/>
|
||||
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="194.4072" y1="374.3564" x2="358.2427" y2="90.5851">
|
||||
<path fill="#010101" stroke="#010101" stroke-width="4.8437" d="M314.837,65.525c72.757-12.333,165.505,89.311,165.505,187.528
|
||||
c0,98.213-74.307,162.833-165.707,162.833"/>
|
||||
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-664.3811" y1="374.0068" x2="-500.546" y2="90.2362" gradientTransform="matrix(1 0 0 1 858.79 0.3506)">
|
||||
<stop offset="0" style="stop-color:#000000"/>
|
||||
<stop offset="1" style="stop-color:#5B3E1D"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_4_)" stroke="#010101" stroke-width="4.8437" d="M314.634,415.888c-91.402,0-165.297-64.619-165.297-162.834
|
||||
<path fill="url(#SVGID_4_)" stroke="#010101" stroke-width="4.8437" d="M314.635,415.888c-91.402,0-165.299-64.619-165.299-162.833
|
||||
c0-98.218,88.615-199.862,165.5-187.528"/>
|
||||
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="297.3164" y1="139.4717" x2="418.2684" y2="-70.0234" gradientTransform="matrix(-0.6092 0.7802 -0.4118 -0.3216 476.7253 -96.4624)">
|
||||
<linearGradient id="SVGID_5_" gradientUnits="userSpaceOnUse" x1="-760.302" y1="-37.9087" x2="-639.3506" y2="-247.4027" gradientTransform="matrix(-0.6092 0.7802 -0.4118 -0.3216 -240.6183 671.6459)">
|
||||
<stop offset="0" style="stop-color:#8B654B"/>
|
||||
<stop offset="1" style="stop-color:#000000"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_5_)" d="M169.611,266.578c-27.578-21.539-16.863-81.354,23.935-133.604
|
||||
c40.802-52.245,93.808-72.894,126.21-59.689c26.67,10.864,14.474,85.434-26.328,137.681
|
||||
c40.804-52.245,93.81-72.894,126.21-59.689c26.672,10.864,14.476,85.434-26.326,137.681
|
||||
C252.63,263.215,197.193,288.112,169.611,266.578z"/>
|
||||
<circle fill="#010101" cx="214.367" cy="388.831" r="34.682"/>
|
||||
<circle fill="#010101" cx="214.367" cy="388.832" r="34.682"/>
|
||||
<g>
|
||||
<path fill="#F4DFED" d="M131.831,427.709c-23.973,79.733-18.741,132.267-9.011,135.459c10.855,3.563,43.561-47.223,60.839-128.324
|
||||
c12.189-57.265,11.727-83.75,0.009-81.625l3.505-31.111l-8.901-2.432l-14.271,32.445
|
||||
C152.554,347.564,150.184,366.689,131.831,427.709z"/>
|
||||
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="148.1519" y1="319.6758" x2="148.1518" y2="563.168">
|
||||
<path fill="#F4DFED" d="M131.831,427.708c-23.973,79.734-18.741,132.268-9.011,135.459c10.854,3.564,43.561-47.223,60.839-128.324
|
||||
c12.189-57.264,11.729-83.75,0.009-81.625l3.505-31.108l-8.899-2.435l-14.271,32.445
|
||||
C152.554,347.564,150.184,366.689,131.831,427.708z"/>
|
||||
|
||||
<linearGradient id="SVGID_6_" gradientUnits="userSpaceOnUse" x1="-710.6404" y1="319.3252" x2="-710.6405" y2="562.8164" gradientTransform="matrix(1 0 0 1 858.79 0.3506)">
|
||||
<stop offset="0" style="stop-color:#571A54"/>
|
||||
<stop offset="0.2641" style="stop-color:#7C5378"/>
|
||||
<stop offset="0.528" style="stop-color:#A78AA3"/>
|
||||
@@ -94,11 +95,11 @@
|
||||
<stop offset="0.9095" style="stop-color:#EAE1E8"/>
|
||||
<stop offset="1" style="stop-color:#F9F3F8"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_6_)" d="M146.41,479.117l-22.914,19.186l35.325-65.182l4.683-17.371c0,0,3.098-26.758-24.228,14.713
|
||||
c16.962-56.432,32.317-62.998,32.317-62.998l11.404-46.658l-4.725-1.131l-14.702,30.23c-11.429-4.588-13.859,14.521-32.392,75.485
|
||||
c-24.224,79.655-20.501,124.085-8.358,137.776L146.41,479.117z"/>
|
||||
<path fill="url(#SVGID_6_)" d="M146.41,479.117l-22.914,19.186l35.325-65.182l4.683-17.371c0,0,3.1-26.758-24.228,14.713
|
||||
c16.962-56.432,32.317-62.998,32.317-62.998l11.402-46.658l-4.725-1.131l-14.702,30.23c-11.429-4.588-13.859,14.521-32.392,75.483
|
||||
c-24.226,79.656-20.501,124.087-8.358,137.777L146.41,479.117z"/>
|
||||
|
||||
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="75.7998" y1="402.9658" x2="43.9086" y2="490.7602" gradientTransform="matrix(0.9399 -0.3414 0.3414 0.9399 -44.7892 56.207)">
|
||||
<linearGradient id="SVGID_7_" gradientUnits="userSpaceOnUse" x1="-789.3508" y1="444.1797" x2="-821.2424" y2="531.975" gradientTransform="matrix(0.9399 -0.3414 0.3414 0.9399 754.2939 -277.891)">
|
||||
<stop offset="0" style="stop-color:#802986"/>
|
||||
<stop offset="0.2641" style="stop-color:#9D66A2"/>
|
||||
<stop offset="0.528" style="stop-color:#BE9BC2"/>
|
||||
@@ -106,10 +107,10 @@
|
||||
<stop offset="0.9095" style="stop-color:#F0E6F1"/>
|
||||
<stop offset="1" style="stop-color:#F9F3F8"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_7_)" d="M147.332,501.478l31.839-92.4c0,0,6.608,60.692-7.474,93.405
|
||||
c1.438-44.878-2.328-36.951-9.176-25.254C159.71,482.03,147.332,501.478,147.332,501.478z"/>
|
||||
<path fill="url(#SVGID_7_)" d="M147.332,501.478l31.839-92.399c0,0,6.608,60.69-7.474,93.406
|
||||
c1.438-44.879-2.328-36.951-9.176-25.257C159.71,482.031,147.332,501.478,147.332,501.478z"/>
|
||||
|
||||
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="100.2559" y1="370.0205" x2="67.8228" y2="459.3065" gradientTransform="matrix(0.9399 -0.3414 0.3414 0.9399 -44.7892 56.207)">
|
||||
<linearGradient id="SVGID_8_" gradientUnits="userSpaceOnUse" x1="-764.8928" y1="411.2344" x2="-797.3259" y2="500.5203" gradientTransform="matrix(0.9399 -0.3414 0.3414 0.9399 754.2939 -277.891)">
|
||||
<stop offset="0" style="stop-color:#802986"/>
|
||||
<stop offset="0.2641" style="stop-color:#9D66A2"/>
|
||||
<stop offset="0.528" style="stop-color:#BE9BC2"/>
|
||||
@@ -117,10 +118,10 @@
|
||||
<stop offset="0.9095" style="stop-color:#F0E6F1"/>
|
||||
<stop offset="1" style="stop-color:#F9F3F8"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_8_)" d="M156.286,463.716l38.825-93.952c0,0,2.251,62.278-11.831,94.991
|
||||
c-0.298-44.249-5.388-28.089-8.538-23.508C165.662,454.416,156.286,463.716,156.286,463.716z"/>
|
||||
<path fill="url(#SVGID_8_)" d="M156.286,463.716l38.825-93.953c0,0,2.251,62.279-11.831,94.992
|
||||
c-0.298-44.25-5.388-28.09-8.538-23.508C165.662,454.416,156.286,463.716,156.286,463.716z"/>
|
||||
|
||||
<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="19.1768" y1="337.1123" x2="-32.4432" y2="389.2988" gradientTransform="matrix(0.711 -0.7032 0.7032 0.711 -56.5767 131.5096)">
|
||||
<linearGradient id="SVGID_9_" gradientUnits="userSpaceOnUse" x1="-872.7551" y1="422.8174" x2="-924.3751" y2="475.0038" gradientTransform="matrix(0.711 -0.7032 0.7032 0.711 517.3177 -556.6326)">
|
||||
<stop offset="0" style="stop-color:#571A54"/>
|
||||
<stop offset="0.2641" style="stop-color:#7C5378"/>
|
||||
<stop offset="0.528" style="stop-color:#A78AA3"/>
|
||||
@@ -128,21 +129,22 @@
|
||||
<stop offset="0.9095" style="stop-color:#EAE1E8"/>
|
||||
<stop offset="1" style="stop-color:#F9F3F8"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_9_)" d="M180.916,431.115l9.787-73.404c0,0,18.589,43.111,16.428,71.425
|
||||
c-11.773-30.423-13.671-21.048-17.578-14.96C187.396,417.538,180.916,431.115,180.916,431.115z"/>
|
||||
<path fill="#1E3D73" d="M174.914,335.556L158.76,362.31l-23.24,76.647c0,0,1.211-8.173,1.788-15.883l-18.783,50.773
|
||||
c0,0,8.386-31.226,3.609-28.382c-4.777,2.84,4.225-21.91-23.102,13.729c5.316-18.514,20.495-39.508,33.324-54.9
|
||||
c-2.172,0.474-7.1,4.788-18.387,18.374c4.38-15.232,14.957-32.934,25.358-47.898c-1.159-2.683-5.151-3.889-21.234,5.221
|
||||
C134.366,356.719,174.914,335.556,174.914,335.556z"/>
|
||||
<path fill="url(#SVGID_9_)" d="M180.916,431.115l9.787-73.404c0,0,18.589,43.111,16.428,71.426
|
||||
c-11.771-30.424-13.671-21.049-17.576-14.961C187.396,417.539,180.916,431.115,180.916,431.115z"/>
|
||||
<path fill="#1E3D73" d="M174.914,335.556L158.76,362.31l-23.24,76.646c0,0,1.211-8.172,1.788-15.883l-18.783,50.772
|
||||
c0,0,8.386-31.227,3.607-28.383c-4.775,2.84,4.227-21.91-23.102,13.73c5.316-18.517,20.495-39.511,33.324-54.9
|
||||
c-2.172,0.473-7.102,4.787-18.388,18.373c4.381-15.232,14.956-32.934,25.357-47.898c-1.159-2.682-5.151-3.889-21.234,5.224
|
||||
C134.366,356.718,174.914,335.556,174.914,335.556z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#F4DFED" d="M94.453,401.163c-49.752,66.752-62.779,117.913-54.719,124.242c8.987,7.059,57.064-29.51,100.989-99.844
|
||||
c31.011-49.657,39.62-74.709,27.879-76.714l13.916-28.052l-7.539-5.319L150.496,341.1
|
||||
C141.291,332.911,132.531,350.072,94.453,401.163z"/>
|
||||
<path fill="#656B84" d="M90.603,454.464L62.515,464.67l55.456-49.201l10.331-14.731c0,0,12.047-24.096-27.794,5.558
|
||||
c35.211-47.255,51.89-48.182,51.89-48.182l26.641-39.956l-4.058-2.681l-24.133,23.399c-9.177-8.222-17.989,8.911-56.224,59.885
|
||||
c-49.96,66.6-61.634,109.635-54.889,126.645L90.603,454.464z"/>
|
||||
<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="106.2383" y1="485.0312" x2="121.9901" y2="395.6984">
|
||||
<path fill="#F4DFED" d="M94.453,401.164c-49.752,66.752-62.779,117.912-54.719,124.242c8.987,7.059,57.062-29.513,100.989-99.847
|
||||
c31.011-49.655,39.62-74.709,27.879-76.713l13.916-28.053l-7.539-5.318l-24.483,25.623
|
||||
C141.291,332.912,132.531,350.072,94.453,401.164z"/>
|
||||
<path fill="#656B84" d="M90.603,454.464l-28.088,10.205l55.456-49.201l10.331-14.729c0,0,12.047-24.097-27.796,5.559
|
||||
c35.213-47.256,51.892-48.182,51.892-48.182l26.641-39.957l-4.058-2.683l-24.133,23.4c-9.179-8.223-17.989,8.91-56.226,59.885
|
||||
c-49.96,66.601-61.634,109.635-54.889,126.646L90.603,454.464z"/>
|
||||
|
||||
<linearGradient id="SVGID_10_" gradientUnits="userSpaceOnUse" x1="-752.551" y1="484.6816" x2="-736.7991" y2="395.3488" gradientTransform="matrix(1 0 0 1 858.79 0.3506)">
|
||||
<stop offset="0" style="stop-color:#571A54"/>
|
||||
<stop offset="0.2641" style="stop-color:#7C5378"/>
|
||||
<stop offset="0.528" style="stop-color:#A78AA3"/>
|
||||
@@ -150,9 +152,10 @@
|
||||
<stop offset="0.9095" style="stop-color:#EAE1E8"/>
|
||||
<stop offset="1" style="stop-color:#F9F3F8"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_10_)" d="M83.829,475.791l61.474-75.981c0,0-14.507,59.304-38.916,85.248
|
||||
c16.678-41.696,12.058-33.368,0-26.873C101.491,460.821,83.829,475.791,83.829,475.791z"/>
|
||||
<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="130.9844" y1="453.7012" x2="146.8758" y2="363.5764">
|
||||
<path fill="url(#SVGID_10_)" d="M83.829,475.791l61.476-75.98c0,0-14.509,59.306-38.916,85.248
|
||||
c16.678-41.694,12.058-33.366,0-26.873C101.491,460.822,83.829,475.791,83.829,475.791z"/>
|
||||
|
||||
<linearGradient id="SVGID_11_" gradientUnits="userSpaceOnUse" x1="-727.8064" y1="453.3486" x2="-711.9149" y2="363.2233" gradientTransform="matrix(1 0 0 1 858.79 0.3506)">
|
||||
<stop offset="0" style="stop-color:#571A54"/>
|
||||
<stop offset="0.2641" style="stop-color:#7C5378"/>
|
||||
<stop offset="0.528" style="stop-color:#A78AA3"/>
|
||||
@@ -160,37 +163,36 @@
|
||||
<stop offset="0.9095" style="stop-color:#EAE1E8"/>
|
||||
<stop offset="1" style="stop-color:#F9F3F8"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_11_)" d="M105.143,443.356l68.564-75.05c0,0-19.143,59.297-43.551,85.248
|
||||
c14.824-41.701,10.567-27.993,0-25.023C124.802,430.041,105.143,443.356,105.143,443.356z"/>
|
||||
<path fill="#656B84" d="M139.423,421.124l34.26-65.654c0,0,2.748,46.867-8.945,72.74c-0.676-32.615-3.041-28.432-11.413-20.06
|
||||
C150.5,410.974,139.423,421.124,139.423,421.124z"/>
|
||||
<path fill="#656B84" d="M166.408,329.256l-24.322,19.63l-48.011,64.112c0,0,3.931-7.274,7.104-14.322l-34.994,41.313
|
||||
c0,0,18.552-26.484,13.089-25.448c-5.464,1.04,11.451-19.148-26.399,5.019c11.313-15.587,32.751-30.137,50.064-40.227
|
||||
c-2.205-0.298-8.316,2.077-23.552,10.989c9.313-12.818,25.302-25.842,40.183-36.357c-0.175-2.919-3.515-5.416-21.74-2.346
|
||||
C121.065,335.3,166.408,329.256,166.408,329.256z"/>
|
||||
<path fill="url(#SVGID_11_)" d="M105.143,443.357l68.562-75.052c0,0-19.143,59.297-43.551,85.248
|
||||
c14.824-41.7,10.567-27.994,0-25.022C124.802,430.041,105.143,443.357,105.143,443.357z"/>
|
||||
<path fill="#656B84" d="M139.423,421.125l34.262-65.654c0,0,2.748,46.867-8.945,72.74c-0.676-32.615-3.041-28.432-11.413-20.061
|
||||
C150.5,410.974,139.423,421.125,139.423,421.125z"/>
|
||||
<path fill="#656B84" d="M166.408,329.255l-24.322,19.631l-48.011,64.111c0,0,3.931-7.273,7.104-14.322L66.185,439.99
|
||||
c0,0,18.552-26.484,13.089-25.449c-5.464,1.041,11.451-19.148-26.399,5.02c11.313-15.588,32.751-30.137,50.064-40.227
|
||||
c-2.205-0.299-8.316,2.076-23.552,10.988c9.312-12.818,25.302-25.842,40.183-36.357c-0.175-2.918-3.515-5.416-21.74-2.346
|
||||
C121.065,335.3,166.408,329.255,166.408,329.255z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#D9AF82" enable-background="new " d="M315.05,115.063c-50.514,0-83.218,15.021-109.641,64.839
|
||||
c-2.502,4.713-0.232,14.337-2.796,19.152c-13.845,26.007-37.089,48.236-37.089,71.707c0,34.337,19.1,65.637,42.505,89.297
|
||||
c12.185,71.644,34.7,151.593,104.339,151.593"/>
|
||||
<path fill="#010101" d="M203.271,178.766c-1.519,2.855-1.59,6.774-1.656,10.562c-0.062,3.283-0.123,6.677-1.14,8.588
|
||||
c-4.537,8.519-10.146,16.707-15.577,24.624c-11.21,16.353-21.797,31.798-21.797,48.221c0,30.307,15.166,62.382,42.666,90.413
|
||||
c12.578,73.606,36.115,150.477,106.6,150.477v-1.546c-67.084,0-89.722-78.554-101.95-150.453l-0.127-0.748l-0.54-0.549
|
||||
c-26.957-27.255-41.805-58.361-41.805-87.594c0-14.923,10.174-29.766,20.949-45.482c5.501-8.027,11.192-16.327,15.857-25.087
|
||||
c1.56-2.935,1.636-6.92,1.707-10.773c0.057-3.221,0.118-6.551,1.088-8.381c24.256-45.734,54.398-65.974,107.503-65.974v-2.422
|
||||
<path fill="#D9AF82" d="M315.05,115.063c-50.514,0-83.218,15.021-109.641,64.839c-2.502,4.713-0.23,14.337-2.796,19.152
|
||||
c-13.845,26.007-37.089,48.236-37.089,71.707c0,34.335,19.1,65.637,42.505,89.296c12.185,71.646,34.7,151.595,104.339,151.595"/>
|
||||
<path fill="#010101" d="M203.271,178.766c-1.521,2.855-1.59,6.774-1.656,10.562c-0.062,3.283-0.123,6.677-1.14,8.588
|
||||
c-4.537,8.519-10.146,16.707-15.577,24.624c-11.21,16.353-21.797,31.798-21.797,48.221c0,30.307,15.166,62.38,42.666,90.412
|
||||
c12.578,73.607,36.113,150.479,106.6,150.479v-1.547c-67.084,0-89.722-78.556-101.95-150.453l-0.127-0.748l-0.54-0.549
|
||||
c-26.957-27.257-41.805-58.361-41.805-87.594c0-14.923,10.174-29.766,20.949-45.482c5.501-8.027,11.19-16.327,15.855-25.087
|
||||
c1.562-2.935,1.638-6.92,1.707-10.773c0.059-3.221,0.118-6.551,1.088-8.381c24.258-45.734,54.398-65.974,107.503-65.974v-2.422
|
||||
C259.849,112.641,228.506,131.181,203.271,178.766z"/>
|
||||
</g>
|
||||
<path fill="#8B654B" d="M312.368,511.65c72.045,0,92.163-79.949,104.338-151.593c23.405-23.66,42.512-54.96,42.512-89.297
|
||||
c0-37.004-22.588-49.51-38.609-77.154c-5.681-9.798-1.496-24.634-8.084-33.382c-26.905-35.728-53.772-45.162-97.475-45.162"/>
|
||||
<path fill="#8B654B" d="M312.368,511.65c72.045,0,92.163-79.949,104.338-151.595c23.405-23.657,42.514-54.959,42.514-89.296
|
||||
c0-37.004-22.588-49.51-38.609-77.154c-5.681-9.798-1.496-24.634-8.084-33.382c-26.905-35.728-53.772-45.162-97.477-45.162"/>
|
||||
<ellipse fill="#D9AF82" cx="313.792" cy="343.947" rx="21.906" ry="68.144"/>
|
||||
<path fill="#8B654B" d="M342.916,373.454c0,7.813-14.98,12.535-27.275,12.535c-12.293,0-27.808-4.735-27.808-12.549
|
||||
c3.43-3.43,15.246,4.886,27.544,4.886C334.789,378.326,342.916,312.495,342.916,373.454z"/>
|
||||
<path fill="#D9AF82" d="M335.697,435.217c0,37.637-9.81,68.831-21.91,68.831c-12.096,0-21.901-31.194-21.901-68.831
|
||||
c0-37.639,9.882-50.259,21.977-50.259C325.962,384.958,335.697,397.578,335.697,435.217z"/>
|
||||
<path opacity="0.36" fill="#8A644B" d="M328.365,281.605c-1.826,24.681-14.186-7.573-34.757,20.974
|
||||
c-8.672,12.026-23.23,10.877-38.845,10.877c-39.61,0-66.544-26.03-67.859-38.868c-2.517-24.557,29.024-39.586,71.464-39.586
|
||||
<path fill="#8B654B" d="M342.916,373.455c0,7.812-14.979,12.535-27.273,12.535c-12.293,0-27.81-4.736-27.81-12.549
|
||||
c3.432-3.433,15.246,4.885,27.544,4.885C334.789,378.326,342.916,312.496,342.916,373.455z"/>
|
||||
<path fill="#D9AF82" d="M335.697,435.216c0,37.637-9.81,68.832-21.91,68.832c-12.096,0-21.899-31.195-21.899-68.832
|
||||
c0-37.639,9.882-50.258,21.977-50.258C325.962,384.958,335.697,397.578,335.697,435.216z"/>
|
||||
<path opacity="0.36" fill="#8A644B" enable-background="new " d="M328.365,281.605c-1.826,24.682-14.186-7.573-34.757,20.975
|
||||
c-8.672,12.025-23.23,10.877-38.845,10.877c-39.61,0-66.544-26.031-67.859-38.869c-2.517-24.557,29.024-39.586,71.464-39.586
|
||||
C297.028,235.002,329.255,269.622,328.365,281.605z"/>
|
||||
<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="214.7554" y1="341.0537" x2="290.4385" y2="341.0537">
|
||||
<linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="-644.0354" y1="340.7031" x2="-568.3508" y2="340.7031" gradientTransform="matrix(1 0 0 1 858.79 0.3506)">
|
||||
<stop offset="0" style="stop-color:#D9AF82"/>
|
||||
<stop offset="0.0786" style="stop-color:#DFB791"/>
|
||||
<stop offset="0.2053" style="stop-color:#E7C1A5"/>
|
||||
@@ -199,40 +201,38 @@
|
||||
<stop offset="0.6917" style="stop-color:#F4D3C7"/>
|
||||
<stop offset="1" style="stop-color:#F5D4C9"/>
|
||||
</linearGradient>
|
||||
<path opacity="0.36" fill="url(#SVGID_12_)" d="M272.246,361.529c-28.722,19.46-56.346-24.299-57.491-43.314
|
||||
c15.913,13.821,62.032,18.457,75.683-2.517L272.246,361.529z"/>
|
||||
<path opacity="0.36" fill="#8A644B" d="M313.706,461.213c-38.167,0-61.231-13.681-61.231-31.63c0-6.048,15.651-24.078,37.32-49.365
|
||||
c5.952-3.699,7.464,10.038,14.958,4.731C331.61,392.044,328.318,461.213,313.706,461.213z"/>
|
||||
<path opacity="0.36" fill="url(#SVGID_12_)" enable-background="new " d="M272.246,361.529
|
||||
c-28.722,19.461-56.346-24.299-57.491-43.314c15.913,13.822,62.032,18.457,75.685-2.516L272.246,361.529z"/>
|
||||
<path opacity="0.36" fill="#8A644B" enable-background="new " d="M313.706,461.212c-38.167,0-61.229-13.68-61.229-31.629
|
||||
c0-6.049,15.649-24.078,37.318-49.365c5.952-3.699,7.464,10.037,14.958,4.73C331.61,392.044,328.318,461.212,313.706,461.212z"/>
|
||||
<g>
|
||||
<path fill="#8A644B" d="M260.464,472.116c8.339,23.94,32.817,36.466,52.688,36.466v-4.845
|
||||
C294.99,503.737,268.056,493.921,260.464,472.116L260.464,472.116z"/>
|
||||
<path fill="#8A644B" d="M260.464,472.117c8.341,23.938,32.817,36.465,52.688,36.465v-4.844
|
||||
C294.99,503.738,268.056,493.921,260.464,472.117L260.464,472.117z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#8A644B" d="M180.954,271.658c0,21.359,5.388,36.679,27.099,48.222c0.587,1.121,7.021,13.387,7.021,13.387
|
||||
c8.916,16.375,19.02,34.94,19.02,54.406h4.844c0-20.699-10.416-39.839-19.612-56.725l-7.586-14.455l-0.709-0.426
|
||||
C190.509,305.4,180.954,291.289,180.954,271.658L180.954,271.658z"/>
|
||||
<path fill="#8A644B" d="M180.954,271.658c0,21.359,5.388,36.679,27.101,48.222c0.587,1.121,7.021,13.387,7.021,13.387
|
||||
c8.916,16.375,19.021,34.939,19.021,54.406h4.844c0-20.699-10.416-39.84-19.612-56.725l-7.586-14.455l-0.709-0.426
|
||||
C190.51,305.4,180.954,291.289,180.954,271.658L180.954,271.658z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#010101" d="M208.814,230.649l-0.104-0.97c-3.108-15.25-3.226-33.651-0.312-49.217l-4.764-0.889
|
||||
<path fill="#010101" d="M208.814,230.649l-0.104-0.97c-3.106-15.25-3.226-33.651-0.312-49.217l-4.764-0.889
|
||||
C200.613,195.722,205.583,214.815,208.814,230.649z"/>
|
||||
</g>
|
||||
<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="191.0591" y1="310.5205" x2="451.5771" y2="310.5205">
|
||||
<linearGradient id="SVGID_13_" gradientUnits="userSpaceOnUse" x1="-667.7327" y1="310.1709" x2="-407.218" y2="310.1709" gradientTransform="matrix(1 0 0 1 858.79 0.3506)">
|
||||
<stop offset="0" style="stop-color:#5B3E1D"/>
|
||||
<stop offset="1" style="stop-color:#010101"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_13_)" d="M423.943,199.054c-3.983-11.059-0.737-20.853-8.061-31.231
|
||||
c-19.885-28.185-51.072-56.27-108.998-52.618l5.212,140.363c0,0-122.733-25.589-121.021,15.935c0.227,5.387,40.188,2.88,63.46,4.428
|
||||
c-26.092,4.566-32.185,5.898-32.185,8.838c0,6.206,21.863,0.683,25.108,2.467c4.976,2.739-43.139,7.052-34.351,8.757
|
||||
c10.057,1.951,44.474,3.086,57.444,3.086c28.929,0,41.077-25.412,41.077-4.485c7.346,27.893,14.739,59.24,13.972,69.882
|
||||
c-1.475,20.662-19.62,20.188-19.62,20.188l5.089,24.285c-8.557,0.439-6.245-1.324-13.85-0.549
|
||||
c-14.427,0-32.354,13.032-32.354,16.054l39.989,0.435c0,0-29.081,13.771-22.975,22.928c4.763,7.143,20.316,13.378,31.091,13.424
|
||||
c0,0,3.273,8.55,3.273,22.352c0,13.811-4.035,22.565-4.035,22.565c46.171,0,67.49-49.036,80.324-118.446
|
||||
c6.083-32.876,20.018-58.106,36.034-71.657c15.742-13.321,23.008-26.641,23.008-52.071
|
||||
C451.577,249.847,443.574,230.354,423.943,199.054z"/>
|
||||
<path fill="#D9AF82" d="M325.395,252.416l-13.297,4.328c0,0-65.848-96.356-46.493-121.312
|
||||
c12.682-16.357,24.611-18.136,40.046-19.238c13.519-0.965,21.294,16.525,27.302,24.271
|
||||
C350.375,162.927,325.395,252.416,325.395,252.416z"/>
|
||||
<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="260.7119" y1="113.4033" x2="349.5527" y2="113.4033" gradientTransform="matrix(0.676 0.6564 -0.9247 0.9523 168.3961 -132.5865)">
|
||||
<path fill="url(#SVGID_13_)" d="M423.943,199.054c-3.983-11.059-0.737-20.853-8.062-31.231
|
||||
c-19.885-28.185-51.07-56.271-108.998-52.618l5.214,140.363c0,0-122.733-25.589-121.021,15.935c0.229,5.387,40.188,2.88,63.46,4.428
|
||||
c-26.092,4.566-32.185,5.898-32.185,8.838c0,6.206,21.861,0.683,25.106,2.467c4.978,2.739-43.139,7.052-34.351,8.757
|
||||
c10.057,1.951,44.474,3.086,57.442,3.086c28.931,0,41.077-25.413,41.077-4.485c7.348,27.894,14.739,59.239,13.974,69.882
|
||||
c-1.477,20.661-19.62,20.188-19.62,20.188l5.089,24.285c-8.557,0.438-6.245-1.324-13.85-0.549c-14.429,0-32.354,13.03-32.354,16.055
|
||||
l39.989,0.434c0,0-29.081,13.771-22.977,22.931c4.765,7.143,20.316,13.377,31.093,13.424c0,0,3.271,8.549,3.271,22.352
|
||||
c0,13.812-4.035,22.564-4.035,22.564c46.171,0,67.49-49.035,80.324-118.445c6.083-32.877,20.018-58.104,36.034-71.658
|
||||
c15.742-13.319,23.008-26.64,23.008-52.07C451.577,249.847,443.574,230.354,423.943,199.054z"/>
|
||||
<path fill="#D9AF82" d="M325.395,252.416l-13.297,4.328c0,0-65.85-96.356-46.493-121.312c12.682-16.357,24.609-18.136,40.046-19.238
|
||||
c13.519-0.965,21.294,16.525,27.302,24.271C350.375,162.927,325.395,252.416,325.395,252.416z"/>
|
||||
<linearGradient id="SVGID_14_" gradientUnits="userSpaceOnUse" x1="-629.0159" y1="50.6562" x2="-540.175" y2="50.6562" gradientTransform="matrix(0.676 0.6564 -0.9247 0.9523 711.8302 511.1852)">
|
||||
<stop offset="0" style="stop-color:#FFFFFF"/>
|
||||
<stop offset="0.0769" style="stop-color:#F4E9DD"/>
|
||||
<stop offset="0.1814" style="stop-color:#EBD6BF"/>
|
||||
@@ -242,10 +242,10 @@
|
||||
<stop offset="0.7265" style="stop-color:#DAB084"/>
|
||||
<stop offset="1" style="stop-color:#D9AF82"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_14_)" d="M305.253,199.27c-26.745,27.542-70.168,41.961-81.283,24.357
|
||||
c-14.513-22.972-12.896-47.545,13.854-75.082c26.74-27.547,64.922-33.847,85.28-14.081
|
||||
<path fill="url(#SVGID_14_)" d="M305.253,199.27c-26.745,27.542-70.168,41.961-81.281,24.357
|
||||
c-14.515-22.972-12.896-47.545,13.854-75.082c26.74-27.547,64.922-33.847,85.28-14.081
|
||||
C343.464,154.233,332.003,171.726,305.253,199.27z"/>
|
||||
<linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="241.0796" y1="401.8057" x2="241.0796" y2="318.2148">
|
||||
<linearGradient id="SVGID_15_" gradientUnits="userSpaceOnUse" x1="-617.7107" y1="401.4551" x2="-617.7107" y2="317.8633" gradientTransform="matrix(1 0 0 1 858.79 0.3506)">
|
||||
<stop offset="0" style="stop-color:#D9AF82"/>
|
||||
<stop offset="0.1127" style="stop-color:#BD936E"/>
|
||||
<stop offset="0.2679" style="stop-color:#A57C5E"/>
|
||||
@@ -253,27 +253,29 @@
|
||||
<stop offset="0.6554" style="stop-color:#8D664D"/>
|
||||
<stop offset="1" style="stop-color:#8A644B"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_15_)" d="M272.246,361.529c0,46.274-35.419,42.799-45.106,36.896c0-45.751-17.227-80.21-17.227-80.21
|
||||
S249.882,354.221,272.246,361.529z"/>
|
||||
<linearGradient id="SVGID_16_" gradientUnits="userSpaceOnUse" x1="175.4648" y1="345.0176" x2="128.5757" y2="362.0838" gradientTransform="matrix(-1 0 0 1 538.9277 0)">
|
||||
<path fill="url(#SVGID_15_)" d="M272.246,361.529c0,46.272-35.419,42.799-45.104,36.896c0-45.752-17.229-80.211-17.229-80.211
|
||||
S249.882,354.22,272.246,361.529z"/>
|
||||
<linearGradient id="SVGID_16_" gradientUnits="userSpaceOnUse" x1="-925.8547" y1="344.666" x2="-972.7458" y2="361.7328" gradientTransform="matrix(-1 0 0 1 -562.3931 0.3506)">
|
||||
<stop offset="0" style="stop-color:#382815"/>
|
||||
<stop offset="0.4081" style="stop-color:#553E2B"/>
|
||||
<stop offset="1" style="stop-color:#8B654B"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_16_)" d="M359.338,356.35c0,46.27,21.504,44.032,31.073,44.032c7.488-45.135,35.671-81.515,35.671-81.515
|
||||
S381.703,349.045,359.338,356.35z"/>
|
||||
<path fill="url(#SVGID_16_)" d="M359.338,356.349c0,46.271,21.506,44.033,31.073,44.033c7.488-45.135,35.671-81.516,35.671-81.516
|
||||
S381.703,349.044,359.338,356.349z"/>
|
||||
<path fill="none" stroke="#010101" stroke-width="4.8437" d="M173.934,294.978"/>
|
||||
<g>
|
||||
<path fill="#010101" d="M311.507,115.089c53.106,0,83.247,20.214,107.503,65.948c0.904,1.702,0.904,4.883,0.904,7.96
|
||||
c-0.005,4.146-0.005,8.432,2.029,11.419c16.157,23.757,31.933,48.809,31.933,70.969c0,32.381-12.818,62.458-37.074,86.969
|
||||
l-0.541,0.549l-0.128,0.748c-12.222,71.899-36.672,150.453-103.765,150.453v1.517c70.499,0,95.847-76.845,108.416-150.456
|
||||
c24.801-25.335,37.935-56.354,37.935-89.78c0-23.537-16.19-49.311-32.774-73.694c-1.153-1.698-1.192-5.061-1.192-8.37
|
||||
c0-0.109,0.004-0.537,0.004-0.646c0-3.567-0.041-7.221-1.469-9.91c-25.237-47.585-56.579-66.125-111.78-66.125V115.089z"/>
|
||||
<path fill="#010101" d="M311.507,115.089c53.106,0,83.247,20.214,107.505,65.948c0.902,1.702,0.902,4.883,0.902,7.96
|
||||
c-0.005,4.146-0.005,8.432,2.029,11.419c16.157,23.757,31.934,48.809,31.934,70.969c0,32.38-12.817,62.458-37.073,86.969
|
||||
l-0.541,0.551l-0.13,0.748c-12.222,71.897-36.672,150.451-103.765,150.451v1.518c70.499,0,95.847-76.844,108.416-150.455
|
||||
c24.803-25.336,37.937-56.355,37.937-89.781c0-23.537-16.19-49.311-32.774-73.694c-1.151-1.698-1.19-5.061-1.19-8.37
|
||||
c0-0.109,0.004-0.537,0.004-0.646c0-3.567-0.041-7.221-1.471-9.91C398.053,131.18,366.71,112.64,311.51,112.64v2.449H311.507
|
||||
L311.507,115.089z"/>
|
||||
</g>
|
||||
<polygon fill="#010101" points="339.974,84.79 334.59,115.675 300.608,113.719 312.435,66.413 "/>
|
||||
<circle fill="#010101" stroke="#010101" stroke-width="4.8437" cx="452.06" cy="492.948" r="19.204"/>
|
||||
<g>
|
||||
<linearGradient id="SVGID_17_" gradientUnits="userSpaceOnUse" x1="109.1782" y1="336.3027" x2="170.7935" y2="336.3027">
|
||||
|
||||
<linearGradient id="SVGID_17_" gradientUnits="userSpaceOnUse" x1="-749.6116" y1="335.9512" x2="-687.9983" y2="335.9512" gradientTransform="matrix(1 0 0 1 858.79 0.3506)">
|
||||
<stop offset="0" style="stop-color:#571A54"/>
|
||||
<stop offset="0.2641" style="stop-color:#7C5378"/>
|
||||
<stop offset="0.528" style="stop-color:#A78AA3"/>
|
||||
@@ -281,10 +283,10 @@
|
||||
<stop offset="0.9095" style="stop-color:#EAE1E8"/>
|
||||
<stop offset="1" style="stop-color:#F9F3F8"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#SVGID_17_)" d="M109.178,338.034c9.592-7.823,34.696,4.862,34.833,4.862l26.782-8.396
|
||||
C170.211,334.501,120.246,321.648,109.178,338.034z"/>
|
||||
<path fill="url(#SVGID_17_)" d="M109.178,338.035c9.592-7.824,34.694,4.861,34.833,4.861l26.78-8.396
|
||||
C170.211,334.501,120.246,321.648,109.178,338.035z"/>
|
||||
</g>
|
||||
<linearGradient id="SVGID_18_" gradientUnits="userSpaceOnUse" x1="-102.0645" y1="221.0444" x2="-84.4219" y2="221.0444" gradientTransform="matrix(-0.0113 -0.7169 1.2476 -0.0198 36.6184 302.7065)">
|
||||
<linearGradient id="SVGID_18_" gradientUnits="userSpaceOnUse" x1="-1081.0227" y1="320.6133" x2="-1063.3801" y2="320.6133" gradientTransform="matrix(-0.0113 -0.7169 1.2476 -0.0198 -98.6661 -397.1379)">
|
||||
<stop offset="0" style="stop-color:#D9AF82"/>
|
||||
<stop offset="0.0786" style="stop-color:#DFB791"/>
|
||||
<stop offset="0.2053" style="stop-color:#E7C1A5"/>
|
||||
@@ -293,10 +295,10 @@
|
||||
<stop offset="0.6917" style="stop-color:#F4D3C7"/>
|
||||
<stop offset="1" style="stop-color:#F5D4C9"/>
|
||||
</linearGradient>
|
||||
<path opacity="0.36" fill="url(#SVGID_18_)" d="M313.352,358.852c6.074-0.1,11.045,2.653,11.102,6.149
|
||||
c0.058,3.49-4.829,6.399-10.907,6.498c-6.078,0.101-11.045-2.657-11.107-6.153C302.388,361.854,307.269,358.946,313.352,358.852z"/>
|
||||
<path fill="#483218" d="M397.109,309.378c15.699-3.759,26.445-18.402,20.099-27.063c-38.74,19.354-75.295,11.369-85.531,9.147
|
||||
<path opacity="0.36" fill="url(#SVGID_18_)" enable-background="new " d="M313.352,358.851c6.074-0.1,11.045,2.654,11.102,6.15
|
||||
c0.06,3.49-4.829,6.398-10.907,6.498c-6.076,0.1-11.045-2.658-11.105-6.154C302.388,361.853,307.269,358.947,313.352,358.851z"/>
|
||||
<path fill="#483218" d="M397.109,309.378c15.699-3.76,26.445-18.402,20.099-27.063c-38.738,19.354-75.295,11.369-85.529,9.147
|
||||
C368.014,309.492,371.117,315.595,397.109,309.378z"/>
|
||||
<path fill="#B4B4B4" d="M310.92,73.714c-38.372,0-93.118,22.758-117.549,74.944c-6.089,12.999-6.656,32.87,0.638,45.014
|
||||
c0,0,18.604-81.43,108.231-86.494"/>
|
||||
<path fill="#B4B4B4" d="M310.92,73.714c-38.372,0-93.116,22.758-117.549,74.944c-6.089,12.999-6.656,32.87,0.64,45.014
|
||||
c0,0,18.604-81.43,108.229-86.494"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
BIN
data/images/album-icon.png
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
data/images/artist-icon.png
Normal file
After Width: | Height: | Size: 91 KiB |
BIN
data/images/charts.png
Normal file
After Width: | Height: | Size: 1.0 MiB |
BIN
data/images/close.png
Normal file
After Width: | Height: | Size: 1.0 MiB |
BIN
data/images/collapse.png
Normal file
After Width: | Height: | Size: 1.0 MiB |
BIN
data/images/drop-album.png
Normal file
After Width: | Height: | Size: 1.0 MiB |
BIN
data/images/drop-all-songs.png
Normal file
After Width: | Height: | Size: 1.0 MiB |
BIN
data/images/drop-local-songs.png
Normal file
After Width: | Height: | Size: 1.0 MiB |
BIN
data/images/drop-song.png
Normal file
After Width: | Height: | Size: 1.0 MiB |
BIN
data/images/drop-top-songs.png
Normal file
After Width: | Height: | Size: 1.0 MiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 1.0 MiB |
BIN
data/images/open.png
Normal file
After Width: | Height: | Size: 1.0 MiB |
BIN
data/images/search-icon.png
Normal file
After Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 19 KiB |
@@ -91,6 +91,11 @@ var TomahawkResolver = {
|
||||
var configJson = JSON.stringify( config );
|
||||
|
||||
window.localStorage[ this.scriptPath() ] = configJson;
|
||||
|
||||
this.newConfigSaved();
|
||||
},
|
||||
newConfigSaved: function()
|
||||
{
|
||||
},
|
||||
resolve: function( qid, artist, album, title )
|
||||
{
|
||||
|
@@ -85,8 +85,15 @@
|
||||
<file>data/images/automatic-playlist.png</file>
|
||||
<file>data/images/station.png</file>
|
||||
<file>data/images/new-additions.png</file>
|
||||
<file>data/images/charts.png</file>
|
||||
<file>data/images/loved_playlist.png</file>
|
||||
<file>data/images/dashboard.png</file>
|
||||
<file>data/images/artist-icon.png</file>
|
||||
<file>data/images/album-icon.png</file>
|
||||
<file>data/images/search-icon.png</file>
|
||||
<file>data/images/track-icon-22x22.png</file>
|
||||
<file>data/images/track-icon-32x32.png</file>
|
||||
<file>data/images/track-icon-16x16.png</file>
|
||||
<file>data/stylesheets/topbar-radiobuttons.css</file>
|
||||
<file>data/icons/tomahawk-icon-16x16.png</file>
|
||||
<file>data/icons/tomahawk-icon-32x32.png</file>
|
||||
@@ -94,9 +101,6 @@
|
||||
<file>data/icons/tomahawk-icon-128x128.png</file>
|
||||
<file>data/icons/tomahawk-icon-256x256.png</file>
|
||||
<file>data/icons/tomahawk-icon-512x512.png</file>
|
||||
<file>data/icons/audio-x-generic-22x22.png</file>
|
||||
<file>data/icons/audio-x-generic-32x32.png</file>
|
||||
<file>data/icons/audio-x-generic-16x16.png</file>
|
||||
<file>data/www/auth.html</file>
|
||||
<file>data/www/auth.na.html</file>
|
||||
<file>data/www/tomahawk_banner_small.png</file>
|
||||
@@ -106,5 +110,10 @@
|
||||
<file>data/sql/dbmigrate-25_to_26.sql</file>
|
||||
<file>data/js/tomahawk.js</file>
|
||||
<file>data/images/avatar_frame.png</file>
|
||||
<file>data/images/drop-all-songs.png</file>
|
||||
<file>data/images/drop-local-songs.png</file>
|
||||
<file>data/images/drop-top-songs.png</file>
|
||||
<file>data/images/drop-song.png</file>
|
||||
<file>data/images/drop-album.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@@ -57,11 +57,14 @@ SET( tomahawkSourcesGui ${tomahawkSourcesGui}
|
||||
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
|
||||
|
||||
transferview.cpp
|
||||
PipelineStatusView.cpp
|
||||
@@ -75,6 +78,7 @@ SET( tomahawkSourcesGui ${tomahawkSourcesGui}
|
||||
settingslistdelegate.cpp
|
||||
resolversmodel.cpp
|
||||
tomahawkwindow.cpp
|
||||
tomahawkdesktopwindow.cpp
|
||||
)
|
||||
|
||||
SET( tomahawkHeaders ${tomahawkHeaders}
|
||||
@@ -101,11 +105,14 @@ 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
|
||||
|
||||
transferview.h
|
||||
PipelineStatusView.h
|
||||
@@ -120,14 +127,14 @@ SET( tomahawkHeadersGui ${tomahawkHeadersGui}
|
||||
resolversmodel.h
|
||||
delegateconfigwrapper.h
|
||||
tomahawkwindow.h
|
||||
tomahawkdesktopwindow.h
|
||||
)
|
||||
|
||||
SET( tomahawkUI ${tomahawkUI}
|
||||
tomahawkwindow.ui
|
||||
tomahawkdesktopwindow.ui
|
||||
diagnosticsdialog.ui
|
||||
stackedsettingsdialog.ui
|
||||
proxydialog.ui
|
||||
searchbox.ui
|
||||
|
||||
audiocontrols.ui
|
||||
)
|
||||
@@ -170,13 +177,12 @@ ENDIF( UNIX )
|
||||
IF( APPLE )
|
||||
INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/thirdparty/SPMediaKeyTap )
|
||||
|
||||
SET( tomahawkHeaders ${tomahawkHeaders} mac/tomahawkapp_mac.h mac/macshortcuthandler.h )
|
||||
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)
|
||||
@@ -186,6 +192,10 @@ IF(GLOOX_FOUND)
|
||||
ENDIF(GLOOX_FOUND)
|
||||
ADD_SUBDIRECTORY( sip )
|
||||
|
||||
IF(QCA2_FOUND)
|
||||
INCLUDE_DIRECTORIES( ${QCA2_INCLUDE_DIR} )
|
||||
ENDIF(QCA2_FOUND)
|
||||
|
||||
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} )
|
||||
@@ -226,7 +236,11 @@ IF(GLOOX_FOUND)
|
||||
SET(LINK_LIBRARIES ${LINK_LIBRARIES} ${GLOOX_LIBRARIES} )
|
||||
ENDIF(GLOOX_FOUND)
|
||||
|
||||
TARGET_LINK_LIBRARIES( tomahawk
|
||||
IF(QCA2_FOUND)
|
||||
SET(LINK_LIBRARIES ${LINK_LIBRARIES} ${QCA2_LIBRARIES} )
|
||||
ENDIF(QCA2_FOUND)
|
||||
|
||||
SET( tomahawkLinkLibraries
|
||||
${LINK_LIBRARIES}
|
||||
${TOMAHAWK_LIBRARIES}
|
||||
${PHONON_LIBS}
|
||||
@@ -237,9 +251,14 @@ TARGET_LINK_LIBRARIES( tomahawk
|
||||
${QXTWEB_LIBRARIES}
|
||||
${QJSON_LIBRARIES}
|
||||
${TAGLIB_LIBRARIES}
|
||||
${CLUCENE_LIBRARIES}
|
||||
)
|
||||
|
||||
TARGET_LINK_LIBRARIES( tomahawk ${tomahawkLinkLibraries} )
|
||||
|
||||
IF( BUILD_GUI_QML )
|
||||
# sic! add_subdirectory would make it harder to reuse ${final_src}
|
||||
INCLUDE( active/CMakeLists.txt )
|
||||
ENDIF()
|
||||
|
||||
IF( APPLE )
|
||||
IF(HAVE_SPARKLE)
|
||||
|
@@ -22,7 +22,7 @@
|
||||
#include <QTreeWidget>
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "utils/animatedsplitter.h"
|
||||
#include "widgets/animatedsplitter.h"
|
||||
|
||||
class StreamConnection;
|
||||
|
||||
|
30
src/active/CMakeLists.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
|
||||
|
||||
SET( touchmahawkSources ${final_src} )
|
||||
#LIST( REMOVE_ITEM touchmahawkSources "main.cpp" )
|
||||
|
||||
SET( touchmahawkHeaders
|
||||
active/tomahawktouchwindow.h
|
||||
)
|
||||
|
||||
SET( touchmahawkSources
|
||||
${touchmahawkSources}
|
||||
active/tomahawktouchwindow.cpp
|
||||
|
||||
# active/main.cpp
|
||||
)
|
||||
|
||||
|
||||
qt4_wrap_cpp( touchmahawkMoc ${touchmahawkHeaders} )
|
||||
|
||||
SET( touchmahawkFinalSources ${touchmahawkMoc} ${touchmahawkSources} )
|
||||
SET( touchmahawkLinkLibraries
|
||||
kdeclarative
|
||||
${tomahawkLinkLibraries}
|
||||
) #${QT_QTDECLARATIVE_LIBRARY}
|
||||
|
||||
ADD_EXECUTABLE( active-tomahawk ${touchmahawkFinalSources} )
|
||||
TARGET_LINK_LIBRARIES( active-tomahawk ${touchmahawkLinkLibraries} )
|
||||
SET_TARGET_PROPERTIES( active-tomahawk PROPERTIES COMPILE_FLAGS -DTOUCHMAHAWK )
|
||||
INSTALL( TARGETS active-tomahawk DESTINATION bin )
|
||||
|
134
src/active/tomahawktouchwindow.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2011, Dominik Schmidt <domme@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "active/tomahawktouchwindow.h"
|
||||
|
||||
#include "utils/logger.h"
|
||||
#include "audio/audioengine.h"
|
||||
#include "globalactionmanager.h"
|
||||
#include "sourcesmodel.h"
|
||||
#include "items/sourcetreeitem.h"
|
||||
#include "items/collectionitem.h"
|
||||
#include "viewmanager.h"
|
||||
|
||||
|
||||
#include "libtomahawk/playlist/treeproxymodel.h"
|
||||
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QtDeclarative>
|
||||
|
||||
#define QMLGUI "/home/domme/dev/sources/tomahawk-qml"
|
||||
|
||||
TomahawkTouchWindow::TomahawkTouchWindow()
|
||||
: m_view(0)
|
||||
, m_currentPlaylistTreeModel(0)
|
||||
{
|
||||
QFileSystemWatcher* watcher = new QFileSystemWatcher;
|
||||
watcher->addPath( QMLGUI );
|
||||
|
||||
connect( watcher, SIGNAL( directoryChanged( QString ) ), SLOT( loadQml() ));
|
||||
loadQml();
|
||||
|
||||
setCentralWidget( m_view );
|
||||
setWindowTitle("Touch-ma-hawk");
|
||||
}
|
||||
|
||||
|
||||
TomahawkTouchWindow::~TomahawkTouchWindow()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void TomahawkTouchWindow::play(const QModelIndex& index )
|
||||
{
|
||||
TreeModelItem* item = m_currentPlaylistTreeModel->sourceModel()->itemFromIndex( m_currentPlaylistTreeModel->mapToSource( index ) );
|
||||
if ( item )
|
||||
{
|
||||
m_currentPlaylistTreeModel->sourceModel()->setCurrentItem( item->index );
|
||||
AudioEngine::instance()->playItem( m_currentPlaylistTreeModel, item->result() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TomahawkTouchWindow::activateItem(const QModelIndex& index)
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << index;
|
||||
SourceTreeItem* item = qobject_cast< SourceTreeItem* >( s_sourcesModel->data( index, SourcesModel::SourceTreeItemRole ).value< SourceTreeItem* >() );
|
||||
item->activate();
|
||||
|
||||
CollectionItem* collectionItem = qobject_cast< CollectionItem* >( item );
|
||||
if( collectionItem )
|
||||
{
|
||||
tLog() << "Activate collectionItem!";
|
||||
Tomahawk::collection_ptr collection = collectionItem->source()->collection();
|
||||
|
||||
TreeModel* model = ViewManager::instance()->treeModelForCollection( collection );
|
||||
TreeProxyModel* proxyModel = m_modelProxyModels.value( model );
|
||||
if( !proxyModel )
|
||||
{
|
||||
proxyModel = new TreeProxyModel();
|
||||
//m_currentPlaylistTreeModel->setDynamicSortFilter( true );
|
||||
proxyModel->setSourceTreeModel( model );
|
||||
proxyModel->sort(TreeModel::Name, Qt::AscendingOrder );
|
||||
//m_currentPlaylistTreeModel->setShowModes( false );
|
||||
//m_currentPlaylistTreeModel->setSortRole( );
|
||||
}
|
||||
|
||||
m_currentPlaylistTreeModel = proxyModel;
|
||||
emit currentTreeModelChanged();
|
||||
//m_view->rootContext()->setContextProperty( "currentPlaylistTreeModel", m_currentPlaylistTreeModel );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
TomahawkTouchWindow::loadQml()
|
||||
{
|
||||
tLog() << Q_FUNC_INFO;
|
||||
qmlRegisterType<AudioEngine>("org.tomahawkplayer.qmlcomponents", 1, 0, "AudioEngine");
|
||||
qmlRegisterType<TreeProxyModel>("org.tomahawkplayer.qmlcomponents", 1, 0, "TreeProxyModel");
|
||||
|
||||
if( !m_view )
|
||||
{
|
||||
tLog()<< Q_FUNC_INFO << "create qml view";
|
||||
m_view = new QDeclarativeView;
|
||||
m_view->setResizeMode(QDeclarativeView::SizeRootObjectToView);
|
||||
m_view->show();
|
||||
}
|
||||
|
||||
tLog()<< Q_FUNC_INFO << "clear component cache";
|
||||
m_view->engine()->clearComponentCache();
|
||||
|
||||
tLog()<< Q_FUNC_INFO << "set context property";
|
||||
QDeclarativeContext* context = m_view->rootContext();
|
||||
|
||||
tLog()<< Q_FUNC_INFO << "make objects accessible from qml";
|
||||
context->setContextProperty( "touchWindow", this );
|
||||
context->setContextProperty( "audioEngine", AudioEngine::instance() );
|
||||
context->setContextProperty( "globalActionManager", GlobalActionManager::instance() );
|
||||
context->setContextProperty( "sourcesModel", s_sourcesModel );
|
||||
|
||||
// don't start in an undefined state
|
||||
m_currentPlaylistTreeModel = 0;
|
||||
//context->setContextProperty( "currentPlaylistTreeModel", m_currentPlaylistTreeModel );
|
||||
|
||||
tLog()<< Q_FUNC_INFO << "set source";
|
||||
m_view->setSource( QUrl::fromLocalFile( QMLGUI "/main.qml" ) );
|
||||
}
|
62
src/active/tomahawktouchwindow.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2011, Dominik Schmidt <domme@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TOMAHAWKTOUCHWINDOW_H
|
||||
#define TOMAHAWKTOUCHWINDOW_H
|
||||
|
||||
#include "tomahawkwindow.h"
|
||||
|
||||
#include <QtDeclarative>
|
||||
|
||||
class TomahawkTouchWindow;
|
||||
class QFileSystemWatcher;
|
||||
class TreeModel;
|
||||
class TreeProxyModel;
|
||||
|
||||
class TomahawkTouchWindow : public TomahawkWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY( TreeProxyModel* currentTreeModel READ currentTreeModel NOTIFY currentTreeModelChanged )
|
||||
|
||||
public:
|
||||
TomahawkTouchWindow();
|
||||
~TomahawkTouchWindow();
|
||||
|
||||
|
||||
Q_INVOKABLE void play( const QModelIndex& index );
|
||||
Q_INVOKABLE void activateItem( const QModelIndex& index );
|
||||
|
||||
signals:
|
||||
void currentTreeModelChanged();
|
||||
|
||||
private slots:
|
||||
void loadQml();
|
||||
|
||||
private:
|
||||
TreeProxyModel* currentTreeModel() { return m_currentPlaylistTreeModel; }
|
||||
|
||||
|
||||
QDeclarativeView* m_view;
|
||||
QFileSystemWatcher* m_watcher;
|
||||
|
||||
TreeProxyModel* m_currentPlaylistTreeModel;
|
||||
QHash< TreeModel*, TreeProxyModel* > m_modelProxyModels;
|
||||
};
|
||||
|
||||
#endif // TOMAHAWKTOUCHWINDOW_H
|
||||
|
@@ -24,17 +24,16 @@
|
||||
#include <QMouseEvent>
|
||||
|
||||
#include "audio/audioengine.h"
|
||||
#include "viewmanager.h"
|
||||
#include "playlist/playlistview.h"
|
||||
#include "database/database.h"
|
||||
#include "database/databasecommand_socialaction.h"
|
||||
|
||||
#include "album.h"
|
||||
|
||||
#include "utils/imagebutton.h"
|
||||
#include "widgets/imagebutton.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "utils/logger.h"
|
||||
#include <globalactionmanager.h>
|
||||
#include "album.h"
|
||||
#include "dropjob.h"
|
||||
#include "globalactionmanager.h"
|
||||
#include "viewmanager.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
@@ -90,56 +89,14 @@ AudioControls::AudioControls( QWidget* parent )
|
||||
ui->ownerLabel->setForegroundRole( QPalette::Dark );
|
||||
ui->metaDataArea->setStyleSheet( "QWidget#metaDataArea {\nborder-width: 4px;\nborder-image: url(" RESPATH "images/now-playing-panel.png) 4 4 4 4 stretch stretch; }" );
|
||||
|
||||
ui->seekSlider->setFixedHeight( 20 );
|
||||
ui->seekSlider->setEnabled( true );
|
||||
ui->seekSlider->setStyleSheet( "QSlider::groove::horizontal {"
|
||||
"margin: 5px; border-width: 3px;"
|
||||
"border-image: url(" RESPATH "images/seek-slider-bkg.png) 3 3 3 3 stretch stretch;"
|
||||
"}"
|
||||
|
||||
"QSlider::sub-page:horizontal {"
|
||||
"margin: 5px; border-width: 3px;"
|
||||
"border-image: url(" RESPATH "images/seek-slider-level.png) 3 3 3 3 stretch stretch;"
|
||||
"}"
|
||||
|
||||
"QSlider::handle::horizontal {"
|
||||
"margin-bottom: -7px; margin-top: -7px;"
|
||||
"margin-left: -4px; margin-right: -4px;"
|
||||
"height: 17px; width: 16px;"
|
||||
"background-image: url(" RESPATH "images/seek-and-volume-knob-rest.png);"
|
||||
"background-repeat: no-repeat;"
|
||||
"}" );
|
||||
|
||||
ui->volumeSlider->setFixedHeight( 20 );
|
||||
ui->volumeSlider->setRange( 0, 100 );
|
||||
ui->volumeSlider->setValue( AudioEngine::instance()->volume() );
|
||||
ui->volumeSlider->setStyleSheet( "QSlider::groove::horizontal {"
|
||||
"margin: 5px; border-width: 3px;"
|
||||
"border-image: url(" RESPATH "images/volume-slider-bkg.png) 3 3 3 3 stretch stretch;"
|
||||
"}"
|
||||
|
||||
"QSlider::sub-page:horizontal {"
|
||||
"margin: 5px; border-width: 3px;"
|
||||
"border-image: url(" RESPATH "images/seek-slider-level.png) 3 3 3 3 stretch stretch;"
|
||||
"}"
|
||||
m_sliderTimeLine.setCurveShape( QTimeLine::LinearCurve );
|
||||
ui->seekSlider->setTimeLine( &m_sliderTimeLine );
|
||||
|
||||
"QSlider::handle::horizontal {"
|
||||
"margin-bottom: -7px; margin-top: -7px;"
|
||||
"margin-left: -4px; margin-right: -4px;"
|
||||
"height: 17px; width: 16px;"
|
||||
"background-image: url(" RESPATH "images/seek-and-volume-knob-rest.png);"
|
||||
"background-repeat: no-repeat;"
|
||||
"}" );
|
||||
|
||||
/* m_playAction = new QAction( this );
|
||||
m_pauseAction = new QAction( this );
|
||||
m_prevAction = new QAction( this );
|
||||
m_nextAction = new QAction( this );
|
||||
|
||||
connect( m_playAction, SIGNAL( triggered() ), (QObject*)APP->audioEngine(), SLOT( play() ) );
|
||||
connect( m_pauseAction, SIGNAL( triggered() ), (QObject*)APP->audioEngine(), SLOT( pause() ) );
|
||||
connect( m_prevAction, SIGNAL( triggered() ), (QObject*)APP->audioEngine(), SLOT( previous() ) );
|
||||
connect( m_nextAction, SIGNAL( triggered() ), (QObject*)APP->audioEngine(), SLOT( next() ) ); */
|
||||
connect( &m_sliderTimeLine, SIGNAL( frameChanged( int ) ), ui->seekSlider, SLOT( setValue( int ) ) );
|
||||
|
||||
connect( ui->seekSlider, SIGNAL( valueChanged( int ) ), AudioEngine::instance(), SLOT( seek( int ) ) );
|
||||
connect( ui->volumeSlider, SIGNAL( valueChanged( int ) ), AudioEngine::instance(), SLOT( setVolume( int ) ) );
|
||||
@@ -167,6 +124,7 @@ AudioControls::AudioControls( QWidget* parent )
|
||||
connect( AudioEngine::instance(), SIGNAL( paused() ), SLOT( onPlaybackPaused() ) );
|
||||
connect( AudioEngine::instance(), SIGNAL( resumed() ), SLOT( onPlaybackResumed() ) );
|
||||
connect( AudioEngine::instance(), SIGNAL( stopped() ), SLOT( onPlaybackStopped() ) );
|
||||
connect( AudioEngine::instance(), SIGNAL( seeked( qint64 ) ), SLOT( onPlaybackSeeked( qint64 ) ) );
|
||||
connect( AudioEngine::instance(), SIGNAL( timerMilliSeconds( qint64 ) ), SLOT( onPlaybackTimer( qint64 ) ) );
|
||||
connect( AudioEngine::instance(), SIGNAL( volumeChanged( int ) ), SLOT( onVolumeChanged( int ) ) );
|
||||
|
||||
@@ -179,7 +137,6 @@ AudioControls::AudioControls( QWidget* parent )
|
||||
|
||||
connect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ), SLOT( infoSystemFinished( QString ) ) );
|
||||
|
||||
|
||||
ui->buttonAreaLayout->setSpacing( 0 );
|
||||
ui->stackedLayout->setSpacing( 0 );
|
||||
ui->stackedLayout->setContentsMargins( 0, 0, 0, 0 );
|
||||
@@ -228,7 +185,27 @@ AudioControls::onPlaybackStarted( const Tomahawk::result_ptr& result )
|
||||
{
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO;
|
||||
|
||||
onPlaybackLoading( result );
|
||||
if ( result.isNull() )
|
||||
return;
|
||||
|
||||
if ( m_currentTrack.isNull() || ( !m_currentTrack.isNull() && m_currentTrack.data()->id() != result.data()->id() ) )
|
||||
onPlaybackLoading( result );
|
||||
|
||||
qint64 duration = AudioEngine::instance()->currentTrackTotalTime();
|
||||
|
||||
if ( duration == -1 )
|
||||
duration = result.data()->duration() * 1000;
|
||||
|
||||
ui->seekSlider->setRange( 0, duration );
|
||||
ui->seekSlider->setValue( 0 );
|
||||
|
||||
m_sliderTimeLine.stop();
|
||||
m_sliderTimeLine.setDuration( duration );
|
||||
m_sliderTimeLine.setFrameRange( 0, duration );
|
||||
m_sliderTimeLine.setCurrentTime( 0 );
|
||||
m_seekMsecs = -1;
|
||||
|
||||
ui->seekSlider->setVisible( true );
|
||||
|
||||
Tomahawk::InfoSystem::InfoCriteriaHash trackInfo;
|
||||
trackInfo["artist"] = result->artist()->name();
|
||||
@@ -299,14 +276,7 @@ AudioControls::onPlaybackLoading( const Tomahawk::result_ptr& result )
|
||||
ui->coverImage->setPixmap( m_defaultCover );
|
||||
|
||||
ui->timeLabel->setText( TomahawkUtils::timeToString( 0 ) );
|
||||
ui->timeLeftLabel->setText( "-" + TomahawkUtils::timeToString( result->duration() ) );
|
||||
|
||||
ui->seekSlider->setRange( 0, m_currentTrack->duration() * 1000 );
|
||||
ui->seekSlider->setValue( 0 );
|
||||
ui->seekSlider->setVisible( true );
|
||||
|
||||
/* m_playAction->setEnabled( false );
|
||||
m_pauseAction->setEnabled( true ); */
|
||||
ui->timeLeftLabel->setText( "-" + TomahawkUtils::timeToString( result.data()->duration() ) );
|
||||
|
||||
ui->stackedLayout->setCurrentWidget( ui->pauseButton );
|
||||
|
||||
@@ -343,26 +313,35 @@ AudioControls::socialActionsLoaded()
|
||||
void
|
||||
AudioControls::onPlaybackPaused()
|
||||
{
|
||||
/* m_pauseAction->setEnabled( false );
|
||||
m_playAction->setEnabled( true ); */
|
||||
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO;
|
||||
ui->stackedLayout->setCurrentWidget( ui->playPauseButton );
|
||||
m_sliderTimeLine.setPaused( true );
|
||||
}
|
||||
|
||||
void
|
||||
AudioControls::onPlaybackResumed()
|
||||
{
|
||||
/* m_playAction->setEnabled( false );
|
||||
m_pauseAction->setEnabled( true ); */
|
||||
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO;
|
||||
ui->stackedLayout->setCurrentWidget( ui->pauseButton );
|
||||
ui->loveButton->setVisible( true );
|
||||
m_sliderTimeLine.resume();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioControls::onPlaybackSeeked( qint64 msec )
|
||||
{
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << " setting current timer to " << msec;
|
||||
m_sliderTimeLine.setPaused( true );
|
||||
m_sliderTimeLine.setCurrentTime( msec );
|
||||
m_seekMsecs = msec;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioControls::onPlaybackStopped()
|
||||
{
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO;
|
||||
m_currentTrack.clear();
|
||||
|
||||
ui->artistTrackLabel->setText( "" );
|
||||
@@ -372,19 +351,19 @@ AudioControls::onPlaybackStopped()
|
||||
ui->timeLeftLabel->setText( "" );
|
||||
ui->coverImage->setPixmap( QPixmap() );
|
||||
ui->seekSlider->setVisible( false );
|
||||
m_sliderTimeLine.stop();
|
||||
m_sliderTimeLine.setCurrentTime( 0 );
|
||||
|
||||
ui->stackedLayout->setCurrentWidget( ui->playPauseButton );
|
||||
ui->loveButton->setEnabled( false );
|
||||
ui->loveButton->setVisible( false );
|
||||
|
||||
/* m_pauseAction->setEnabled( false );
|
||||
m_playAction->setEnabled( true ); */
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioControls::onPlaybackTimer( qint64 msElapsed )
|
||||
{
|
||||
//tDebug( LOGEXTRA ) << Q_FUNC_INFO << " msElapsed = " << msElapsed << " and timer current time = " << m_sliderTimeLine.currentTime() << " and m_seekMsecs = " << m_seekMsecs;
|
||||
if ( m_currentTrack.isNull() )
|
||||
return;
|
||||
|
||||
@@ -393,7 +372,25 @@ AudioControls::onPlaybackTimer( qint64 msElapsed )
|
||||
const int seconds = msElapsed / 1000;
|
||||
ui->timeLabel->setText( TomahawkUtils::timeToString( seconds ) );
|
||||
ui->timeLeftLabel->setText( "-" + TomahawkUtils::timeToString( m_currentTrack->duration() - seconds ) );
|
||||
ui->seekSlider->setValue( msElapsed );
|
||||
|
||||
if ( m_sliderTimeLine.currentTime() > msElapsed || m_seekMsecs != -1 )
|
||||
{
|
||||
m_sliderTimeLine.setPaused( true );
|
||||
m_sliderTimeLine.setCurrentTime( msElapsed );
|
||||
m_seekMsecs = -1;
|
||||
if ( AudioEngine::instance()->state() != AudioEngine::Paused )
|
||||
m_sliderTimeLine.resume();
|
||||
}
|
||||
else if ( m_sliderTimeLine.duration() > msElapsed && m_sliderTimeLine.state() == QTimeLine::NotRunning )
|
||||
{
|
||||
ui->seekSlider->setEnabled( AudioEngine::instance()->canSeek() );
|
||||
m_sliderTimeLine.resume();
|
||||
}
|
||||
else if ( m_sliderTimeLine.state() == QTimeLine::Paused && AudioEngine::instance()->state() != AudioEngine::Paused )
|
||||
{
|
||||
ui->seekSlider->setEnabled( AudioEngine::instance()->canSeek() );
|
||||
m_sliderTimeLine.resume();
|
||||
}
|
||||
|
||||
ui->seekSlider->blockSignals( false );
|
||||
}
|
||||
@@ -521,7 +518,7 @@ AudioControls::onTrackClicked()
|
||||
void
|
||||
AudioControls::dragEnterEvent( QDragEnterEvent* e )
|
||||
{
|
||||
if ( GlobalActionManager::instance()->acceptsMimeData( e->mimeData() ) )
|
||||
if ( DropJob::acceptsMimeData( e->mimeData() ) )
|
||||
e->acceptProposedAction();
|
||||
}
|
||||
|
||||
@@ -538,10 +535,11 @@ void
|
||||
AudioControls::dropEvent( QDropEvent* e )
|
||||
{
|
||||
tDebug() << "AudioControls got drop:" << e->mimeData()->formats();
|
||||
if ( GlobalActionManager::instance()->acceptsMimeData( e->mimeData() ) )
|
||||
if ( DropJob::acceptsMimeData( e->mimeData() ) )
|
||||
{
|
||||
connect( GlobalActionManager::instance(), SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( droppedTracks( QList<Tomahawk::query_ptr> ) ) );
|
||||
GlobalActionManager::instance()->tracksFromMimeData( e->mimeData() );
|
||||
DropJob *dj = new DropJob();
|
||||
connect( dj, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( droppedTracks( QList<Tomahawk::query_ptr> ) ) );
|
||||
dj->tracksFromMimeData( e->mimeData() );
|
||||
|
||||
e->accept();
|
||||
}
|
||||
@@ -551,8 +549,6 @@ AudioControls::dropEvent( QDropEvent* e )
|
||||
void
|
||||
AudioControls::droppedTracks( QList< query_ptr > tracks )
|
||||
{
|
||||
disconnect( GlobalActionManager::instance(), SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( droppedTracks( QList<Tomahawk::query_ptr> ) ) );
|
||||
|
||||
if ( !tracks.isEmpty() )
|
||||
{
|
||||
// queue and play the first if nothign is playing
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#define AUDIOCONTROLS_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QTimeLine>
|
||||
|
||||
#include "result.h"
|
||||
#include "playlistinterface.h"
|
||||
@@ -60,6 +61,7 @@ private slots:
|
||||
void onPlaybackLoading( const Tomahawk::result_ptr& result );
|
||||
void onPlaybackPaused();
|
||||
void onPlaybackResumed();
|
||||
void onPlaybackSeeked( qint64 msec );
|
||||
void onPlaybackStopped();
|
||||
|
||||
void onPlaybackTimer( qint64 msElapsed );
|
||||
@@ -79,19 +81,18 @@ private slots:
|
||||
void droppedTracks( QList<Tomahawk::query_ptr> );
|
||||
|
||||
void socialActionsLoaded();
|
||||
|
||||
private:
|
||||
Ui::AudioControls *ui;
|
||||
|
||||
QAction* m_playAction;
|
||||
QAction* m_pauseAction;
|
||||
QAction* m_prevAction;
|
||||
QAction* m_nextAction;
|
||||
|
||||
QPixmap m_defaultCover;
|
||||
|
||||
Tomahawk::result_ptr m_currentTrack;
|
||||
Tomahawk::PlaylistInterface::RepeatMode m_repeatMode;
|
||||
bool m_shuffled;
|
||||
|
||||
QTimeLine m_sliderTimeLine;
|
||||
qint64 m_seekMsecs;
|
||||
};
|
||||
|
||||
#endif // AUDIOCONTROLS_H
|
||||
|
@@ -337,7 +337,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="seekSlider">
|
||||
<widget class="SeekSlider" name="seekSlider">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
@@ -489,7 +489,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="volumeSlider">
|
||||
<widget class="SeekSlider" name="volumeSlider">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
@@ -529,15 +529,20 @@
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>SeekSlider</class>
|
||||
<extends>QSlider</extends>
|
||||
<header location="global">widgets/SeekSlider.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ImageButton</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>utils/imagebutton.h</header>
|
||||
<header>widgets/imagebutton.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>QueryLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>utils/querylabel.h</header>
|
||||
<header>widgets/querylabel.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
|
@@ -17,5 +17,6 @@
|
||||
|
||||
#cmakedefine LIBLASTFM_FOUND
|
||||
#cmakedefine GLOOX_FOUND
|
||||
#cmakedefine QCA2_FOUND
|
||||
|
||||
#endif // CONFIG_H_IN
|
||||
|
@@ -31,6 +31,7 @@ set( libSources
|
||||
viewmanager.cpp
|
||||
globalactionmanager.cpp
|
||||
contextmenu.cpp
|
||||
dropjob.cpp
|
||||
|
||||
sip/SipPlugin.cpp
|
||||
sip/SipHandler.cpp
|
||||
@@ -39,6 +40,13 @@ set( libSources
|
||||
|
||||
audio/audioengine.cpp
|
||||
|
||||
context/ContextPage.cpp
|
||||
context/ContextWidget.cpp
|
||||
context/pages/TopTracksContext.cpp
|
||||
context/pages/RelatedArtistsContext.cpp
|
||||
context/pages/WikipediaContext.cpp
|
||||
context/pages/WebContext.cpp
|
||||
|
||||
database/database.cpp
|
||||
database/fuzzyindex.cpp
|
||||
database/databasecollection.cpp
|
||||
@@ -66,6 +74,7 @@ set( libSources
|
||||
database/databasecommand_playbackhistory.cpp
|
||||
database/databasecommand_setplaylistrevision.cpp
|
||||
database/databasecommand_loadallplaylists.cpp
|
||||
database/databasecommand_loadallsortedplaylists.cpp
|
||||
database/databasecommand_loadallsources.cpp
|
||||
database/databasecommand_createplaylist.cpp
|
||||
database/databasecommand_deleteplaylist.cpp
|
||||
@@ -86,6 +95,8 @@ set( libSources
|
||||
database/databasecommand_genericselect.cpp
|
||||
database/database.cpp
|
||||
|
||||
infobar/infobar.cpp
|
||||
|
||||
infosystem/infosystemcache.cpp
|
||||
infosystem/infosystem.cpp
|
||||
infosystem/infosystemworker.cpp
|
||||
@@ -120,6 +131,7 @@ set( libSources
|
||||
playlist/albumview.cpp
|
||||
playlist/artistview.cpp
|
||||
playlist/customplaylistview.cpp
|
||||
playlist/ViewHeader.cpp
|
||||
|
||||
playlist/topbar/topbar.cpp
|
||||
playlist/topbar/clearbutton.cpp
|
||||
@@ -127,8 +139,6 @@ set( libSources
|
||||
playlist/topbar/lineedit.cpp
|
||||
playlist/topbar/searchbutton.cpp
|
||||
|
||||
playlist/infobar/infobar.cpp
|
||||
|
||||
playlist/dynamic/DynamicPlaylist.cpp
|
||||
playlist/dynamic/DynamicControl.cpp
|
||||
playlist/dynamic/GeneratorFactory.cpp
|
||||
@@ -160,36 +170,47 @@ set( libSources
|
||||
network/controlconnection.cpp
|
||||
|
||||
utils/tomahawkutils.cpp
|
||||
utils/querylabel.cpp
|
||||
utils/elidedlabel.cpp
|
||||
utils/imagebutton.cpp
|
||||
utils/logger.cpp
|
||||
utils/proxystyle.cpp
|
||||
utils/widgetdragfilter.cpp
|
||||
utils/animatedsplitter.cpp
|
||||
utils/xspfloader.cpp
|
||||
utils/xspfgenerator.cpp
|
||||
utils/jspfloader.cpp
|
||||
utils/spotifyparser.cpp
|
||||
utils/rdioparser.cpp
|
||||
utils/shortenedlinkparser.cpp
|
||||
utils/stylehelper.cpp
|
||||
|
||||
widgets/querylabel.cpp
|
||||
widgets/imagebutton.cpp
|
||||
widgets/animatedsplitter.cpp
|
||||
widgets/elidedlabel.cpp
|
||||
widgets/newplaylistwidget.cpp
|
||||
widgets/searchwidget.cpp
|
||||
widgets/SeekSlider.cpp
|
||||
widgets/playlisttypeselectordlg.cpp
|
||||
widgets/welcomewidget.cpp
|
||||
widgets/welcomeplaylistmodel.cpp
|
||||
widgets/whatshotwidget.cpp
|
||||
widgets/RecentlyPlayedPlaylistsModel.cpp
|
||||
widgets/RecentPlaylistsModel.cpp
|
||||
widgets/overlaywidget.cpp
|
||||
widgets/HeaderLabel.cpp
|
||||
widgets/HeaderWidget.cpp
|
||||
widgets/combobox.cpp
|
||||
widgets/SocialPlaylistWidget.cpp
|
||||
widgets/infowidgets/sourceinfowidget.cpp
|
||||
widgets/infowidgets/ArtistInfoWidget.cpp
|
||||
widgets/infowidgets/AlbumInfoWidget.cpp
|
||||
widgets/kbreadcrumbselectionmodel.cpp
|
||||
widgets/breadcrumbbar.cpp
|
||||
widgets/breadcrumbbuttonbase.cpp
|
||||
widgets/headerbreadcrumb.cpp
|
||||
widgets/siblingcrumbbutton.cpp
|
||||
|
||||
kdsingleapplicationguard/kdsingleapplicationguard.cpp
|
||||
kdsingleapplicationguard/kdsharedmemorylocker.cpp
|
||||
kdsingleapplicationguard/kdtoolsglobal.cpp
|
||||
kdsingleapplicationguard/kdlockedsharedmemorypointer.cpp
|
||||
thirdparty/kdsingleapplicationguard/kdsingleapplicationguard.cpp
|
||||
thirdparty/kdsingleapplicationguard/kdsharedmemorylocker.cpp
|
||||
thirdparty/kdsingleapplicationguard/kdtoolsglobal.cpp
|
||||
thirdparty/kdsingleapplicationguard/kdlockedsharedmemorypointer.cpp
|
||||
)
|
||||
|
||||
set( libHeaders
|
||||
@@ -208,6 +229,7 @@ set( libHeaders
|
||||
viewmanager.h
|
||||
globalactionmanager.h
|
||||
contextmenu.h
|
||||
dropjob.h
|
||||
|
||||
artist.h
|
||||
album.h
|
||||
@@ -220,6 +242,13 @@ set( libHeaders
|
||||
|
||||
audio/audioengine.h
|
||||
|
||||
context/ContextPage.h
|
||||
context/ContextWidget.h
|
||||
context/pages/TopTracksContext.h
|
||||
context/pages/RelatedArtistsContext.h
|
||||
context/pages/WikipediaContext.h
|
||||
context/pages/WebContext.h
|
||||
|
||||
database/database.h
|
||||
database/fuzzyindex.h
|
||||
database/databaseworker.h
|
||||
@@ -245,6 +274,7 @@ set( libHeaders
|
||||
database/databasecommand_playbackhistory.h
|
||||
database/databasecommand_setplaylistrevision.h
|
||||
database/databasecommand_loadallplaylists.h
|
||||
database/databasecommand_loadallsortedplaylists.h
|
||||
database/databasecommand_loadallsources.h
|
||||
database/databasecommand_createplaylist.h
|
||||
database/databasecommand_deleteplaylist.h
|
||||
@@ -266,6 +296,8 @@ set( libHeaders
|
||||
database/databasecommand_loadsocialactions.h
|
||||
database/databasecommand_genericselect.h
|
||||
|
||||
infobar/infobar.h
|
||||
|
||||
infosystem/infosystem.h
|
||||
infosystem/infosystemworker.h
|
||||
infosystem/infosystemcache.h
|
||||
@@ -310,6 +342,7 @@ set( libHeaders
|
||||
playlist/albumview.h
|
||||
playlist/artistview.h
|
||||
playlist/customplaylistview.h
|
||||
playlist/ViewHeader.h
|
||||
|
||||
playlist/topbar/topbar.h
|
||||
playlist/topbar/clearbutton.h
|
||||
@@ -318,8 +351,6 @@ set( libHeaders
|
||||
playlist/topbar/lineedit_p.h
|
||||
playlist/topbar/searchbutton.h
|
||||
|
||||
playlist/infobar/infobar.h
|
||||
|
||||
playlist/dynamic/DynamicPlaylist.h
|
||||
playlist/dynamic/DynamicControl.h
|
||||
playlist/dynamic/GeneratorInterface.h
|
||||
@@ -339,32 +370,45 @@ set( libHeaders
|
||||
playlist/dynamic/database/DatabaseControl.h
|
||||
playlist/dynamic/database/DatabaseGenerator.h
|
||||
|
||||
utils/querylabel.h
|
||||
utils/elidedlabel.h
|
||||
utils/animatedcounterlabel.h
|
||||
utils/imagebutton.h
|
||||
utils/widgetdragfilter.h
|
||||
utils/animatedsplitter.h
|
||||
utils/xspfloader.h
|
||||
utils/xspfgenerator.h
|
||||
utils/jspfloader.h
|
||||
utils/spotifyparser.h
|
||||
utils/rdioparser.h
|
||||
utils/shortenedlinkparser.h
|
||||
utils/stylehelper.h
|
||||
|
||||
widgets/querylabel.h
|
||||
widgets/animatedcounterlabel.h
|
||||
widgets/imagebutton.h
|
||||
widgets/animatedsplitter.h
|
||||
widgets/elidedlabel.h
|
||||
widgets/newplaylistwidget.h
|
||||
widgets/searchwidget.h
|
||||
widgets/SeekSlider.h
|
||||
widgets/playlisttypeselectordlg.h
|
||||
widgets/welcomewidget.h
|
||||
widgets/welcomeplaylistmodel.h
|
||||
widgets/whatshotwidget.h
|
||||
widgets/RecentlyPlayedPlaylistsModel.h
|
||||
widgets/RecentPlaylistsModel.h
|
||||
widgets/overlaywidget.h
|
||||
widgets/HeaderLabel.h
|
||||
widgets/HeaderWidget.h
|
||||
widgets/combobox.h
|
||||
widgets/SocialPlaylistWidget.h
|
||||
widgets/infowidgets/sourceinfowidget.h
|
||||
widgets/infowidgets/ArtistInfoWidget.h
|
||||
widgets/infowidgets/AlbumInfoWidget.h
|
||||
widgets/kbreadcrumbselectionmodel.h
|
||||
widgets/kbreadcrumbselectionmodel_p.h
|
||||
widgets/breadcrumbbar.h
|
||||
widgets/breadcrumbbuttonbase.h
|
||||
widgets/headerbreadcrumb.h
|
||||
widgets/siblingcrumbbutton.h
|
||||
|
||||
kdsingleapplicationguard/kdsingleapplicationguard.h
|
||||
thirdparty/kdsingleapplicationguard/kdsingleapplicationguard.h
|
||||
thirdparty/Qocoa/qsearchfield.h
|
||||
)
|
||||
|
||||
set( libHeaders_NoMOC
|
||||
@@ -383,12 +427,15 @@ set( libUI ${libUI}
|
||||
widgets/newplaylistwidget.ui
|
||||
widgets/searchwidget.ui
|
||||
widgets/welcomewidget.ui
|
||||
widgets/whatshotwidget.ui
|
||||
widgets/SocialPlaylistWidget.ui
|
||||
widgets/infowidgets/sourceinfowidget.ui
|
||||
widgets/infowidgets/ArtistInfoWidget.ui
|
||||
widgets/infowidgets/AlbumInfoWidget.ui
|
||||
playlist/topbar/topbar.ui
|
||||
playlist/infobar/infobar.ui
|
||||
playlist/queueview.ui
|
||||
context/ContextWidget.ui
|
||||
infobar/infobar.ui
|
||||
)
|
||||
|
||||
include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/.. ..
|
||||
@@ -406,16 +453,28 @@ include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/.
|
||||
|
||||
${LIBPORTFWD_INCLUDE_DIR}
|
||||
${THIRDPARTY_DIR}/qxt/qxtweb-standalone/qxtweb
|
||||
${CMAKE_BINARY_DIR}/thirdparty/liblastfm2/src
|
||||
|
||||
)
|
||||
|
||||
IF( UNIX AND NOT APPLE )
|
||||
SET( libSources ${libSources}
|
||||
infosystem/infoplugins/unix/mprispluginrootadaptor.cpp
|
||||
infosystem/infoplugins/unix/mprispluginplayeradaptor.cpp
|
||||
infosystem/infoplugins/unix/mprisplugin.cpp
|
||||
infosystem/infoplugins/unix/fdonotifyplugin.cpp
|
||||
infosystem/infoplugins/unix/imageconverter.cpp )
|
||||
|
||||
SET( libHeaders ${libHeaders}
|
||||
infosystem/infoplugins/unix/mprispluginrootadaptor.h
|
||||
infosystem/infoplugins/unix/mprispluginplayeradaptor.h
|
||||
infosystem/infoplugins/unix/mprisplugin.h
|
||||
infosystem/infoplugins/unix/fdonotifyplugin.h )
|
||||
|
||||
IF( BUILD_GUI AND X11_FOUND )
|
||||
INCLUDE_DIRECTORIES( ${THIRDPARTY_DIR}/libqnetwm )
|
||||
SET( libSources ${libSources} ${THIRDPARTY_DIR}/libqnetwm/libqnetwm/netwm.cpp )
|
||||
SET( LINK_LIBRARIES ${LINK_LIBRARIES} ${X11_LIBRARIES} )
|
||||
ENDIF()
|
||||
ENDIF( UNIX AND NOT APPLE )
|
||||
|
||||
IF( WIN32 )
|
||||
@@ -441,11 +500,10 @@ IF( APPLE )
|
||||
SET( libSources ${libSources}
|
||||
infosystem/infoplugins/mac/adium.mm
|
||||
infosystem/infoplugins/mac/adiumplugin.cpp
|
||||
widgets/maclineedit.mm
|
||||
utils/tomahawkutils_mac.mm )
|
||||
utils/tomahawkutils_mac.mm
|
||||
thirdparty/Qocoa/qsearchfield_mac.mm )
|
||||
|
||||
SET( libHeaders ${libHeaders}
|
||||
widgets/maclineedit.h
|
||||
infosystem/infoplugins/mac/adium.h
|
||||
infosystem/infoplugins/mac/adiumplugin.h )
|
||||
|
||||
@@ -459,6 +517,8 @@ IF( APPLE )
|
||||
|
||||
/System/Library/Frameworks/AppKit.framework
|
||||
)
|
||||
ELSE( APPLE )
|
||||
SET( libSources ${libSources} thirdparty/Qocoa/qsearchfield.cpp )
|
||||
ENDIF( APPLE )
|
||||
|
||||
IF(LIBLASTFM_FOUND)
|
||||
|
74
src/libtomahawk/accounts/account.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ACCOUNT_H
|
||||
#define ACCOUNT_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QVariantMap>
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "dllmacro.h"
|
||||
#include "infosystem/infosystem.h"
|
||||
#include "sip/SipPlugin.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class DLLEXPORT Account
|
||||
{
|
||||
|
||||
typedef QMap< QString, bool > ACLMap;
|
||||
|
||||
public:
|
||||
enum AccountTypes { InfoType, SipType };
|
||||
|
||||
explicit Account();
|
||||
virtual ~Account();
|
||||
|
||||
QString accountServiceName(); // e.g. "Twitter", "Last.fm"
|
||||
void setAccountServiceName( const QString &serviceName );
|
||||
|
||||
QString accountFriendlyName(); // e.g. screen name on the service, JID, etc.
|
||||
void setAccountFriendlyName( const QString &friendlyName );
|
||||
|
||||
bool autoConnect();
|
||||
void setAutoConnect( bool autoConnect );
|
||||
|
||||
QStringMap credentials();
|
||||
void setCredentials( const QStringMap &credentialMap );
|
||||
|
||||
QVariantMap configuration();
|
||||
void setConfiguration( const QVariantMap &configuration );
|
||||
QWidget* configurationWidget();
|
||||
|
||||
ACLMap acl();
|
||||
void setAcl( const ACLMap &acl );
|
||||
QWidget* aclWidget();
|
||||
|
||||
QSet< AccountTypes > types();
|
||||
void setTypes( const QSet< AccountTypes > types );
|
||||
|
||||
Tomahawk::InfoSystem::InfoPlugin* infoPlugin();
|
||||
SipPlugin* sipPlugin();
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif // ACCOUNT_H
|
@@ -74,6 +74,12 @@ AudioEngine::AudioEngine()
|
||||
connect( m_audioOutput, SIGNAL( volumeChanged( qreal ) ), this, SLOT( onVolumeChanged( qreal ) ) );
|
||||
|
||||
onVolumeChanged( m_audioOutput->volume() );
|
||||
|
||||
|
||||
connect( this, SIGNAL(started(Tomahawk::result_ptr)), SIGNAL(currentTrackChanged()));
|
||||
connect( this, SIGNAL(stopped()), SIGNAL(currentTrackChanged()));
|
||||
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
// On mac, phonon volume is independent from system volume, so the onVolumeChanged call above just sets our volume to 100%.
|
||||
// Since it's indendent, we'll set it to 75% since that's nicer
|
||||
@@ -137,7 +143,7 @@ AudioEngine::play()
|
||||
QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo ) );
|
||||
}
|
||||
else
|
||||
loadNextTrack();
|
||||
next();
|
||||
}
|
||||
|
||||
|
||||
@@ -188,55 +194,93 @@ AudioEngine::previous()
|
||||
{
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO;
|
||||
|
||||
if ( m_playlist.isNull() )
|
||||
return;
|
||||
|
||||
if ( m_playlist.data()->skipRestrictions() == PlaylistInterface::NoSkip ||
|
||||
m_playlist.data()->skipRestrictions() == PlaylistInterface::NoSkipBackwards )
|
||||
return;
|
||||
|
||||
loadPreviousTrack();
|
||||
if( canGoPrevious() )
|
||||
loadPreviousTrack();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::next()
|
||||
{
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO;
|
||||
|
||||
if( canGoNext() )
|
||||
loadNextTrack();
|
||||
}
|
||||
|
||||
bool
|
||||
AudioEngine::canGoNext()
|
||||
{
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO;
|
||||
|
||||
if ( m_queue && m_queue->trackCount() )
|
||||
return true;
|
||||
|
||||
if ( m_playlist.isNull() )
|
||||
return;
|
||||
return false;
|
||||
|
||||
if ( m_playlist.data()->skipRestrictions() == PlaylistInterface::NoSkip ||
|
||||
m_playlist.data()->skipRestrictions() == PlaylistInterface::NoSkipForwards )
|
||||
return;
|
||||
return false;
|
||||
|
||||
if ( !m_currentTrack.isNull() && !m_playlist.data()->hasNextItem() &&
|
||||
m_currentTrack->id() == m_playlist.data()->currentItem()->id() )
|
||||
( m_playlist.data()->currentItem().isNull() || ( m_currentTrack->id() == m_playlist.data()->currentItem()->id() ) ) )
|
||||
{
|
||||
//For instance, when doing a catch-up while listening along, but the person
|
||||
//you're following hasn't started a new track yet...don't do anything
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << "catch up";
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_playlist.data()->hasNextItem();
|
||||
}
|
||||
|
||||
bool
|
||||
AudioEngine::canGoPrevious()
|
||||
{
|
||||
if ( m_playlist.isNull() )
|
||||
return false;
|
||||
|
||||
if ( m_playlist.data()->skipRestrictions() == PlaylistInterface::NoSkip ||
|
||||
m_playlist.data()->skipRestrictions() == PlaylistInterface::NoSkipBackwards )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
AudioEngine::canSeek()
|
||||
{
|
||||
bool phononCanSeek = true;
|
||||
/* TODO: When phonon properly reports this, re-enable it
|
||||
if ( m_mediaObject && m_mediaObject->isValid() )
|
||||
phononCanSeek = m_mediaObject->isSeekable();
|
||||
*/
|
||||
return !m_playlist.isNull() && ( m_playlist.data()->seekRestrictions() != PlaylistInterface::NoSeek ) && phononCanSeek;
|
||||
}
|
||||
|
||||
void
|
||||
AudioEngine::seek( qint64 ms )
|
||||
{
|
||||
if( !canSeek() )
|
||||
{
|
||||
qDebug() << "Could not seek!";
|
||||
return;
|
||||
}
|
||||
|
||||
loadNextTrack();
|
||||
if( isPlaying() || isPaused() )
|
||||
{
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << ms;
|
||||
m_mediaObject->seek( ms );
|
||||
emit seeked( ms );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::seek( int ms )
|
||||
{
|
||||
if ( !m_playlist.isNull() && m_playlist.data()->seekRestrictions() == PlaylistInterface::NoSeek )
|
||||
return;
|
||||
|
||||
if ( isPlaying() || isPaused() )
|
||||
{
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << ms;
|
||||
m_mediaObject->seek( ms );
|
||||
}
|
||||
seek( (qint64) ms );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::setVolume( int percentage )
|
||||
{
|
||||
@@ -305,11 +349,16 @@ AudioEngine::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData,
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_currentTrack.isNull() ||
|
||||
m_currentTrack->track().isNull() ||
|
||||
m_currentTrack->artist().isNull() )
|
||||
return;
|
||||
|
||||
QVariantMap playInfo;
|
||||
playInfo["message"] = QString( "Tomahawk is playing \"%1\" by %2 on album %3." )
|
||||
.arg( m_currentTrack->track() )
|
||||
.arg( m_currentTrack->artist()->name() )
|
||||
.arg( m_currentTrack->album()->name() );
|
||||
playInfo["message"] = tr( "Tomahawk is playing \"%1\" by %2%3." )
|
||||
.arg( m_currentTrack->track() )
|
||||
.arg( m_currentTrack->artist()->name() )
|
||||
.arg( m_currentTrack->album().isNull() ? QString() : tr( " on album %1" ).arg( m_currentTrack->album()->name() ) );
|
||||
if ( !output.isNull() && output.isValid() )
|
||||
{
|
||||
QVariantMap returnedData = output.value< QVariantMap >();
|
||||
@@ -468,11 +517,15 @@ AudioEngine::loadNextTrack()
|
||||
|
||||
if ( !m_playlist.isNull() && result.isNull() )
|
||||
{
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << " loading playlist's next item";
|
||||
result = m_playlist.data()->nextItem();
|
||||
}
|
||||
|
||||
if ( !result.isNull() )
|
||||
{
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << " got next item, loading track";
|
||||
loadTrack( result );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !m_playlist.isNull() && m_playlist.data()->retryMode() == Tomahawk::PlaylistInterface::Retry )
|
||||
@@ -487,8 +540,6 @@ AudioEngine::playItem( Tomahawk::PlaylistInterface* playlist, const Tomahawk::re
|
||||
{
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : result->url() );
|
||||
|
||||
if ( !result->isOnline() )
|
||||
return;
|
||||
if ( !m_playlist.isNull() )
|
||||
m_playlist.data()->reset();
|
||||
|
||||
@@ -512,7 +563,7 @@ AudioEngine::playlistNextTrackReady()
|
||||
return;
|
||||
|
||||
m_waitingOnNewTrack = false;
|
||||
next();
|
||||
loadNextTrack();
|
||||
}
|
||||
|
||||
|
||||
@@ -564,7 +615,14 @@ AudioEngine::onStateChanged( Phonon::State newState, Phonon::State oldState )
|
||||
{
|
||||
m_expectStop = false;
|
||||
tDebug( LOGEXTRA ) << "Finding next track.";
|
||||
loadNextTrack();
|
||||
if ( canGoNext() )
|
||||
loadNextTrack();
|
||||
else
|
||||
{
|
||||
if ( !m_playlist.isNull() && m_playlist.data()->retryMode() == Tomahawk::PlaylistInterface::Retry )
|
||||
m_waitingOnNewTrack = true;
|
||||
stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -596,10 +654,15 @@ void
|
||||
AudioEngine::setPlaylist( PlaylistInterface* playlist )
|
||||
{
|
||||
if ( !m_playlist.isNull() )
|
||||
{
|
||||
if ( m_playlist.data()->object() && m_playlist.data()->retryMode() == PlaylistInterface::Retry )
|
||||
disconnect( m_playlist.data()->object(), SIGNAL( nextTrackReady() ) );
|
||||
m_playlist.data()->reset();
|
||||
}
|
||||
|
||||
if ( !playlist )
|
||||
return;
|
||||
|
||||
m_playlist = playlist->getSharedPointer();
|
||||
|
||||
if ( m_playlist.data()->object() && m_playlist.data()->retryMode() == PlaylistInterface::Retry )
|
||||
|
@@ -29,6 +29,8 @@
|
||||
#include "infosystem/infosystem.h"
|
||||
|
||||
#include "result.h"
|
||||
#include "album.h"
|
||||
#include "artist.h"
|
||||
#include "typedefs.h"
|
||||
|
||||
#include "dllmacro.h"
|
||||
@@ -42,7 +44,12 @@ namespace Tomahawk
|
||||
|
||||
class DLLEXPORT AudioEngine : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
Q_ENUMS( AudioState )
|
||||
Q_PROPERTY(AudioState audioState READ state NOTIFY stateChanged)
|
||||
Q_PROPERTY(QString currentArtist READ currentArtist NOTIFY currentTrackChanged)
|
||||
Q_PROPERTY(QString currentAlbum READ currentAlbum NOTIFY currentTrackChanged)
|
||||
Q_PROPERTY(QString currentTitle READ currentTitle NOTIFY currentTrackChanged)
|
||||
|
||||
public:
|
||||
enum AudioErrorCode { StreamReadError, AudioDeviceError, DecodeError };
|
||||
@@ -69,6 +76,9 @@ public:
|
||||
|
||||
Tomahawk::result_ptr currentTrack() const { return m_currentTrack; }
|
||||
|
||||
qint64 currentTime() const { return m_mediaObject->currentTime(); }
|
||||
qint64 currentTrackTotalTime() const { return m_mediaObject->totalTime(); }
|
||||
|
||||
public slots:
|
||||
void playPause();
|
||||
void play();
|
||||
@@ -78,7 +88,12 @@ public slots:
|
||||
void previous();
|
||||
void next();
|
||||
|
||||
void seek( int ms );
|
||||
bool canGoPrevious();
|
||||
bool canGoNext();
|
||||
bool canSeek();
|
||||
|
||||
void seek( qint64 ms );
|
||||
void seek( int ms ); // for compatibility with seekbar in audiocontrols
|
||||
void setVolume( int percentage );
|
||||
void lowerVolume() { setVolume( volume() - AUDIO_VOLUME_STEP ); }
|
||||
void raiseVolume() { setVolume( volume() + AUDIO_VOLUME_STEP ); }
|
||||
@@ -94,7 +109,13 @@ public slots:
|
||||
void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
|
||||
void infoSystemFinished( QString caller );
|
||||
|
||||
const QString currentArtist() const { return !m_currentTrack.isNull() ? m_currentTrack->artist()->name() : QString(); }
|
||||
const QString currentAlbum() const { return !m_currentTrack.isNull() ? currentTrack()->album()->name() : QString(); }
|
||||
const QString currentTitle() const { return !m_currentTrack.isNull() ? currentTrack()->track() : QString(); }
|
||||
|
||||
signals:
|
||||
void currentTrackChanged();
|
||||
|
||||
void loading( const Tomahawk::result_ptr& track );
|
||||
void started( const Tomahawk::result_ptr& track );
|
||||
void finished( const Tomahawk::result_ptr& track );
|
||||
@@ -102,6 +123,8 @@ signals:
|
||||
void paused();
|
||||
void resumed();
|
||||
|
||||
void seeked( qint64 ms );
|
||||
|
||||
void stateChanged( AudioState newState, AudioState oldState );
|
||||
void volumeChanged( int volume /* in percent */ );
|
||||
|
||||
|
95
src/libtomahawk/context/ContextPage.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ContextPage.h"
|
||||
|
||||
#include <QGraphicsLinearLayout>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
void
|
||||
ContextProxyPage::paint( QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget )
|
||||
{
|
||||
painter->save();
|
||||
|
||||
painter->setRenderHint( QPainter::Antialiasing, true );
|
||||
painter->setPen( StyleHelper::headerHighlightColor() );
|
||||
painter->setBrush( StyleHelper::headerHighlightColor() );
|
||||
painter->drawRoundedRect( option->rect, 4.0, 4.0 );
|
||||
|
||||
QFont f( font() );
|
||||
f.setBold( true );
|
||||
f.setPixelSize( 14 );
|
||||
painter->setFont( f );
|
||||
painter->setPen( Qt::white );
|
||||
|
||||
QRect r( 1, 1, option->rect.width(), 19 );
|
||||
QTextOption to( Qt::AlignCenter );
|
||||
painter->drawText( r, m_page->title(), to );
|
||||
|
||||
painter->restore();
|
||||
|
||||
QGraphicsWidget::paint( painter, option, widget );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ContextProxyPage::setPage( Tomahawk::ContextPage* page )
|
||||
{
|
||||
m_page = page;
|
||||
|
||||
#ifdef Q_OS_LINUX //FIXME: why do we need this? maybe it's only oxygen style misbehaving?
|
||||
QGraphicsWebView* testWebView = qobject_cast<QGraphicsWebView*>( page->widget() );
|
||||
if ( testWebView )
|
||||
{
|
||||
setContentsMargins( 4, 4, 4, 4 );
|
||||
}
|
||||
#endif
|
||||
|
||||
QGraphicsLinearLayout* layout = new QGraphicsLinearLayout();
|
||||
layout->setContentsMargins( 4, 20, 4, 4 );
|
||||
layout->addItem( page->widget() );
|
||||
setLayout( layout );
|
||||
|
||||
page->widget()->installEventFilter( this );
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ContextProxyPage::eventFilter( QObject* watched, QEvent* event )
|
||||
{
|
||||
if ( event->type() == QEvent::GrabMouse )
|
||||
{
|
||||
emit focused();
|
||||
}
|
||||
|
||||
return QGraphicsWidget::eventFilter( watched, event );
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ContextProxyPage::sceneEvent( QEvent* event )
|
||||
{
|
||||
if ( event->type() == QEvent::GrabMouse )
|
||||
{
|
||||
emit focused();
|
||||
}
|
||||
|
||||
return QGraphicsWidget::sceneEvent( event );
|
||||
}
|
91
src/libtomahawk/context/ContextPage.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CONTEXTPAGE_H
|
||||
#define CONTEXTPAGE_H
|
||||
|
||||
#include <QGraphicsProxyWidget>
|
||||
#include <QGraphicsWebView>
|
||||
#include <QStyleOptionGraphicsItem>
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "playlistinterface.h"
|
||||
#include "utils/stylehelper.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
|
||||
#include "dllmacro.h"
|
||||
#include <signal.h>
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class DLLEXPORT ContextPage : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ContextPage() {}
|
||||
virtual ~ContextPage() {}
|
||||
|
||||
virtual QGraphicsWidget* widget() = 0;
|
||||
virtual Tomahawk::PlaylistInterface* playlistInterface() const = 0;
|
||||
|
||||
virtual QString title() const = 0;
|
||||
virtual QString description() const = 0;
|
||||
virtual QPixmap pixmap() const { return QPixmap( RESPATH "icons/tomahawk-icon-128x128.png" ); }
|
||||
|
||||
virtual bool jumpToCurrentTrack() = 0;
|
||||
|
||||
public slots:
|
||||
virtual void setQuery( const Tomahawk::query_ptr& query ) = 0;
|
||||
|
||||
signals:
|
||||
void nameChanged( const QString& );
|
||||
void descriptionChanged( const QString& );
|
||||
void pixmapChanged( const QPixmap& );
|
||||
void destroyed( QWidget* widget );
|
||||
};
|
||||
|
||||
|
||||
class DLLEXPORT ContextProxyPage : public QGraphicsWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ContextProxyPage() : QGraphicsWidget()
|
||||
{}
|
||||
|
||||
Tomahawk::ContextPage* page() const { return m_page; }
|
||||
void setPage( Tomahawk::ContextPage* page );
|
||||
|
||||
virtual bool eventFilter( QObject* watched, QEvent* event );
|
||||
|
||||
signals:
|
||||
void focused();
|
||||
|
||||
protected:
|
||||
virtual void paint( QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget );
|
||||
virtual bool sceneEvent( QEvent* event );
|
||||
|
||||
private:
|
||||
Tomahawk::ContextPage* m_page;
|
||||
};
|
||||
|
||||
}; // ns
|
||||
|
||||
#endif //CONTEXTPAGE_H
|
306
src/libtomahawk/context/ContextWidget.cpp
Normal file
@@ -0,0 +1,306 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ContextWidget.h"
|
||||
#include "ui_ContextWidget.h"
|
||||
|
||||
#include <QGraphicsProxyWidget>
|
||||
#include <QGraphicsScene>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QTimeLine>
|
||||
|
||||
#include "context/ContextPage.h"
|
||||
#include "context/pages/RelatedArtistsContext.h"
|
||||
#include "context/pages/TopTracksContext.h"
|
||||
#include "context/pages/WikipediaContext.h"
|
||||
|
||||
#include "playlist/artistview.h"
|
||||
#include "playlist/treemodel.h"
|
||||
|
||||
#define ANIMATION_TIME 450
|
||||
#define SLIDE_TIME 350
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
ContextWidget::ContextWidget( QWidget* parent )
|
||||
: QWidget( parent )
|
||||
, ui( new Ui::ContextWidget )
|
||||
, m_minHeight( 22 )
|
||||
, m_currentView( 0 )
|
||||
, m_visible( false )
|
||||
{
|
||||
ui->setupUi( this );
|
||||
TomahawkUtils::unmarginLayout( layout() );
|
||||
setContentsMargins( 0, 0, 0, 0 );
|
||||
|
||||
m_scene = new QGraphicsScene( this );
|
||||
|
||||
TopTracksContext* ttc = new TopTracksContext();
|
||||
RelatedArtistsContext* rac = new RelatedArtistsContext();
|
||||
WebContext* wiki = new WikipediaContext();
|
||||
WebContext* lastfm = new LastfmContext();
|
||||
|
||||
m_views << ttc;
|
||||
m_views << rac;
|
||||
m_views << wiki;
|
||||
m_views << lastfm;
|
||||
|
||||
foreach ( ContextPage* view, m_views )
|
||||
{
|
||||
ContextProxyPage* page = new ContextProxyPage();
|
||||
page->setPage( view );
|
||||
m_scene->addItem( page );
|
||||
|
||||
connect( page, SIGNAL( focused() ), SLOT( onPageFocused() ) );
|
||||
m_pages << page;
|
||||
}
|
||||
|
||||
ui->contextView->setScene( m_scene );
|
||||
ui->contextView->setFrameShape( QFrame::NoFrame );
|
||||
ui->contextView->setStyleSheet( "background: transparent" );
|
||||
ui->contextView->setAttribute( Qt::WA_MacShowFocusRect, 0 );
|
||||
ui->contextView->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
|
||||
|
||||
ui->contextView->hide();
|
||||
|
||||
QPalette whitePal = ui->toggleButton->palette();
|
||||
whitePal.setColor( QPalette::Foreground, Qt::white );
|
||||
ui->toggleButton->setPalette( whitePal );
|
||||
|
||||
QFont boldFont = ui->toggleButton->font();
|
||||
boldFont.setPixelSize( 12 );
|
||||
boldFont.setBold( true );
|
||||
ui->toggleButton->setFont( boldFont );
|
||||
ui->toggleButton->setText( tr( "Open Dashboard" ) );
|
||||
|
||||
setAutoFillBackground( true );
|
||||
setFixedHeight( m_minHeight );
|
||||
|
||||
QPalette pal = palette();
|
||||
pal.setBrush( QPalette::Window, QColor( 0x70, 0x70, 0x70 ) );
|
||||
setPalette( pal );
|
||||
|
||||
connect( ui->toggleButton, SIGNAL( clicked() ), SLOT( toggleSize() ) );
|
||||
|
||||
m_timeLine = new QTimeLine( ANIMATION_TIME, this );
|
||||
m_timeLine->setUpdateInterval( 20 );
|
||||
m_timeLine->setEasingCurve( QEasingCurve::OutCubic );
|
||||
|
||||
connect( m_timeLine, SIGNAL( frameChanged( int ) ), SLOT( onAnimationStep( int ) ) );
|
||||
connect( m_timeLine, SIGNAL( finished() ), SLOT( onAnimationFinished() ) );
|
||||
}
|
||||
|
||||
|
||||
ContextWidget::~ContextWidget()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ContextWidget::layoutViews( bool animate )
|
||||
{
|
||||
int smallViewWidth = 120;
|
||||
float smallViewOpacity = 0.6;
|
||||
|
||||
int margin = 6;
|
||||
int maxVisible = 2;
|
||||
int itemSize = ( m_scene->sceneRect().width() - smallViewWidth * 2 ) / maxVisible;
|
||||
int firstPos = margin;
|
||||
float opacity;
|
||||
|
||||
if ( m_currentView > 0 )
|
||||
firstPos = smallViewWidth;
|
||||
|
||||
if ( m_currentView + maxVisible >= m_pages.count() )
|
||||
{
|
||||
int delta = m_pages.count() - m_currentView;
|
||||
firstPos = m_scene->sceneRect().width() - ( delta * itemSize ) + 1;
|
||||
}
|
||||
|
||||
for ( int i = 0; i < m_pages.count(); i++ )
|
||||
{
|
||||
QGraphicsWidget* view = m_pages.at( i );
|
||||
|
||||
int x = firstPos - ( ( m_currentView - i ) * itemSize );
|
||||
|
||||
if ( ( x < smallViewWidth && x < firstPos ) || i > m_currentView + maxVisible - 1 )
|
||||
{
|
||||
opacity = smallViewOpacity;
|
||||
}
|
||||
else
|
||||
{
|
||||
opacity = 1.0;
|
||||
}
|
||||
|
||||
{
|
||||
QPropertyAnimation* animation = new QPropertyAnimation( view, "opacity" );
|
||||
animation->setDuration( SLIDE_TIME );
|
||||
animation->setEndValue( opacity );
|
||||
animation->start();
|
||||
}
|
||||
|
||||
QRect rect( x, margin, itemSize - margin * 2, m_scene->sceneRect().height() - margin * 2 );
|
||||
if ( animate )
|
||||
{
|
||||
{
|
||||
QPropertyAnimation* animation = new QPropertyAnimation( view, "geometry" );
|
||||
animation->setDuration( SLIDE_TIME );
|
||||
animation->setEndValue( rect );
|
||||
animation->start();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
view->setGeometry( rect );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ContextWidget::onPageFocused()
|
||||
{
|
||||
ContextProxyPage* widget = qobject_cast< ContextProxyPage* >( sender() );
|
||||
|
||||
int i = 0;
|
||||
foreach ( ContextProxyPage* view, m_pages )
|
||||
{
|
||||
if ( view == widget )
|
||||
{
|
||||
m_currentView = i;
|
||||
layoutViews( true );
|
||||
return;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ContextWidget::fadeOut( bool animate )
|
||||
{
|
||||
foreach ( QGraphicsWidget* view, m_pages )
|
||||
{
|
||||
if ( animate )
|
||||
{
|
||||
QPropertyAnimation* animation = new QPropertyAnimation( view, "opacity" );
|
||||
animation->setDuration( SLIDE_TIME );
|
||||
animation->setEndValue( 0.0 );
|
||||
animation->start();
|
||||
}
|
||||
else
|
||||
view->setOpacity( 0.0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ContextWidget::setQuery( const Tomahawk::query_ptr& query, bool force )
|
||||
{
|
||||
if ( query.isNull() )
|
||||
return;
|
||||
if ( !force && !m_query.isNull() && query->artist() == m_query->artist() )
|
||||
return;
|
||||
|
||||
m_query = query;
|
||||
if ( height() > m_minHeight )
|
||||
{
|
||||
foreach ( ContextProxyPage* proxy, m_pages )
|
||||
{
|
||||
proxy->page()->setQuery( query );
|
||||
}
|
||||
|
||||
layoutViews( true );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ContextWidget::toggleSize()
|
||||
{
|
||||
m_maxHeight = TomahawkUtils::tomahawkWindow()->height() * 0.3;
|
||||
|
||||
if ( height() == m_minHeight )
|
||||
{
|
||||
ui->toggleButton->setText( tr( "Close Dashboard" ) );
|
||||
|
||||
m_timeLine->setFrameRange( height(), m_maxHeight );
|
||||
m_timeLine->setDirection( QTimeLine::Forward );
|
||||
m_timeLine->start();
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->toggleButton->setText( tr( "Open Dashboard" ) );
|
||||
m_visible = false;
|
||||
ui->contextView->hide();
|
||||
|
||||
m_timeLine->setFrameRange( m_minHeight, height() );
|
||||
m_timeLine->setDirection( QTimeLine::Backward );
|
||||
m_timeLine->start();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ContextWidget::onAnimationStep( int frame )
|
||||
{
|
||||
setFixedHeight( frame );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ContextWidget::onAnimationFinished()
|
||||
{
|
||||
if ( m_timeLine->direction() == QTimeLine::Forward )
|
||||
{
|
||||
setFixedHeight( m_maxHeight );
|
||||
m_visible = true;
|
||||
ui->contextView->show();
|
||||
|
||||
fadeOut( false );
|
||||
m_scene->setSceneRect( ui->contextView->viewport()->rect() );
|
||||
layoutViews( false );
|
||||
setQuery( m_query, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
setFixedHeight( m_minHeight );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ContextWidget::paintEvent( QPaintEvent* e )
|
||||
{
|
||||
QWidget::paintEvent( e );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ContextWidget::resizeEvent( QResizeEvent* e )
|
||||
{
|
||||
QWidget::resizeEvent( e );
|
||||
|
||||
if ( m_visible )
|
||||
{
|
||||
m_scene->setSceneRect( ui->contextView->viewport()->rect() );
|
||||
layoutViews( false );
|
||||
}
|
||||
}
|
88
src/libtomahawk/context/ContextWidget.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CONTEXTWIDGET_H
|
||||
#define CONTEXTWIDGET_H
|
||||
|
||||
#include <QGraphicsView>
|
||||
|
||||
#include "dllmacro.h"
|
||||
|
||||
#include "query.h"
|
||||
|
||||
class QGraphicsScene;
|
||||
class QGraphicsWebView;
|
||||
class QGraphicsWidget;
|
||||
class QTimeLine;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
class ContextPage;
|
||||
class ContextProxyPage;
|
||||
}
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ContextWidget;
|
||||
}
|
||||
|
||||
class DLLEXPORT ContextWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ContextWidget( QWidget* parent = 0 );
|
||||
~ContextWidget();
|
||||
|
||||
public slots:
|
||||
void setQuery( const Tomahawk::query_ptr& query, bool force = false );
|
||||
|
||||
void toggleSize();
|
||||
|
||||
private slots:
|
||||
void onPageFocused();
|
||||
|
||||
void onAnimationStep( int frame );
|
||||
void onAnimationFinished();
|
||||
|
||||
protected:
|
||||
void paintEvent( QPaintEvent* e );
|
||||
void resizeEvent( QResizeEvent* e );
|
||||
|
||||
private:
|
||||
void fadeOut( bool animate );
|
||||
|
||||
void layoutViews( bool animate = true );
|
||||
|
||||
Ui::ContextWidget* ui;
|
||||
|
||||
int m_minHeight;
|
||||
int m_maxHeight;
|
||||
QTimeLine* m_timeLine;
|
||||
|
||||
QGraphicsScene* m_scene;
|
||||
QList<Tomahawk::ContextPage*> m_views;
|
||||
QList<Tomahawk::ContextProxyPage*> m_pages;
|
||||
|
||||
int m_currentView;
|
||||
|
||||
Tomahawk::query_ptr m_query;
|
||||
bool m_visible;
|
||||
};
|
||||
|
||||
#endif // CONTEXTWIDGET_H
|
76
src/libtomahawk/context/ContextWidget.ui
Normal file
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ContextWidget</class>
|
||||
<widget class="QWidget" name="ContextWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>774</width>
|
||||
<height>72</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>72</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>InfoBar</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="HeaderLabel" name="toggleButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Dashboard</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>1</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGraphicsView" name="contextView"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>HeaderLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header location="global">widgets/HeaderLabel.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
123
src/libtomahawk/context/pages/RelatedArtistsContext.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "RelatedArtistsContext.h"
|
||||
|
||||
#include <QHeaderView>
|
||||
|
||||
#include "playlist/artistview.h"
|
||||
#include "playlist/treemodel.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
RelatedArtistsContext::RelatedArtistsContext()
|
||||
: ContextPage()
|
||||
, m_infoId( uuid() )
|
||||
{
|
||||
m_relatedView = new ArtistView();
|
||||
m_relatedView->setGuid( "RelatedArtistsContext" );
|
||||
m_relatedModel = new TreeModel( m_relatedView );
|
||||
m_relatedModel->setColumnStyle( TreeModel::TrackOnly );
|
||||
m_relatedView->setTreeModel( m_relatedModel );
|
||||
m_relatedView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
|
||||
|
||||
QPalette pal = m_relatedView->palette();
|
||||
pal.setColor( QPalette::Window, QColor( 0, 0, 0, 0 ) );
|
||||
m_relatedView->setPalette( pal );
|
||||
|
||||
m_proxy = new QGraphicsProxyWidget();
|
||||
m_proxy->setWidget( m_relatedView );
|
||||
|
||||
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
|
||||
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
|
||||
|
||||
connect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ), SLOT( infoSystemFinished( QString ) ) );
|
||||
}
|
||||
|
||||
|
||||
RelatedArtistsContext::~RelatedArtistsContext()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RelatedArtistsContext::setQuery( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
if ( !m_query.isNull() && query->artist() == m_query->artist() )
|
||||
return;
|
||||
|
||||
m_query = query;
|
||||
|
||||
Tomahawk::InfoSystem::InfoCriteriaHash artistInfo;
|
||||
artistInfo["artist"] = query->artist();
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData;
|
||||
requestData.caller = m_infoId;
|
||||
requestData.customData = QVariantMap();
|
||||
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( artistInfo );
|
||||
|
||||
requestData.type = Tomahawk::InfoSystem::InfoArtistSimilars;
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RelatedArtistsContext::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
|
||||
{
|
||||
if ( requestData.caller != m_infoId )
|
||||
return;
|
||||
|
||||
InfoSystem::InfoCriteriaHash trackInfo;
|
||||
trackInfo = requestData.input.value< InfoSystem::InfoCriteriaHash >();
|
||||
|
||||
if ( output.canConvert< QVariantMap >() )
|
||||
{
|
||||
if ( trackInfo["artist"] != m_query->artist() )
|
||||
{
|
||||
qDebug() << "Returned info was for:" << trackInfo["artist"] << "- was looking for:" << m_query->artist();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QVariantMap returnedData = output.value< QVariantMap >();
|
||||
switch ( requestData.type )
|
||||
{
|
||||
case InfoSystem::InfoArtistSimilars:
|
||||
{
|
||||
m_relatedModel->clear();
|
||||
const QStringList artists = returnedData["artists"].toStringList();
|
||||
foreach ( const QString& artist, artists )
|
||||
{
|
||||
m_relatedModel->addArtists( Artist::get( artist ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
RelatedArtistsContext::infoSystemFinished( QString target )
|
||||
{
|
||||
Q_UNUSED( target );
|
||||
}
|
67
src/libtomahawk/context/pages/RelatedArtistsContext.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef RELATEDARTISTSCONTEXT_H
|
||||
#define RELATEDARTISTSCONTEXT_H
|
||||
|
||||
#include <QGraphicsProxyWidget>
|
||||
|
||||
#include "dllmacro.h"
|
||||
|
||||
#include "query.h"
|
||||
#include "context/ContextPage.h"
|
||||
#include "infosystem/infosystem.h"
|
||||
|
||||
class TreeModel;
|
||||
class ArtistView;
|
||||
|
||||
class DLLEXPORT RelatedArtistsContext : public Tomahawk::ContextPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RelatedArtistsContext();
|
||||
~RelatedArtistsContext();
|
||||
|
||||
virtual QGraphicsWidget* widget() { return m_proxy; }
|
||||
|
||||
virtual Tomahawk::PlaylistInterface* playlistInterface() const { return 0; }
|
||||
|
||||
virtual QString title() const { return tr( "Related Artists" ); }
|
||||
virtual QString description() const { return QString(); }
|
||||
|
||||
virtual bool jumpToCurrentTrack() { return false; }
|
||||
|
||||
public slots:
|
||||
virtual void setQuery( const Tomahawk::query_ptr& query );
|
||||
|
||||
private slots:
|
||||
void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
|
||||
void infoSystemFinished( QString target );
|
||||
|
||||
private:
|
||||
ArtistView* m_relatedView;
|
||||
TreeModel* m_relatedModel;
|
||||
|
||||
QGraphicsProxyWidget* m_proxy;
|
||||
|
||||
QString m_infoId;
|
||||
Tomahawk::query_ptr m_query;
|
||||
};
|
||||
|
||||
#endif // RELATEDARTISTSCONTEXT_H
|
129
src/libtomahawk/context/pages/TopTracksContext.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "TopTracksContext.h"
|
||||
|
||||
#include "playlist/playlistmodel.h"
|
||||
#include "playlist/playlistview.h"
|
||||
#include "playlist/trackheader.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
TopTracksContext::TopTracksContext()
|
||||
: ContextPage()
|
||||
, m_infoId( uuid() )
|
||||
{
|
||||
m_topHitsView = new PlaylistView();
|
||||
m_topHitsView->setGuid( "TopTracksContext" );
|
||||
m_topHitsView->setUpdatesContextView( false );
|
||||
m_topHitsModel = new PlaylistModel( m_topHitsView );
|
||||
m_topHitsModel->setStyle( TrackModel::Short );
|
||||
m_topHitsView->setPlaylistModel( m_topHitsModel );
|
||||
m_topHitsView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
|
||||
|
||||
QPalette pal = m_topHitsView->palette();
|
||||
pal.setColor( QPalette::Window, QColor( 0, 0, 0, 0 ) );
|
||||
m_topHitsView->setPalette( pal );
|
||||
|
||||
m_proxy = new QGraphicsProxyWidget();
|
||||
m_proxy->setWidget( m_topHitsView );
|
||||
|
||||
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
|
||||
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
|
||||
|
||||
connect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ), SLOT( infoSystemFinished( QString ) ) );
|
||||
}
|
||||
|
||||
|
||||
TopTracksContext::~TopTracksContext()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TopTracksContext::setQuery( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
if ( !m_query.isNull() && query->artist() == m_query->artist() )
|
||||
return;
|
||||
|
||||
m_query = query;
|
||||
|
||||
Tomahawk::InfoSystem::InfoCriteriaHash artistInfo;
|
||||
artistInfo["artist"] = query->artist();
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData;
|
||||
requestData.caller = m_infoId;
|
||||
requestData.customData = QVariantMap();
|
||||
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( artistInfo );
|
||||
|
||||
requestData.type = Tomahawk::InfoSystem::InfoArtistSongs;
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TopTracksContext::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
|
||||
{
|
||||
if ( requestData.caller != m_infoId )
|
||||
return;
|
||||
|
||||
InfoSystem::InfoCriteriaHash trackInfo;
|
||||
trackInfo = requestData.input.value< InfoSystem::InfoCriteriaHash >();
|
||||
|
||||
if ( output.canConvert< QVariantMap >() )
|
||||
{
|
||||
if ( trackInfo["artist"] != m_query->artist() )
|
||||
{
|
||||
qDebug() << "Returned info was for:" << trackInfo["artist"] << "- was looking for:" << m_query->artist();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QVariantMap returnedData = output.value< QVariantMap >();
|
||||
switch ( requestData.type )
|
||||
{
|
||||
case InfoSystem::InfoArtistSongs:
|
||||
{
|
||||
m_topHitsModel->clear();
|
||||
const QStringList tracks = returnedData["tracks"].toStringList();
|
||||
|
||||
int i = 0;
|
||||
foreach ( const QString& track, tracks )
|
||||
{
|
||||
query_ptr query = Query::get( m_query->artist(), track, QString(), uuid() );
|
||||
m_topHitsModel->append( query );
|
||||
|
||||
if ( ++i == 15 )
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TopTracksContext::infoSystemFinished( QString target )
|
||||
{
|
||||
Q_UNUSED( target );
|
||||
}
|
67
src/libtomahawk/context/pages/TopTracksContext.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TOPTRACKSCONTEXT_H
|
||||
#define TOPTRACKSCONTEXT_H
|
||||
|
||||
#include <QGraphicsProxyWidget>
|
||||
|
||||
#include "dllmacro.h"
|
||||
|
||||
#include "query.h"
|
||||
#include "context/ContextPage.h"
|
||||
#include "infosystem/infosystem.h"
|
||||
|
||||
class PlaylistModel;
|
||||
class PlaylistView;
|
||||
|
||||
class DLLEXPORT TopTracksContext : public Tomahawk::ContextPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TopTracksContext();
|
||||
~TopTracksContext();
|
||||
|
||||
virtual QGraphicsWidget* widget() { return m_proxy; }
|
||||
|
||||
virtual Tomahawk::PlaylistInterface* playlistInterface() const { return 0; }
|
||||
|
||||
virtual QString title() const { return tr( "Top Hits" ); }
|
||||
virtual QString description() const { return QString(); }
|
||||
|
||||
virtual bool jumpToCurrentTrack() { return false; }
|
||||
|
||||
public slots:
|
||||
virtual void setQuery( const Tomahawk::query_ptr& query );
|
||||
|
||||
private slots:
|
||||
void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
|
||||
void infoSystemFinished( QString target );
|
||||
|
||||
private:
|
||||
PlaylistView* m_topHitsView;
|
||||
PlaylistModel* m_topHitsModel;
|
||||
|
||||
QGraphicsProxyWidget* m_proxy;
|
||||
|
||||
QString m_infoId;
|
||||
Tomahawk::query_ptr m_query;
|
||||
};
|
||||
|
||||
#endif // TOPTRACKSCONTEXT_H
|
37
src/libtomahawk/context/pages/WebContext.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "WebContext.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
WebContext::WebContext()
|
||||
: ContextPage()
|
||||
{
|
||||
m_webView = new QGraphicsWebView();
|
||||
|
||||
QPalette pal = m_webView->palette();
|
||||
pal.setColor( QPalette::Window, QColor( 0, 0, 0, 0 ) );
|
||||
m_webView->setPalette( pal );
|
||||
}
|
||||
|
||||
|
||||
WebContext::~WebContext()
|
||||
{
|
||||
}
|
45
src/libtomahawk/context/pages/WebContext.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef WEBCONTEXT_H
|
||||
#define WEBCONTEXT_H
|
||||
|
||||
#include <QGraphicsWebView>
|
||||
|
||||
#include "dllmacro.h"
|
||||
|
||||
#include "query.h"
|
||||
#include "context/ContextPage.h"
|
||||
|
||||
class DLLEXPORT WebContext : public Tomahawk::ContextPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
WebContext();
|
||||
~WebContext();
|
||||
|
||||
QGraphicsWebView* webView() const { return m_webView; }
|
||||
virtual QGraphicsWidget* widget() { return m_webView; }
|
||||
|
||||
private:
|
||||
QGraphicsWebView* m_webView;
|
||||
Tomahawk::query_ptr m_query;
|
||||
};
|
||||
|
||||
#endif // WEBCONTEXT_H
|
43
src/libtomahawk/context/pages/WikipediaContext.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "WikipediaContext.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
void
|
||||
WikipediaContext::setQuery( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
if ( !m_query.isNull() && query->artist() == m_query->artist() )
|
||||
return;
|
||||
|
||||
m_query = query;
|
||||
webView()->load( QString( "http://en.wikipedia.org/w/index.php?printable=yes&title=%1" ).arg( query->artist() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastfmContext::setQuery( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
if ( !m_query.isNull() && query->artist() == m_query->artist() )
|
||||
return;
|
||||
|
||||
m_query = query;
|
||||
webView()->load( QString( "http://last.fm/music/%1" ).arg( query->artist() ) );
|
||||
}
|
74
src/libtomahawk/context/pages/WikipediaContext.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef WIKIPEDIACONTEXT_H
|
||||
#define WIKIPEDIACONTEXT_H
|
||||
|
||||
#include <QGraphicsProxyWidget>
|
||||
|
||||
#include "dllmacro.h"
|
||||
|
||||
#include "query.h"
|
||||
#include "WebContext.h"
|
||||
|
||||
class DLLEXPORT WikipediaContext : public WebContext
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
WikipediaContext() : WebContext() {}
|
||||
~WikipediaContext() {}
|
||||
|
||||
virtual Tomahawk::PlaylistInterface* playlistInterface() const { return 0; }
|
||||
|
||||
virtual QString title() const { return tr( "Wikipedia" ); }
|
||||
virtual QString description() const { return QString(); }
|
||||
|
||||
virtual bool jumpToCurrentTrack() { return false; }
|
||||
|
||||
public slots:
|
||||
virtual void setQuery( const Tomahawk::query_ptr& query );
|
||||
|
||||
private:
|
||||
Tomahawk::query_ptr m_query;
|
||||
};
|
||||
|
||||
|
||||
class DLLEXPORT LastfmContext : public WebContext
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LastfmContext() : WebContext() {}
|
||||
~LastfmContext() {}
|
||||
|
||||
virtual Tomahawk::PlaylistInterface* playlistInterface() const { return 0; }
|
||||
|
||||
virtual QString title() const { return tr( "Last.fm" ); }
|
||||
virtual QString description() const { return QString(); }
|
||||
|
||||
virtual bool jumpToCurrentTrack() { return false; }
|
||||
|
||||
public slots:
|
||||
virtual void setQuery( const Tomahawk::query_ptr& query );
|
||||
|
||||
private:
|
||||
Tomahawk::query_ptr m_query;
|
||||
};
|
||||
|
||||
#endif // WIKIPEDIACONTEXT_H
|
@@ -27,6 +27,7 @@
|
||||
#include "databasecommand_collectionstats.h"
|
||||
#include "databaseimpl.h"
|
||||
#include "network/controlconnection.h"
|
||||
#include "sourcelist.h"
|
||||
|
||||
#include "utils/logger.h"
|
||||
|
||||
@@ -72,7 +73,15 @@ DatabaseCommand_AddFiles::postCommitHook()
|
||||
emit notify( m_queries );
|
||||
|
||||
if( source()->isLocal() )
|
||||
{
|
||||
Servent::instance()->triggerDBSync();
|
||||
|
||||
// Re-calculate local db stats
|
||||
DatabaseCommand_CollectionStats* cmd = new DatabaseCommand_CollectionStats( SourceList::instance()->getLocal() );
|
||||
connect( cmd, SIGNAL( done( QVariantMap ) ),
|
||||
SourceList::instance()->getLocal().data(), SLOT( setStats( QVariantMap ) ), Qt::QueuedConnection );
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#include <QSqlQuery>
|
||||
|
||||
#include "databaseimpl.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "utils/logger.h"
|
||||
|
||||
|
||||
@@ -29,7 +30,7 @@ DatabaseCommand_AllAlbums::execForArtist( DatabaseImpl* dbi )
|
||||
{
|
||||
TomahawkSqlQuery query = dbi->newquery();
|
||||
QList<Tomahawk::album_ptr> al;
|
||||
QString orderToken, sourceToken;
|
||||
QString orderToken, sourceToken, filterToken, tables;
|
||||
|
||||
switch ( m_sortOrder )
|
||||
{
|
||||
@@ -43,17 +44,33 @@ DatabaseCommand_AllAlbums::execForArtist( DatabaseImpl* dbi )
|
||||
if ( !m_collection.isNull() )
|
||||
sourceToken = QString( "AND file.source %1 " ).arg( m_collection->source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( m_collection->source()->id() ) );
|
||||
|
||||
if ( !m_filter.isEmpty() )
|
||||
{
|
||||
QString filtersql;
|
||||
QStringList sl = m_filter.split( " ", QString::SkipEmptyParts );
|
||||
foreach( QString s, sl )
|
||||
{
|
||||
filtersql += QString( " AND ( artist.name LIKE '%%1%' OR album.name LIKE '%%1%' OR track.name LIKE '%%1%' )" ).arg( TomahawkUtils::sqlEscape( s ) );
|
||||
}
|
||||
|
||||
filterToken = QString( "AND artist.id = file_join.artist AND file_join.track = track.id %1" ).arg( filtersql );
|
||||
tables = "artist, track, file, file_join";
|
||||
}
|
||||
else
|
||||
tables = "file, file_join";
|
||||
|
||||
QString sql = QString(
|
||||
"SELECT DISTINCT album.id, album.name "
|
||||
"FROM file, file_join "
|
||||
"FROM %1 "
|
||||
"LEFT OUTER JOIN album "
|
||||
"ON file_join.album = album.id "
|
||||
"WHERE file.id = file_join.file "
|
||||
"AND file_join.artist = %1 "
|
||||
"%2 "
|
||||
"%3 %4 %5"
|
||||
).arg( m_artist->id() )
|
||||
"AND file_join.artist = %2 "
|
||||
"%3 %4 %5 %6 %7"
|
||||
).arg( tables )
|
||||
.arg( m_artist->id() )
|
||||
.arg( sourceToken )
|
||||
.arg( filterToken )
|
||||
.arg( m_sortOrder > 0 ? QString( "ORDER BY %1" ).arg( orderToken ) : QString() )
|
||||
.arg( m_sortDescending ? "DESC" : QString() )
|
||||
.arg( m_amount > 0 ? QString( "LIMIT 0, %1" ).arg( m_amount ) : QString() );
|
||||
@@ -74,8 +91,7 @@ DatabaseCommand_AllAlbums::execForArtist( DatabaseImpl* dbi )
|
||||
al << album;
|
||||
}
|
||||
|
||||
if ( al.count() )
|
||||
emit albums( al, data() );
|
||||
emit albums( al, data() );
|
||||
emit done();
|
||||
}
|
||||
|
||||
@@ -124,8 +140,7 @@ DatabaseCommand_AllAlbums::execForCollection( DatabaseImpl* dbi )
|
||||
al << album;
|
||||
}
|
||||
|
||||
if ( al.count() )
|
||||
emit albums( al, data() );
|
||||
emit albums( al, data() );
|
||||
emit done();
|
||||
}
|
||||
|
||||
|
@@ -59,6 +59,7 @@ public:
|
||||
void setLimit( unsigned int amount ) { m_amount = amount; }
|
||||
void setSortOrder( DatabaseCommand_AllAlbums::SortOrder order ) { m_sortOrder = order; }
|
||||
void setSortDescending( bool descending ) { m_sortDescending = descending; }
|
||||
void setFilter( const QString& filter ) { m_filter = filter; }
|
||||
|
||||
signals:
|
||||
void albums( const QList<Tomahawk::album_ptr>&, const QVariant& data );
|
||||
@@ -71,6 +72,7 @@ private:
|
||||
unsigned int m_amount;
|
||||
DatabaseCommand_AllAlbums::SortOrder m_sortOrder;
|
||||
bool m_sortDescending;
|
||||
QString m_filter;
|
||||
};
|
||||
|
||||
#endif // DATABASECOMMAND_ALLALBUMS_H
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#include <QSqlQuery>
|
||||
|
||||
#include "databaseimpl.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "utils/logger.h"
|
||||
|
||||
|
||||
@@ -29,7 +30,7 @@ DatabaseCommand_AllArtists::exec( DatabaseImpl* dbi )
|
||||
{
|
||||
TomahawkSqlQuery query = dbi->newquery();
|
||||
QList<Tomahawk::artist_ptr> al;
|
||||
QString orderToken, sourceToken;
|
||||
QString orderToken, sourceToken, filterToken, tables;
|
||||
|
||||
switch ( m_sortOrder )
|
||||
{
|
||||
@@ -41,15 +42,32 @@ DatabaseCommand_AllArtists::exec( DatabaseImpl* dbi )
|
||||
}
|
||||
|
||||
if ( !m_collection.isNull() )
|
||||
sourceToken = QString( "AND file.source %1 " ).arg( m_collection->source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( m_collection->source()->id() ) );
|
||||
sourceToken = QString( "AND file.source %1" ).arg( m_collection->source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( m_collection->source()->id() ) );
|
||||
|
||||
if ( !m_filter.isEmpty() )
|
||||
{
|
||||
QString filtersql;
|
||||
QStringList sl = m_filter.split( " ", QString::SkipEmptyParts );
|
||||
foreach( QString s, sl )
|
||||
{
|
||||
filtersql += QString( " AND ( artist.name LIKE '%%1%' OR album.name LIKE '%%1%' OR track.name LIKE '%%1%' )" ).arg( TomahawkUtils::sqlEscape( s ) );
|
||||
}
|
||||
|
||||
filterToken = QString( "AND file_join.album = album.id AND file_join.track = track.id %1" ).arg( filtersql );
|
||||
tables = "artist, track, album, file, file_join";
|
||||
}
|
||||
else
|
||||
tables = "artist, file, file_join";
|
||||
|
||||
QString sql = QString(
|
||||
"SELECT DISTINCT artist.id, artist.name "
|
||||
"FROM artist, file, file_join "
|
||||
"FROM %1 "
|
||||
"WHERE file.id = file_join.file "
|
||||
"AND file_join.artist = artist.id "
|
||||
"%1 %2 %3 %4"
|
||||
).arg( sourceToken )
|
||||
"%2 %3 %4 %5 %6"
|
||||
).arg( tables )
|
||||
.arg( sourceToken )
|
||||
.arg( filterToken )
|
||||
.arg( m_sortOrder > 0 ? QString( "ORDER BY %1" ).arg( orderToken ) : QString() )
|
||||
.arg( m_sortDescending ? "DESC" : QString() )
|
||||
.arg( m_amount > 0 ? QString( "LIMIT 0, %1" ).arg( m_amount ) : QString() );
|
||||
@@ -64,7 +82,6 @@ DatabaseCommand_AllArtists::exec( DatabaseImpl* dbi )
|
||||
al << artist;
|
||||
}
|
||||
|
||||
if ( al.count() )
|
||||
emit artists( al );
|
||||
emit artists( al );
|
||||
emit done();
|
||||
}
|
||||
|
@@ -54,6 +54,7 @@ public:
|
||||
void setLimit( unsigned int amount ) { m_amount = amount; }
|
||||
void setSortOrder( DatabaseCommand_AllArtists::SortOrder order ) { m_sortOrder = order; }
|
||||
void setSortDescending( bool descending ) { m_sortDescending = descending; }
|
||||
void setFilter( const QString& filter ) { m_filter = filter; }
|
||||
|
||||
signals:
|
||||
void artists( const QList<Tomahawk::artist_ptr>& );
|
||||
@@ -64,6 +65,7 @@ private:
|
||||
unsigned int m_amount;
|
||||
DatabaseCommand_AllArtists::SortOrder m_sortOrder;
|
||||
bool m_sortDescending;
|
||||
QString m_filter;
|
||||
};
|
||||
|
||||
#endif // DATABASECOMMAND_ALLARTISTS_H
|
||||
|
@@ -57,11 +57,7 @@ DatabaseCommand_CollectionStats::exec( DatabaseImpl* dbi )
|
||||
{
|
||||
m.insert( "numfiles", query.value( 0 ).toInt() );
|
||||
m.insert( "lastmodified", query.value( 1 ).toInt() );
|
||||
|
||||
if ( !source()->isLocal() && !source()->lastOpGuid().isEmpty() )
|
||||
m.insert( "lastop", source()->lastOpGuid() );
|
||||
else
|
||||
m.insert( "lastop", query.value( 2 ).toString() );
|
||||
m.insert( "lastop", query.value( 2 ).toString() );
|
||||
}
|
||||
|
||||
emit done( m );
|
||||
|
@@ -31,11 +31,31 @@ void
|
||||
DatabaseCommand_LoadAllAutoPlaylists::exec( DatabaseImpl* dbi )
|
||||
{
|
||||
TomahawkSqlQuery query = dbi->newquery();
|
||||
QString orderToken, sourceToken;
|
||||
|
||||
switch ( m_sortOrder )
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case DatabaseCommand_LoadAllPlaylists::ModificationTime:
|
||||
orderToken = "playlist.createdOn";
|
||||
}
|
||||
|
||||
if ( !source().isNull() )
|
||||
sourceToken = QString( "AND source %1 " ).arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) );
|
||||
|
||||
|
||||
query.exec( QString( "SELECT playlist.guid as guid, title, info, creator, createdOn, lastmodified, shared, currentrevision, dynamic_playlist.pltype, dynamic_playlist.plmode "
|
||||
"FROM playlist, dynamic_playlist WHERE source %1 AND dynplaylist = 'true' AND playlist.guid = dynamic_playlist.guid AND dynamic_playlist.plmode = %2 AND dynamic_playlist.autoload = 'true'" )
|
||||
.arg( source()->isLocal() ? "IS NULL" : QString( "=%1" ).arg( source()->id() ) )
|
||||
.arg( Static ) );
|
||||
"FROM playlist, dynamic_playlist WHERE dynplaylist = 'true' AND playlist.guid = dynamic_playlist.guid AND dynamic_playlist.plmode = %1 AND dynamic_playlist.autoload = 'true' "
|
||||
"%2"
|
||||
"%3 %4 %5"
|
||||
)
|
||||
.arg( Static )
|
||||
.arg( sourceToken )
|
||||
.arg( m_sortOrder > 0 ? QString( "ORDER BY %1" ).arg( orderToken ) : QString() )
|
||||
.arg( m_sortDescending ? "DESC" : QString() )
|
||||
.arg( m_limitAmount > 0 ? QString( "LIMIT 0, %1" ).arg( m_limitAmount ) : QString() ) );
|
||||
|
||||
QList<dynplaylist_ptr> plists;
|
||||
while ( query.next() )
|
||||
|
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "databasecommand.h"
|
||||
#include "typedefs.h"
|
||||
#include "databasecommand_loadallplaylists.h"
|
||||
|
||||
class DatabaseCommand_LoadAllAutoPlaylists : public DatabaseCommand
|
||||
{
|
||||
@@ -32,15 +33,27 @@ class DatabaseCommand_LoadAllAutoPlaylists : public DatabaseCommand
|
||||
public:
|
||||
explicit DatabaseCommand_LoadAllAutoPlaylists( const Tomahawk::source_ptr& s, QObject* parent = 0 )
|
||||
: DatabaseCommand( s, parent )
|
||||
, m_limitAmount( 0 )
|
||||
, m_sortOrder( DatabaseCommand_LoadAllPlaylists::None )
|
||||
, m_sortDescending( false )
|
||||
{}
|
||||
|
||||
virtual void exec( DatabaseImpl* );
|
||||
virtual bool doesMutates() const { return false; }
|
||||
virtual QString commandname() const { return "loadallautoplaylists"; }
|
||||
|
||||
void setLimit( unsigned int limit ) { m_limitAmount = limit; }
|
||||
void setSortOrder( DatabaseCommand_LoadAllPlaylists::SortOrder order ) { m_sortOrder = order; }
|
||||
void setSortDescending( bool descending ) { m_sortDescending = descending; }
|
||||
|
||||
signals:
|
||||
void autoPlaylistLoaded( const Tomahawk::source_ptr& source, const QVariantList& data );
|
||||
void done();
|
||||
|
||||
private:
|
||||
unsigned int m_limitAmount;
|
||||
DatabaseCommand_LoadAllPlaylists::SortOrder m_sortOrder;
|
||||
bool m_sortDescending;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -1,6 +1,7 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@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
|
||||
@@ -31,12 +32,31 @@ void
|
||||
DatabaseCommand_LoadAllPlaylists::exec( DatabaseImpl* dbi )
|
||||
{
|
||||
TomahawkSqlQuery query = dbi->newquery();
|
||||
QString orderToken, sourceToken;
|
||||
|
||||
switch ( m_sortOrder )
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case ModificationTime:
|
||||
orderToken = "playlist.createdOn";
|
||||
}
|
||||
|
||||
if ( !source().isNull() )
|
||||
sourceToken = QString( "AND source %1 " ).arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) );
|
||||
|
||||
|
||||
query.exec( QString( "SELECT guid, title, info, creator, lastmodified, shared, currentrevision, createdOn "
|
||||
"FROM playlist WHERE source %1 AND dynplaylist = 'false'" )
|
||||
.arg( source()->isLocal() ? "IS NULL" :
|
||||
QString( "= %1" ).arg( source()->id() )
|
||||
) );
|
||||
"FROM playlist "
|
||||
"WHERE dynplaylist = 'false' "
|
||||
"%1 "
|
||||
"%2 %3 %4"
|
||||
)
|
||||
.arg( sourceToken )
|
||||
.arg( m_sortOrder > 0 ? QString( "ORDER BY %1" ).arg( orderToken ) : QString() )
|
||||
.arg( m_sortDescending ? "DESC" : QString() )
|
||||
.arg( m_limitAmount > 0 ? QString( "LIMIT 0, %1" ).arg( m_limitAmount ) : QString() ) );
|
||||
|
||||
QList<playlist_ptr> plists;
|
||||
while ( query.next() )
|
||||
|
@@ -1,6 +1,7 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@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
|
||||
@@ -29,19 +30,41 @@
|
||||
|
||||
class DLLEXPORT DatabaseCommand_LoadAllPlaylists : public DatabaseCommand
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum SortOrder {
|
||||
None = 0,
|
||||
ModificationTime = 1
|
||||
};
|
||||
enum SortAscDesc {
|
||||
NoOrder = 0,
|
||||
Ascending = 1,
|
||||
Descending = 2
|
||||
};
|
||||
|
||||
explicit DatabaseCommand_LoadAllPlaylists( const Tomahawk::source_ptr& s, QObject* parent = 0 )
|
||||
: DatabaseCommand( s, parent )
|
||||
, m_limitAmount( 0 )
|
||||
, m_sortOrder( None )
|
||||
, m_sortDescending( false )
|
||||
{}
|
||||
|
||||
virtual void exec( DatabaseImpl* );
|
||||
virtual bool doesMutates() const { return false; }
|
||||
virtual QString commandname() const { return "loadallplaylists"; }
|
||||
|
||||
void setLimit( unsigned int limit ) { m_limitAmount = limit; }
|
||||
void setSortOrder( SortOrder order ) { m_sortOrder = order; }
|
||||
void setSortDescending( bool descending ) { m_sortDescending = descending; }
|
||||
|
||||
signals:
|
||||
void done( const QList<Tomahawk::playlist_ptr>& playlists );
|
||||
|
||||
private:
|
||||
unsigned int m_limitAmount;
|
||||
SortOrder m_sortOrder;
|
||||
bool m_sortDescending;
|
||||
};
|
||||
|
||||
#endif // DATABASECOMMAND_LOADALLPLAYLIST_H
|
||||
|
@@ -0,0 +1,108 @@
|
||||
/* === 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 "databasecommand_loadallsortedplaylists.h"
|
||||
#include "databaseimpl.h"
|
||||
|
||||
#include "playlist.h"
|
||||
#include <libtomahawk/sourcelist.h>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
void
|
||||
DatabaseCommand_LoadAllSortedPlaylists::exec( DatabaseImpl* dbi )
|
||||
{
|
||||
TomahawkSqlQuery query = dbi->newquery();
|
||||
QString orderToken, sourceToken, ascDescToken;
|
||||
|
||||
switch ( m_sortOrder )
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case DatabaseCommand_LoadAllPlaylists::ModificationTime:
|
||||
orderToken = "playlist.createdOn";
|
||||
}
|
||||
|
||||
switch ( m_sortAscDesc )
|
||||
{
|
||||
case DatabaseCommand_LoadAllPlaylists::NoOrder:
|
||||
break;
|
||||
case DatabaseCommand_LoadAllPlaylists::Ascending:
|
||||
ascDescToken = "ASC";
|
||||
break;
|
||||
case DatabaseCommand_LoadAllPlaylists::Descending:
|
||||
ascDescToken = "DESC";
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !source().isNull() )
|
||||
sourceToken = QString( "AND source %1 " ).arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) );
|
||||
|
||||
|
||||
query.exec( QString( "SELECT playlist.guid as guid, title, info, creator, lastmodified, shared, currentrevision, createdOn, dynplaylist, source, dynamic_playlist.pltype, dynamic_playlist.plmode "
|
||||
"FROM playlist "
|
||||
"LEFT JOIN dynamic_playlist ON playlist.guid = dynamic_playlist.guid "
|
||||
"%1 "
|
||||
"%2 %3 %4"
|
||||
)
|
||||
.arg( sourceToken )
|
||||
.arg( m_sortOrder > 0 ? QString( "ORDER BY %1" ).arg( orderToken ) : QString() )
|
||||
.arg( ascDescToken )
|
||||
.arg( m_limitAmount > 0 ? QString( "LIMIT 0, %1" ).arg( m_limitAmount ) : QString() ) );
|
||||
|
||||
QList<SourcePlaylistPair> plists;
|
||||
while ( query.next() )
|
||||
{
|
||||
plists << QPair< int, QString >( query.value(9).toInt(), query.value(0).toString() );
|
||||
// playlist_ptr p;
|
||||
// bool dynamic = query.value(8).toBool();
|
||||
// source_ptr s = SourceList::instance()->get( query.value(9).toInt() );
|
||||
//
|
||||
// if ( dynamic )
|
||||
// {
|
||||
// p = dynplaylist_ptr( new DynamicPlaylist( s,
|
||||
// query.value(6).toString(), //current rev
|
||||
// query.value(1).toString(), //title
|
||||
// query.value(2).toString(), //info
|
||||
// query.value(3).toString(), //creator
|
||||
// query.value(7).toInt(), //createdOn
|
||||
// query.value(10).toString(), //type
|
||||
// (GeneratorMode)query.value(11).toInt(), // mode
|
||||
// query.value(5).toBool(), //shared
|
||||
// query.value(4).toInt(), //lastmod
|
||||
// query.value(0).toString() //GUID
|
||||
// ) );
|
||||
// } else
|
||||
// {
|
||||
// p = playlist_ptr( new Playlist( s, //src
|
||||
// query.value(6).toString(), //current rev
|
||||
// query.value(1).toString(), //title
|
||||
// query.value(2).toString(), //info
|
||||
// query.value(3).toString(), //creator
|
||||
// query.value(7).toInt(), //createdOn
|
||||
// query.value(5).toBool(), //shared
|
||||
// query.value(4).toInt(), //lastmod
|
||||
// query.value(0).toString() //GUID
|
||||
// ) );
|
||||
// }
|
||||
// plists.append( p );
|
||||
}
|
||||
|
||||
emit done( plists );
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
/* === 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 DATABASECOMMAND_LOADALLSORTEDPLAYLISTS_H
|
||||
#define DATABASECOMMAND_LOADALLSORTEDPLAYLISTS_H
|
||||
|
||||
#include "libtomahawk/database/databasecommand.h"
|
||||
#include "databasecommand_loadallplaylists.h"
|
||||
|
||||
/**
|
||||
* Loads *all* playlists, automatic playlists, and stations. Another dbcmd because otherwise loading them all
|
||||
* is fragmented across 3 dbcmds with a different interface.
|
||||
*
|
||||
* You probably want to limit / sort the output.
|
||||
*/
|
||||
class DatabaseCommand_LoadAllSortedPlaylists : public DatabaseCommand
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
// don't macros rock... not
|
||||
typedef QPair<int,QString> SourcePlaylistPair;
|
||||
explicit DatabaseCommand_LoadAllSortedPlaylists( const Tomahawk::source_ptr& s, QObject* parent = 0 )
|
||||
: DatabaseCommand( s, parent )
|
||||
, m_limitAmount( 0 )
|
||||
, m_sortOrder( DatabaseCommand_LoadAllPlaylists::None )
|
||||
, m_sortAscDesc( DatabaseCommand_LoadAllPlaylists::NoOrder )
|
||||
{
|
||||
qRegisterMetaType<QList<DatabaseCommand_LoadAllSortedPlaylists::SourcePlaylistPair> >("QList<DatabaseCommand_LoadAllSortedPlaylists::SourcePlaylistPair>");
|
||||
}
|
||||
|
||||
virtual void exec( DatabaseImpl* );
|
||||
virtual bool doesMutates() const { return false; }
|
||||
virtual QString commandname() const { return "loadallsortedplaylists"; }
|
||||
|
||||
void setLimit( unsigned int limit ) { m_limitAmount = limit; }
|
||||
void setSortOrder( DatabaseCommand_LoadAllPlaylists::SortOrder order ) { m_sortOrder = order; }
|
||||
void setSortAscDesc( DatabaseCommand_LoadAllPlaylists::SortAscDesc asc ) { m_sortAscDesc = asc; }
|
||||
|
||||
signals:
|
||||
void done( const QList<DatabaseCommand_LoadAllSortedPlaylists::SourcePlaylistPair>& playlistGuids ); // QPair< sourceid, playlistguid>
|
||||
|
||||
private:
|
||||
unsigned int m_limitAmount;
|
||||
DatabaseCommand_LoadAllPlaylists::SortOrder m_sortOrder;
|
||||
DatabaseCommand_LoadAllPlaylists::SortAscDesc m_sortAscDesc;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(QList<DatabaseCommand_LoadAllSortedPlaylists::SourcePlaylistPair>)
|
||||
#endif // DATABASECOMMAND_LOADALLSORTEDPLAYLISTS_H
|
@@ -31,11 +31,32 @@ void
|
||||
DatabaseCommand_LoadAllStations::exec( DatabaseImpl* dbi )
|
||||
{
|
||||
TomahawkSqlQuery query = dbi->newquery();
|
||||
QString orderToken, sourceToken;
|
||||
|
||||
switch ( m_sortOrder )
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case DatabaseCommand_LoadAllPlaylists::ModificationTime:
|
||||
orderToken = "playlist.createdOn";
|
||||
}
|
||||
|
||||
if ( !source().isNull() )
|
||||
sourceToken = QString( "AND source %1 " ).arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) );
|
||||
|
||||
|
||||
query.exec( QString( "SELECT playlist.guid as guid, title, info, creator, createdOn, lastmodified, shared, currentrevision, dynamic_playlist.pltype, dynamic_playlist.plmode "
|
||||
"FROM playlist, dynamic_playlist WHERE source %1 AND dynplaylist = 'true' AND playlist.guid = dynamic_playlist.guid AND dynamic_playlist.plmode = %2 AND dynamic_playlist.autoload = 'true'" )
|
||||
.arg( source()->isLocal() ? "IS NULL" : QString( "=%1" ).arg( source()->id() ) )
|
||||
.arg( OnDemand ) );
|
||||
"FROM playlist, dynamic_playlist WHERE "
|
||||
"dynplaylist = 'true' AND playlist.guid = dynamic_playlist.guid AND dynamic_playlist.plmode = %1 AND dynamic_playlist.autoload = 'true' "
|
||||
"%2"
|
||||
"%3 %4 %5"
|
||||
)
|
||||
.arg( OnDemand )
|
||||
.arg( sourceToken )
|
||||
.arg( m_sortOrder > 0 ? QString( "ORDER BY %1" ).arg( orderToken ) : QString() )
|
||||
.arg( m_sortDescending ? "DESC" : QString() )
|
||||
.arg( m_limitAmount > 0 ? QString( "LIMIT 0, %1" ).arg( m_limitAmount ) : QString() ) );
|
||||
|
||||
QList<dynplaylist_ptr> plists;
|
||||
while ( query.next() )
|
||||
|
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "databasecommand.h"
|
||||
#include "typedefs.h"
|
||||
#include "databasecommand_loadallplaylists.h"
|
||||
|
||||
class DatabaseCommand_LoadAllStations : public DatabaseCommand
|
||||
{
|
||||
@@ -32,15 +33,27 @@ class DatabaseCommand_LoadAllStations : public DatabaseCommand
|
||||
public:
|
||||
explicit DatabaseCommand_LoadAllStations( const Tomahawk::source_ptr& s, QObject* parent = 0 )
|
||||
: DatabaseCommand( s, parent )
|
||||
, m_limitAmount( 0 )
|
||||
, m_sortOrder( DatabaseCommand_LoadAllPlaylists::None )
|
||||
, m_sortDescending( false )
|
||||
{}
|
||||
|
||||
virtual void exec( DatabaseImpl* );
|
||||
virtual bool doesMutates() const { return false; }
|
||||
virtual QString commandname() const { return "loadallstations"; }
|
||||
|
||||
void setLimit( unsigned int limit ) { m_limitAmount = limit; }
|
||||
void setSortOrder( DatabaseCommand_LoadAllPlaylists::SortOrder order ) { m_sortOrder = order; }
|
||||
void setSortDescending( bool descending ) { m_sortDescending = descending; }
|
||||
|
||||
signals:
|
||||
void stationLoaded( const Tomahawk::source_ptr& source, const QVariantList& data );
|
||||
void done();
|
||||
|
||||
private:
|
||||
unsigned int m_limitAmount;
|
||||
DatabaseCommand_LoadAllPlaylists::SortOrder m_sortOrder;
|
||||
bool m_sortDescending;
|
||||
};
|
||||
|
||||
#endif
|
@@ -26,6 +26,22 @@ DatabaseCommand_loadOps::exec( DatabaseImpl* dbi )
|
||||
{
|
||||
QList< dbop_ptr > ops;
|
||||
|
||||
if ( !m_since.isEmpty() )
|
||||
{
|
||||
TomahawkSqlQuery query = dbi->newquery();
|
||||
query.prepare( QString( "SELECT id FROM oplog WHERE guid = ?" ) );
|
||||
query.addBindValue( m_since );
|
||||
query.exec();
|
||||
|
||||
if ( !query.next() )
|
||||
{
|
||||
tLog() << "Unknown oplog guid, requested, not replying:" << m_since;
|
||||
Q_ASSERT( false );
|
||||
emit done( m_since, m_since, ops );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
TomahawkSqlQuery query = dbi->newquery();
|
||||
query.prepare( QString(
|
||||
"SELECT guid, command, json, compressed, singleton "
|
||||
|
@@ -45,11 +45,13 @@ DatabaseCommand_LogPlayback::postCommitHook()
|
||||
|
||||
if ( m_action == Finished )
|
||||
{
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << " logging finished from source " << source().data()->id();
|
||||
emit trackPlayed( q );
|
||||
}
|
||||
// if the play time is more than 10 minutes in the past, ignore
|
||||
else if ( m_action == Started && QDateTime::fromTime_t( playtime() ).secsTo( QDateTime::currentDateTime() ) < 600 )
|
||||
{
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << " logging started from source " << source().data()->id();
|
||||
emit trackPlaying( q );
|
||||
}
|
||||
|
||||
|
@@ -110,6 +110,7 @@ DatabaseWorker::doWork()
|
||||
try
|
||||
{
|
||||
{
|
||||
tDebug() << "Executing cmd:" << cmd->guid();
|
||||
cmd->_exec( m_dbimpl ); // runs actual SQL stuff
|
||||
|
||||
if ( cmd->loggable() )
|
||||
|
516
src/libtomahawk/dropjob.cpp
Normal file
@@ -0,0 +1,516 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2011, Michael Zanetti <mzanetti@kde.org>
|
||||
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dropjob.h"
|
||||
|
||||
#include "artist.h"
|
||||
#include "album.h"
|
||||
|
||||
#include "utils/spotifyparser.h"
|
||||
#include "utils/rdioparser.h"
|
||||
#include "utils/shortenedlinkparser.h"
|
||||
#include "utils/logger.h"
|
||||
#include "globalactionmanager.h"
|
||||
#include "infosystem/infosystem.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
DropJob::DropJob( QObject *parent )
|
||||
: QObject( parent )
|
||||
, m_queryCount( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
DropJob::~DropJob()
|
||||
{
|
||||
qDebug() << "destryong DropJob";
|
||||
}
|
||||
|
||||
/// QMIMEDATA HANDLING
|
||||
|
||||
QStringList
|
||||
DropJob::mimeTypes()
|
||||
{
|
||||
QStringList mimeTypes;
|
||||
mimeTypes << "application/tomahawk.query.list"
|
||||
<< "application/tomahawk.plentry.list"
|
||||
<< "application/tomahawk.result.list"
|
||||
<< "application/tomahawk.result"
|
||||
<< "application/tomahawk.metadata.artist"
|
||||
<< "application/tomahawk.metadata.album"
|
||||
<< "application/tomahawk.mixed"
|
||||
<< "text/plain";
|
||||
return mimeTypes;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DropJob::acceptsMimeData( const QMimeData* data, bool tracksOnly )
|
||||
{
|
||||
if ( data->hasFormat( "application/tomahawk.query.list" )
|
||||
|| data->hasFormat( "application/tomahawk.plentry.list" )
|
||||
|| data->hasFormat( "application/tomahawk.result.list" )
|
||||
|| data->hasFormat( "application/tomahawk.result" )
|
||||
|| data->hasFormat( "application/tomahawk.mixed" )
|
||||
|| data->hasFormat( "application/tomahawk.metadata.album" )
|
||||
|| data->hasFormat( "application/tomahawk.metadata.artist" ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// crude check for spotify tracks
|
||||
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "spotify" ) &&
|
||||
( tracksOnly ? data->data( "text/plain" ).contains( "track" ) : true ) )
|
||||
return true;
|
||||
|
||||
// crude check for rdio tracks
|
||||
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "rdio.com" ) &&
|
||||
( tracksOnly ? data->data( "text/plain" ).contains( "track" ) : true ) )
|
||||
return true;
|
||||
|
||||
// We whitelist t.co and bit.ly (and j.mp) since they do some link checking. Often playable (e.g. spotify..) links hide behind them,
|
||||
// so we do an extra level of lookup
|
||||
if ( ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "bit.ly" ) ) ||
|
||||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "j.mp" ) ) ||
|
||||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "t.co" ) ) ||
|
||||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "rd.io" ) ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
DropJob::setGetWholeArtists( bool getWholeArtists )
|
||||
{
|
||||
m_getWholeArtists = getWholeArtists;
|
||||
}
|
||||
|
||||
void
|
||||
DropJob::setGetWholeAlbums( bool getWholeAlbums )
|
||||
{
|
||||
m_getWholeAlbums = getWholeAlbums;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DropJob::tracksFromMimeData( const QMimeData* data, bool allowDuplicates, bool onlyLocal, bool top10 )
|
||||
{
|
||||
m_allowDuplicates = allowDuplicates;
|
||||
m_onlyLocal = onlyLocal;
|
||||
m_top10 = top10;
|
||||
|
||||
parseMimeData( data );
|
||||
|
||||
if ( m_queryCount == 0 )
|
||||
{
|
||||
if ( onlyLocal )
|
||||
removeRemoteSources();
|
||||
|
||||
if ( !allowDuplicates )
|
||||
removeDuplicates();
|
||||
|
||||
emit tracks( m_resultList );
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DropJob::parseMimeData( const QMimeData *data )
|
||||
{
|
||||
QList< query_ptr > results;
|
||||
if ( data->hasFormat( "application/tomahawk.query.list" ) )
|
||||
results = tracksFromQueryList( data );
|
||||
else if ( data->hasFormat( "application/tomahawk.result.list" ) )
|
||||
results = tracksFromResultList( data );
|
||||
else if ( data->hasFormat( "application/tomahawk.metadata.album" ) )
|
||||
results = tracksFromAlbumMetaData( data );
|
||||
else if ( data->hasFormat( "application/tomahawk.metadata.artist" ) )
|
||||
results = tracksFromArtistMetaData( data );
|
||||
else if ( data->hasFormat( "application/tomahawk.mixed" ) )
|
||||
tracksFromMixedData( data );
|
||||
else if ( data->hasFormat( "text/plain" ) )
|
||||
{
|
||||
QString plainData = QString::fromUtf8( data->data( "text/plain" ).constData() );
|
||||
tDebug() << "Got text/plain mime data:" << data->data( "text/plain" ) << "decoded to:" << plainData;
|
||||
handleTrackUrls ( plainData );
|
||||
}
|
||||
|
||||
m_resultList.append( results );
|
||||
}
|
||||
|
||||
QList< query_ptr >
|
||||
DropJob::tracksFromQueryList( const QMimeData* data )
|
||||
{
|
||||
QList< query_ptr > queries;
|
||||
QByteArray itemData = data->data( "application/tomahawk.query.list" );
|
||||
QDataStream stream( &itemData, QIODevice::ReadOnly );
|
||||
|
||||
while ( !stream.atEnd() )
|
||||
{
|
||||
qlonglong qptr;
|
||||
stream >> qptr;
|
||||
|
||||
query_ptr* query = reinterpret_cast<query_ptr*>(qptr);
|
||||
if ( query && !query->isNull() )
|
||||
{
|
||||
tDebug() << "Dropped query item:" << query->data()->artist() << "-" << query->data()->track();
|
||||
|
||||
if ( m_top10 )
|
||||
{
|
||||
getTopTen( query->data()->artist() );
|
||||
}
|
||||
else if ( m_getWholeArtists )
|
||||
{
|
||||
queries << getArtist( query->data()->artist() );
|
||||
}
|
||||
else if ( m_getWholeAlbums )
|
||||
{
|
||||
queries << getAlbum( query->data()->artist(), query->data()->album() );
|
||||
}
|
||||
else
|
||||
{
|
||||
queries << *query;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return queries;
|
||||
}
|
||||
|
||||
QList< query_ptr >
|
||||
DropJob::tracksFromResultList( const QMimeData* data )
|
||||
{
|
||||
QList< query_ptr > queries;
|
||||
QByteArray itemData = data->data( "application/tomahawk.result.list" );
|
||||
QDataStream stream( &itemData, QIODevice::ReadOnly );
|
||||
|
||||
while ( !stream.atEnd() )
|
||||
{
|
||||
qlonglong qptr;
|
||||
stream >> qptr;
|
||||
|
||||
result_ptr* result = reinterpret_cast<result_ptr*>(qptr);
|
||||
if ( result && !result->isNull() )
|
||||
{
|
||||
tDebug() << "Dropped result item:" << result->data()->artist()->name() << "-" << result->data()->track();
|
||||
query_ptr q = result->data()->toQuery();
|
||||
|
||||
if ( m_top10 )
|
||||
{
|
||||
getTopTen( q->artist() );
|
||||
}
|
||||
else if ( m_getWholeArtists )
|
||||
{
|
||||
queries << getArtist( q->artist() );
|
||||
}
|
||||
else if ( m_getWholeAlbums )
|
||||
{
|
||||
queries << getAlbum( q->artist(), q->album() );
|
||||
}
|
||||
else
|
||||
{
|
||||
q->addResults( QList< result_ptr >() << *result );
|
||||
queries << q;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return queries;
|
||||
}
|
||||
|
||||
QList< query_ptr >
|
||||
DropJob::tracksFromAlbumMetaData( const QMimeData *data )
|
||||
{
|
||||
QList<query_ptr> queries;
|
||||
QByteArray itemData = data->data( "application/tomahawk.metadata.album" );
|
||||
QDataStream stream( &itemData, QIODevice::ReadOnly );
|
||||
|
||||
while ( !stream.atEnd() )
|
||||
{
|
||||
QString artist;
|
||||
stream >> artist;
|
||||
QString album;
|
||||
stream >> album;
|
||||
|
||||
if ( m_top10 )
|
||||
getTopTen( artist );
|
||||
else if ( m_getWholeArtists )
|
||||
queries << getArtist( artist );
|
||||
else
|
||||
queries << getAlbum( artist, album );
|
||||
}
|
||||
return queries;
|
||||
}
|
||||
|
||||
QList< query_ptr >
|
||||
DropJob::tracksFromArtistMetaData( const QMimeData *data )
|
||||
{
|
||||
QList<query_ptr> queries;
|
||||
QByteArray itemData = data->data( "application/tomahawk.metadata.artist" );
|
||||
QDataStream stream( &itemData, QIODevice::ReadOnly );
|
||||
|
||||
while ( !stream.atEnd() )
|
||||
{
|
||||
QString artist;
|
||||
stream >> artist;
|
||||
|
||||
if ( !m_top10 )
|
||||
{
|
||||
queries << getArtist( artist );
|
||||
}
|
||||
else
|
||||
{
|
||||
getTopTen( artist );
|
||||
}
|
||||
}
|
||||
return queries;
|
||||
}
|
||||
|
||||
QList< query_ptr >
|
||||
DropJob::tracksFromMixedData( const QMimeData *data )
|
||||
{
|
||||
QList< query_ptr > queries;
|
||||
QByteArray itemData = data->data( "application/tomahawk.mixed" );
|
||||
QDataStream stream( &itemData, QIODevice::ReadOnly );
|
||||
|
||||
QString mimeType;
|
||||
|
||||
while ( !stream.atEnd() )
|
||||
{
|
||||
stream >> mimeType;
|
||||
qDebug() << "mimetype is" << mimeType;
|
||||
|
||||
QByteArray singleData;
|
||||
QDataStream singleStream( &singleData, QIODevice::WriteOnly );
|
||||
|
||||
QMimeData singleMimeData;
|
||||
if ( mimeType == "application/tomahawk.query.list" || mimeType == "application/tomahawk.result.list" )
|
||||
{
|
||||
qlonglong query;
|
||||
stream >> query;
|
||||
singleStream << query;
|
||||
}
|
||||
else if ( mimeType == "application/tomahawk.metadata.album" )
|
||||
{
|
||||
QString artist;
|
||||
stream >> artist;
|
||||
singleStream << artist;
|
||||
QString album;
|
||||
stream >> album;
|
||||
singleStream << album;
|
||||
qDebug() << "got artist" << artist << "and album" << album;
|
||||
}
|
||||
else if ( mimeType == "application/tomahawk.metadata.artist" )
|
||||
{
|
||||
QString artist;
|
||||
stream >> artist;
|
||||
singleStream << artist;
|
||||
qDebug() << "got artist" << artist;
|
||||
}
|
||||
|
||||
singleMimeData.setData( mimeType, singleData );
|
||||
parseMimeData( &singleMimeData );
|
||||
}
|
||||
return queries;
|
||||
}
|
||||
|
||||
void
|
||||
DropJob::handleTrackUrls( const QString& urls )
|
||||
{
|
||||
if ( urls.contains( "open.spotify.com/track") ||
|
||||
urls.contains( "spotify:track" ) )
|
||||
{
|
||||
QStringList tracks = urls.split( "\n" );
|
||||
|
||||
tDebug() << "Got a list of spotify urls!" << tracks;
|
||||
SpotifyParser* spot = new SpotifyParser( tracks, this );
|
||||
connect( spot, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) );
|
||||
m_queryCount++;
|
||||
} else if ( urls.contains( "rdio.com" ) )
|
||||
{
|
||||
QStringList tracks = urls.split( "\n" );
|
||||
|
||||
tDebug() << "Got a list of rdio urls!" << tracks;
|
||||
RdioParser* rdio = new RdioParser( this );
|
||||
connect( rdio, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SLOT( onTracksAdded( QList< Tomahawk::query_ptr > ) ) );
|
||||
m_queryCount++;
|
||||
|
||||
rdio->parse( tracks );
|
||||
} else if ( urls.contains( "bit.ly" ) ||
|
||||
urls.contains( "j.mp" ) ||
|
||||
urls.contains( "t.co" ) ||
|
||||
urls.contains( "rd.io" ) )
|
||||
{
|
||||
QStringList tracks = urls.split( "\n" );
|
||||
|
||||
tDebug() << "Got a list of shortened urls!" << tracks;
|
||||
ShortenedLinkParser* parser = new ShortenedLinkParser( tracks, this );
|
||||
connect( parser, SIGNAL( urls( QStringList ) ), this, SLOT( expandedUrls( QStringList ) ) );
|
||||
m_queryCount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DropJob::expandedUrls( QStringList urls )
|
||||
{
|
||||
m_queryCount--;
|
||||
handleTrackUrls( urls.join( "\n" ) );
|
||||
}
|
||||
|
||||
void
|
||||
DropJob::onTracksAdded( const QList<Tomahawk::query_ptr>& tracksList )
|
||||
{
|
||||
m_resultList.append( tracksList );
|
||||
|
||||
if ( --m_queryCount == 0 )
|
||||
{
|
||||
if ( m_onlyLocal )
|
||||
removeRemoteSources();
|
||||
|
||||
if ( !m_allowDuplicates )
|
||||
removeDuplicates();
|
||||
|
||||
emit tracks( m_resultList );
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DropJob::removeDuplicates()
|
||||
{
|
||||
QList< Tomahawk::query_ptr > list;
|
||||
foreach ( const Tomahawk::query_ptr& item, m_resultList )
|
||||
{
|
||||
bool contains = false;
|
||||
foreach( const Tomahawk::query_ptr &tmpItem, list )
|
||||
if ( item->album() == tmpItem->album()
|
||||
&& item->artist() == tmpItem->artist()
|
||||
&& item->track() == tmpItem->track() )
|
||||
contains = true;
|
||||
if ( !contains )
|
||||
list.append( item );
|
||||
}
|
||||
m_resultList = list;
|
||||
}
|
||||
|
||||
void
|
||||
DropJob::removeRemoteSources()
|
||||
{
|
||||
QList< Tomahawk::query_ptr > list;
|
||||
foreach ( const Tomahawk::query_ptr& item, m_resultList )
|
||||
{
|
||||
bool hasLocalSource = false;
|
||||
foreach ( const Tomahawk::result_ptr& result, item->results() )
|
||||
{
|
||||
if ( !result->collection()->source().isNull() && result->collection()->source()->isLocal() )
|
||||
hasLocalSource = true;
|
||||
}
|
||||
if ( hasLocalSource )
|
||||
list.append( item );
|
||||
}
|
||||
m_resultList = list;
|
||||
}
|
||||
|
||||
void
|
||||
DropJob::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
|
||||
{
|
||||
if ( requestData.caller == "changeme" )
|
||||
{
|
||||
Tomahawk::InfoSystem::InfoCriteriaHash artistInfo;
|
||||
|
||||
artistInfo = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash >();
|
||||
|
||||
QString artist = artistInfo["artist"];
|
||||
|
||||
qDebug() << "Got requestData response for artist" << artist << output;
|
||||
|
||||
QList< query_ptr > results;
|
||||
|
||||
int i = 0;
|
||||
foreach ( const QVariant& title, output.toMap().value( "tracks" ).toList() )
|
||||
{
|
||||
qDebug() << "got title" << title;
|
||||
results << Query::get( artist, title.toString(), QString(), uuid() );
|
||||
|
||||
if ( ++i == 10 ) // Only getting top ten for now. Would make sense to make it configurable
|
||||
break;
|
||||
}
|
||||
|
||||
onTracksAdded( results );
|
||||
}
|
||||
}
|
||||
|
||||
QList< query_ptr >
|
||||
DropJob::getArtist( const QString &artist )
|
||||
{
|
||||
artist_ptr artistPtr = Artist::get( artist );
|
||||
if ( artistPtr->tracks().isEmpty() )
|
||||
{
|
||||
connect( artistPtr.data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr> ) ),
|
||||
SLOT( onTracksAdded( QList<Tomahawk::query_ptr> ) ) );
|
||||
m_queryCount++;
|
||||
return QList< query_ptr >();
|
||||
}
|
||||
else
|
||||
return artistPtr->tracks();
|
||||
}
|
||||
|
||||
QList< query_ptr >
|
||||
DropJob::getAlbum(const QString &artist, const QString &album)
|
||||
{
|
||||
artist_ptr artistPtr = Artist::get( artist );
|
||||
album_ptr albumPtr = Album::get( artistPtr, album );
|
||||
|
||||
if ( albumPtr.isNull() )
|
||||
return QList< query_ptr >();
|
||||
|
||||
if ( albumPtr->tracks().isEmpty() )
|
||||
{
|
||||
connect( albumPtr.data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr> ) ),
|
||||
SLOT( onTracksAdded( QList<Tomahawk::query_ptr> ) ) );
|
||||
m_queryCount++;
|
||||
return QList< query_ptr >();
|
||||
}
|
||||
else
|
||||
return albumPtr->tracks();
|
||||
}
|
||||
|
||||
void
|
||||
DropJob::getTopTen( const QString &artist )
|
||||
{
|
||||
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
|
||||
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
|
||||
|
||||
Tomahawk::InfoSystem::InfoCriteriaHash artistInfo;
|
||||
artistInfo["artist"] = artist;
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData;
|
||||
requestData.caller = "changeme";
|
||||
requestData.customData = QVariantMap();
|
||||
|
||||
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( artistInfo );
|
||||
|
||||
requestData.type = Tomahawk::InfoSystem::InfoArtistSongs;
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
|
||||
|
||||
m_queryCount++;
|
||||
|
||||
}
|
93
src/libtomahawk/dropjob.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2011, Michael Zanetti <mzanetti@kde.org>
|
||||
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef DROPJOB_H
|
||||
#define DROPJOB_H
|
||||
|
||||
#include "query.h"
|
||||
|
||||
#include "infosystem/infosystem.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
#include <QMimeData>
|
||||
|
||||
class DLLEXPORT DropJob : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DropJob( QObject *parent = 0 );
|
||||
~DropJob();
|
||||
|
||||
/**
|
||||
* QMimeData helpers
|
||||
*
|
||||
* Call this to parse the tracks in a QMimeData object to query_ptrs. This will parse internal tomahawk
|
||||
* data as well as all other formats supported (spotify, etc).
|
||||
*
|
||||
* Connect to tracks( QList< query_ptr> ); for the extracted tracks.
|
||||
*/
|
||||
static bool acceptsMimeData( const QMimeData* data, bool tracksOnly = true );
|
||||
static QStringList mimeTypes();
|
||||
|
||||
void setGetWholeArtists( bool getWholeArtists );
|
||||
void setGetWholeAlbums( bool getWholeAlbums );
|
||||
void tracksFromMimeData( const QMimeData* data, bool allowDuplicates = false, bool onlyLocal = false, bool top10 = false );
|
||||
|
||||
signals:
|
||||
/// QMimeData parsing results
|
||||
void tracks( const QList< Tomahawk::query_ptr >& tracks );
|
||||
|
||||
private slots:
|
||||
void expandedUrls( QStringList );
|
||||
|
||||
void onTracksAdded( const QList<Tomahawk::query_ptr>& );
|
||||
|
||||
void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
|
||||
|
||||
private:
|
||||
/// handle parsing mime data
|
||||
void parseMimeData( const QMimeData* data );
|
||||
|
||||
void handleTrackUrls( const QString& urls );
|
||||
QList< Tomahawk::query_ptr > tracksFromQueryList( const QMimeData* d );
|
||||
QList< Tomahawk::query_ptr > tracksFromResultList( const QMimeData* d );
|
||||
QList< Tomahawk::query_ptr > tracksFromArtistMetaData( const QMimeData* d );
|
||||
QList< Tomahawk::query_ptr > tracksFromAlbumMetaData( const QMimeData* d );
|
||||
QList< Tomahawk::query_ptr > tracksFromMixedData( const QMimeData* d );
|
||||
|
||||
QList< Tomahawk::query_ptr > getArtist( const QString& artist );
|
||||
QList< Tomahawk::query_ptr > getAlbum( const QString& artist, const QString& album );
|
||||
|
||||
void getTopTen( const QString& artist );
|
||||
|
||||
void removeDuplicates();
|
||||
void removeRemoteSources();
|
||||
|
||||
int m_queryCount;
|
||||
bool m_allowDuplicates;
|
||||
bool m_onlyLocal;
|
||||
bool m_getWholeArtists;
|
||||
bool m_getWholeAlbums;
|
||||
bool m_top10;
|
||||
|
||||
QList< Tomahawk::query_ptr > m_resultList;
|
||||
};
|
||||
|
||||
#endif // DROPJOB_H
|
@@ -64,7 +64,6 @@ GlobalActionManager::instance()
|
||||
GlobalActionManager::GlobalActionManager( QObject* parent )
|
||||
: QObject( parent )
|
||||
{
|
||||
m_mimeTypes << "application/tomahawk.query.list" << "application/tomahawk.plentry.list" << "application/tomahawk.result.list" << "text/plain";
|
||||
}
|
||||
|
||||
GlobalActionManager::~GlobalActionManager()
|
||||
@@ -358,6 +357,8 @@ GlobalActionManager::doQueueAdd( const QStringList& parts, const QList< QPair< Q
|
||||
|
||||
if( queueSpotify( parts, queryItems ) )
|
||||
return true;
|
||||
else if( queueRdio( parts, queryItems ) )
|
||||
return true;
|
||||
|
||||
QPair< QString, QString > pair;
|
||||
|
||||
@@ -428,6 +429,26 @@ GlobalActionManager::queueSpotify( const QStringList& , const QList< QPair< QStr
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GlobalActionManager::queueRdio( const QStringList& , const QList< QPair< QString, QString > >& queryItems )
|
||||
{
|
||||
QString url;
|
||||
|
||||
QPair< QString, QString > pair;
|
||||
foreach( pair, queryItems ) {
|
||||
if( pair.first == "rdioURL" )
|
||||
url = pair.second;
|
||||
else if( pair.first == "rdioURI" )
|
||||
url = pair.second;
|
||||
}
|
||||
|
||||
if( url.isEmpty() )
|
||||
return false;
|
||||
|
||||
openRdioLink( url );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GlobalActionManager::handleSearchCommand( const QUrl& url )
|
||||
@@ -446,7 +467,7 @@ GlobalActionManager::handleSearchCommand( const QUrl& url )
|
||||
return false;
|
||||
|
||||
ViewManager::instance()->showSuperCollection();
|
||||
ViewManager::instance()->topbar()->setFilter( queryStr );
|
||||
// ViewManager::instance()->topbar()->setFilter( queryStr );
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -618,6 +639,8 @@ GlobalActionManager::handlePlayCommand( const QUrl& url )
|
||||
if( parts[ 0 ] == "track" ) {
|
||||
if( playSpotify( url ) )
|
||||
return true;
|
||||
else if( playRdio( url ) )
|
||||
return true;
|
||||
|
||||
QPair< QString, QString > pair;
|
||||
QString title, artist, album, urlStr;
|
||||
@@ -653,13 +676,13 @@ GlobalActionManager::playSpotify( const QUrl& url )
|
||||
|
||||
QString spotifyUrl = url.hasQueryItem( "spotifyURI" ) ? url.queryItemValue( "spotifyURI" ) : url.queryItemValue( "spotifyURL" );
|
||||
SpotifyParser* p = new SpotifyParser( spotifyUrl, this );
|
||||
connect( p, SIGNAL( track( Tomahawk::query_ptr ) ), this, SLOT( spotifyToPlay( Tomahawk::query_ptr ) ) );
|
||||
connect( p, SIGNAL( track( Tomahawk::query_ptr ) ), this, SLOT( playNow( Tomahawk::query_ptr ) ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
GlobalActionManager::spotifyToPlay( const query_ptr& q )
|
||||
GlobalActionManager::playNow( const query_ptr& q )
|
||||
{
|
||||
Pipeline::instance()->resolve( q, true );
|
||||
|
||||
@@ -667,6 +690,21 @@ GlobalActionManager::spotifyToPlay( const query_ptr& q )
|
||||
connect( q.data(), SIGNAL( resolvingFinished( bool ) ), this, SLOT( waitingForResolved( bool ) ) );
|
||||
}
|
||||
|
||||
bool
|
||||
GlobalActionManager::playRdio( const QUrl& url )
|
||||
{
|
||||
if( !url.hasQueryItem( "rdioURI" ) && !url.hasQueryItem( "rdioURL" ) )
|
||||
return false;
|
||||
|
||||
|
||||
QString rdioUrl = url.hasQueryItem( "rdioURI" ) ? url.queryItemValue( "spotifyURI" ) : url.queryItemValue( "rdioURL" );
|
||||
RdioParser* p = new RdioParser( this );
|
||||
p->parse( rdioUrl );
|
||||
connect( p, SIGNAL( track( Tomahawk::query_ptr ) ), this, SLOT( playNow( Tomahawk::query_ptr ) ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool GlobalActionManager::handleBookmarkCommand(const QUrl& url)
|
||||
{
|
||||
@@ -779,149 +817,6 @@ GlobalActionManager::hostname() const
|
||||
return QString( "http://toma.hk" );
|
||||
}
|
||||
|
||||
/// QMIMEDATA HANDLING
|
||||
|
||||
QStringList
|
||||
GlobalActionManager::mimeTypes() const
|
||||
{
|
||||
return m_mimeTypes;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
GlobalActionManager::acceptsMimeData( const QMimeData* data, bool tracksOnly )
|
||||
{
|
||||
if ( data->hasFormat( "application/tomahawk.query.list" )
|
||||
|| data->hasFormat( "application/tomahawk.plentry.list" )
|
||||
|| data->hasFormat( "application/tomahawk.result.list" ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// crude check for spotify tracks
|
||||
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "spotify" ) &&
|
||||
( tracksOnly ? data->data( "text/plain" ).contains( "track" ) : true ) )
|
||||
return true;
|
||||
|
||||
// crude check for rdio tracks
|
||||
if ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "rdio.com" ) &&
|
||||
( tracksOnly ? data->data( "text/plain" ).contains( "track" ) : true ) )
|
||||
return true;
|
||||
|
||||
// We whitelist t.co and bit.ly (and j.mp) since they do some link checking. Often playable (e.g. spotify..) links hide behind them,
|
||||
// so we do an extra level of lookup
|
||||
if ( ( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "bit.ly" ) ) ||
|
||||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "j.mp" ) ) ||
|
||||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "t.co" ) ) ||
|
||||
( data->hasFormat( "text/plain" ) && data->data( "text/plain" ).contains( "rd.io" ) ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GlobalActionManager::tracksFromMimeData( const QMimeData* data )
|
||||
{
|
||||
if ( data->hasFormat( "application/tomahawk.query.list" ) )
|
||||
emit tracks( tracksFromQueryList( data ) );
|
||||
else if ( data->hasFormat( "application/tomahawk.result.list" ) )
|
||||
emit tracks( tracksFromResultList( data ) );
|
||||
else if ( data->hasFormat( "text/plain" ) )
|
||||
{
|
||||
QString plainData = QString::fromUtf8( data->data( "text/plain" ).constData() );
|
||||
tDebug() << "Got text/plain mime data:" << data->data( "text/plain" ) << "decoded to:" << plainData;
|
||||
handleTrackUrls ( plainData );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GlobalActionManager::handleTrackUrls( const QString& urls )
|
||||
{
|
||||
if ( urls.contains( "open.spotify.com/track") ||
|
||||
urls.contains( "spotify:track" ) )
|
||||
{
|
||||
QStringList tracks = urls.split( "\n" );
|
||||
|
||||
tDebug() << "Got a list of spotify urls!" << tracks;
|
||||
SpotifyParser* spot = new SpotifyParser( tracks, this );
|
||||
connect( spot, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ) );
|
||||
} else if ( urls.contains( "rdio.com" ) )
|
||||
{
|
||||
QStringList tracks = urls.split( "\n" );
|
||||
|
||||
tDebug() << "Got a list of rdio urls!" << tracks;
|
||||
RdioParser* rdio = new RdioParser( this );
|
||||
connect( rdio, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ), this, SIGNAL( tracks( QList<Tomahawk::query_ptr> ) ) );
|
||||
rdio->parse( tracks );
|
||||
} else if ( urls.contains( "bit.ly" ) ||
|
||||
urls.contains( "j.mp" ) ||
|
||||
urls.contains( "t.co" ) ||
|
||||
urls.contains( "rd.io" ) )
|
||||
{
|
||||
QStringList tracks = urls.split( "\n" );
|
||||
|
||||
tDebug() << "Got a list of shortened urls!" << tracks;
|
||||
ShortenedLinkParser* parser = new ShortenedLinkParser( tracks, this );
|
||||
connect( parser, SIGNAL( urls( QStringList ) ), this, SLOT( expandedUrls( QStringList ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GlobalActionManager::expandedUrls( QStringList urls )
|
||||
{
|
||||
handleTrackUrls( urls.join( "\n" ) );
|
||||
}
|
||||
|
||||
|
||||
QList< query_ptr >
|
||||
GlobalActionManager::tracksFromQueryList( const QMimeData* data )
|
||||
{
|
||||
QList< query_ptr > queries;
|
||||
QByteArray itemData = data->data( "application/tomahawk.query.list" );
|
||||
QDataStream stream( &itemData, QIODevice::ReadOnly );
|
||||
|
||||
while ( !stream.atEnd() )
|
||||
{
|
||||
qlonglong qptr;
|
||||
stream >> qptr;
|
||||
|
||||
query_ptr* query = reinterpret_cast<query_ptr*>(qptr);
|
||||
if ( query && !query->isNull() )
|
||||
{
|
||||
tDebug() << "Dropped query item:" << query->data()->artist() << "-" << query->data()->track();
|
||||
queries << *query;
|
||||
}
|
||||
}
|
||||
|
||||
return queries;
|
||||
}
|
||||
|
||||
QList< query_ptr >
|
||||
GlobalActionManager::tracksFromResultList( const QMimeData* data )
|
||||
{
|
||||
QList< query_ptr > queries;
|
||||
QByteArray itemData = data->data( "application/tomahawk.result.list" );
|
||||
QDataStream stream( &itemData, QIODevice::ReadOnly );
|
||||
|
||||
while ( !stream.atEnd() )
|
||||
{
|
||||
qlonglong qptr;
|
||||
stream >> qptr;
|
||||
|
||||
result_ptr* result = reinterpret_cast<result_ptr*>(qptr);
|
||||
if ( result && !result->isNull() )
|
||||
{
|
||||
tDebug() << "Dropped result item:" << result->data()->artist()->name() << "-" << result->data()->track();
|
||||
query_ptr q = result->data()->toQuery();
|
||||
q->addResults( QList< result_ptr >() << *result );
|
||||
queries << q;
|
||||
}
|
||||
}
|
||||
|
||||
return queries;
|
||||
}
|
||||
|
||||
/// SPOTIFY URL HANDLING
|
||||
|
||||
|
@@ -39,7 +39,7 @@ public:
|
||||
virtual ~GlobalActionManager();
|
||||
|
||||
QUrl openLinkFromQuery( const Tomahawk::query_ptr& query ) const;
|
||||
QUrl openLink( const QString& title, const QString& artist, const QString& album ) const;
|
||||
Q_INVOKABLE QUrl openLink( const QString& title, const QString& artist, const QString& album ) const;
|
||||
|
||||
/// Takes a spotify link and performs the default open action on it
|
||||
bool openSpotifyLink( const QString& link );
|
||||
@@ -51,18 +51,6 @@ public:
|
||||
QString copyPlaylistToClipboard( const Tomahawk::dynplaylist_ptr& playlist );
|
||||
void savePlaylistToFile( const Tomahawk::playlist_ptr& playlist, const QString& filename );
|
||||
|
||||
/**
|
||||
* QMimeData helpers
|
||||
*
|
||||
* Call this to parse the tracks in a QMimeData object to query_ptrs. This will parse internal tomahawk
|
||||
* data as well as all other formats supported (spotify, etc).
|
||||
*
|
||||
* Connect to tracks( QList< query_ptr> ); for the extracted tracks.
|
||||
*/
|
||||
bool acceptsMimeData( const QMimeData* data, bool tracksOnly = true );
|
||||
void tracksFromMimeData( const QMimeData* data );
|
||||
QStringList mimeTypes() const;
|
||||
|
||||
public slots:
|
||||
bool parseTomahawkLink( const QString& link );
|
||||
void waitingForResolved( bool );
|
||||
@@ -70,18 +58,14 @@ public slots:
|
||||
Tomahawk::dynplaylist_ptr loadDynamicPlaylist( const QUrl& url, bool station );
|
||||
|
||||
void handleOpenTrack( const Tomahawk::query_ptr& qry );
|
||||
signals:
|
||||
/// QMimeData parsing results
|
||||
void tracks( const QList< Tomahawk::query_ptr >& tracks );
|
||||
|
||||
private slots:
|
||||
void bookmarkPlaylistCreated( const Tomahawk::playlist_ptr& pl );
|
||||
void showPlaylist();
|
||||
|
||||
void xspfCreated( const QByteArray& xspf );
|
||||
void expandedUrls( QStringList );
|
||||
|
||||
void spotifyToPlay( const Tomahawk::query_ptr& );
|
||||
void playNow( const Tomahawk::query_ptr& );
|
||||
private:
|
||||
explicit GlobalActionManager( QObject* parent = 0 );
|
||||
void doBookmark( const Tomahawk::playlist_ptr& pl, const Tomahawk::query_ptr& q );
|
||||
@@ -100,11 +84,8 @@ private:
|
||||
|
||||
bool playSpotify( const QUrl& url );
|
||||
bool queueSpotify( const QStringList& parts, const QList< QPair< QString, QString > >& queryItems );
|
||||
|
||||
/// handle parsing mime data
|
||||
void handleTrackUrls( const QString& urls );
|
||||
QList< Tomahawk::query_ptr > tracksFromQueryList( const QMimeData* d );
|
||||
QList< Tomahawk::query_ptr > tracksFromResultList( const QMimeData* d );
|
||||
bool playRdio( const QUrl& url );
|
||||
bool queueRdio( const QStringList& parts, const QList< QPair< QString, QString > >& queryItems );
|
||||
|
||||
QString hostname() const;
|
||||
|
||||
@@ -112,7 +93,6 @@ private:
|
||||
Tomahawk::query_ptr m_waitingToBookmark;
|
||||
Tomahawk::query_ptr m_waitingToPlay;
|
||||
|
||||
QStringList m_mimeTypes;
|
||||
static GlobalActionManager* s_instance;
|
||||
};
|
||||
|
||||
|
@@ -20,22 +20,26 @@
|
||||
#include "ui_infobar.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QPixmap>
|
||||
|
||||
#include "viewmanager.h"
|
||||
#include "thirdparty/Qocoa/qsearchfield.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "utils/logger.h"
|
||||
|
||||
#define ANIMATION_TIME 400
|
||||
#define IMAGE_HEIGHT 64
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
InfoBar::InfoBar( QWidget* parent )
|
||||
: QWidget( parent )
|
||||
, ui( new Ui::InfoBar )
|
||||
{
|
||||
ui->setupUi( this );
|
||||
layout()->setSpacing( 0 );
|
||||
layout()->setContentsMargins( 0, 0, 0, 0 );
|
||||
TomahawkUtils::unmarginLayout( layout() );
|
||||
layout()->setContentsMargins( 8, 4, 8, 4 );
|
||||
|
||||
QFont boldFont = ui->captionLabel->font();
|
||||
boldFont.setPixelSize( 18 );
|
||||
@@ -66,7 +70,23 @@ InfoBar::InfoBar( QWidget* parent )
|
||||
ui->longDescriptionLabel->setText( QString() );
|
||||
ui->imageLabel->setText( QString() );
|
||||
|
||||
m_searchWidget = new QSearchField( this );
|
||||
m_searchWidget->setPlaceholderText( tr( "Filter..." ) );
|
||||
m_searchWidget->setMinimumWidth( 180 );
|
||||
connect( m_searchWidget, SIGNAL( textChanged( QString ) ), this, SLOT( onFilterEdited() ) );
|
||||
|
||||
ui->horizontalLayout->addWidget( m_searchWidget );
|
||||
|
||||
QLinearGradient gradient = QLinearGradient( QPoint( 0, 0 ), QPoint( 500, 200 ) ); //HACK
|
||||
gradient.setColorAt( 0.0, QColor( 100, 100, 100 ) );
|
||||
gradient.setColorAt( 0.8, QColor( 63, 63, 63 ) );
|
||||
|
||||
QPalette p = palette();
|
||||
p.setBrush( QPalette::Window, QBrush( gradient ) );
|
||||
setPalette( p );
|
||||
setAutoFillBackground( true );
|
||||
|
||||
connect( ViewManager::instance(), SIGNAL( filterAvailable( bool ) ), SLOT( setFilterAvailable( bool ) ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -114,6 +134,27 @@ InfoBar::setPixmap( const QPixmap& p )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoBar::setFilter( const QString& filter )
|
||||
{
|
||||
m_searchWidget->setText( filter );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoBar::setFilterAvailable( bool b )
|
||||
{
|
||||
m_searchWidget->setVisible( b );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoBar::onFilterEdited()
|
||||
{
|
||||
emit filterTextChanged( m_searchWidget->text() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoBar::changeEvent( QEvent* e )
|
||||
{
|
||||
@@ -128,18 +169,3 @@ InfoBar::changeEvent( QEvent* e )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoBar::resizeEvent( QResizeEvent* e )
|
||||
{
|
||||
QWidget::resizeEvent( e );
|
||||
|
||||
QLinearGradient gradient = QLinearGradient( contentsRect().topLeft(), contentsRect().bottomRight() );
|
||||
gradient.setColorAt( 0.0, QColor( 100, 100, 100 ) );
|
||||
gradient.setColorAt( 1.0, QColor( 63, 63, 63 ) );
|
||||
|
||||
QPalette p = palette();
|
||||
p.setBrush( QPalette::Window, QBrush( gradient ) );
|
||||
setPalette( p );
|
||||
}
|
@@ -22,6 +22,11 @@
|
||||
#include <QWidget>
|
||||
|
||||
#include "dllmacro.h"
|
||||
#include "query.h"
|
||||
|
||||
class QTimeLine;
|
||||
class QSearchField;
|
||||
class ContextWidget;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
@@ -42,12 +47,22 @@ public slots:
|
||||
void setLongDescription( const QString& s );
|
||||
void setPixmap( const QPixmap& p );
|
||||
|
||||
void setFilter( const QString& filter );
|
||||
void setFilterAvailable( bool b );
|
||||
|
||||
signals:
|
||||
void filterTextChanged( const QString& filter );
|
||||
|
||||
protected:
|
||||
void changeEvent( QEvent* e );
|
||||
void resizeEvent( QResizeEvent* e );
|
||||
|
||||
private slots:
|
||||
void onFilterEdited();
|
||||
|
||||
private:
|
||||
Ui::InfoBar* ui;
|
||||
|
||||
QSearchField* m_searchWidget;
|
||||
};
|
||||
|
||||
#endif // INFOBAR_H
|
182
src/libtomahawk/infobar/infobar.ui
Normal file
@@ -0,0 +1,182 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>InfoBar</class>
|
||||
<widget class="QWidget" name="InfoBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>774</width>
|
||||
<height>80</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>72</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>InfoBar</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="imageLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>64</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="ElidedLabel" name="captionLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="ElidedLabel" name="descriptionLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMaximumSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="ElidedLabel" name="longDescriptionLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>62</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>62</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>ElidedLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>widgets/elidedlabel.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@@ -22,6 +22,7 @@
|
||||
#include <QSettings>
|
||||
#include <QCryptographicHash>
|
||||
#include <QNetworkConfiguration>
|
||||
#include <QDomElement>
|
||||
|
||||
#include "album.h"
|
||||
#include "typedefs.h"
|
||||
@@ -33,6 +34,8 @@
|
||||
#include <lastfm/ws.h>
|
||||
#include <lastfm/XmlQuery>
|
||||
|
||||
#include <qjson/parser.h>
|
||||
|
||||
using namespace Tomahawk::InfoSystem;
|
||||
|
||||
static QString
|
||||
@@ -47,7 +50,7 @@ LastFmPlugin::LastFmPlugin()
|
||||
: InfoPlugin()
|
||||
, m_scrobbler( 0 )
|
||||
{
|
||||
m_supportedGetTypes << InfoAlbumCoverArt << InfoArtistImages << InfoArtistSimilars << InfoArtistSongs;
|
||||
m_supportedGetTypes << InfoAlbumCoverArt << InfoArtistImages << InfoArtistSimilars << InfoArtistSongs << InfoChart << InfoChartCapabilities;
|
||||
m_supportedPushTypes << InfoSubmitScrobble << InfoSubmitNowPlaying << InfoLove << InfoUnLove;
|
||||
|
||||
/*
|
||||
@@ -87,6 +90,7 @@ LastFmPlugin::~LastFmPlugin()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
delete m_scrobbler;
|
||||
m_scrobbler = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -147,6 +151,13 @@ LastFmPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData req
|
||||
fetchTopTracks( requestId, requestData );
|
||||
break;
|
||||
|
||||
case InfoChart:
|
||||
fetchChart( requestId, requestData );
|
||||
break;
|
||||
|
||||
case InfoChartCapabilities:
|
||||
fetchChartCapabilities( requestId, requestData );
|
||||
break;
|
||||
default:
|
||||
dataError( requestId, requestData );
|
||||
}
|
||||
@@ -298,6 +309,40 @@ LastFmPlugin::fetchTopTracks( uint requestId, Tomahawk::InfoSystem::InfoRequestD
|
||||
emit getCachedInfo( requestId, criteria, 2419200000, requestData );
|
||||
}
|
||||
|
||||
void
|
||||
LastFmPlugin::fetchChart( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoCriteriaHash >() )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
return;
|
||||
}
|
||||
InfoCriteriaHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash >();
|
||||
Tomahawk::InfoSystem::InfoCriteriaHash criteria;
|
||||
if ( !hash.contains( "chart_id" ) )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
return;
|
||||
} else {
|
||||
criteria["chart_id"] = hash["chart_id"];
|
||||
}
|
||||
|
||||
emit getCachedInfo( requestId, criteria, 0, requestData );
|
||||
}
|
||||
|
||||
void
|
||||
LastFmPlugin::fetchChartCapabilities( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
if ( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoCriteriaHash >() )
|
||||
{
|
||||
dataError( requestId, requestData );
|
||||
return;
|
||||
}
|
||||
InfoCriteriaHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash >();
|
||||
Tomahawk::InfoSystem::InfoCriteriaHash criteria;
|
||||
|
||||
emit getCachedInfo( requestId, criteria, 0, requestData );
|
||||
}
|
||||
|
||||
void
|
||||
LastFmPlugin::fetchCoverArt( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
@@ -356,6 +401,47 @@ LastFmPlugin::notInCacheSlot( uint requestId, QHash<QString, QString> criteria,
|
||||
|
||||
switch ( requestData.type )
|
||||
{
|
||||
case InfoChart:
|
||||
{
|
||||
tDebug() << "LastFmPlugin: InfoChart not in cache, fetching";
|
||||
QMap<QString, QString> args;
|
||||
tDebug() << "LastFmPlugin: " << "args chart_id" << criteria["chart_id"];
|
||||
args["method"] = criteria["chart_id"];
|
||||
args["limit"] = "100";
|
||||
QNetworkReply* reply = lastfm::ws::get(args);
|
||||
reply->setProperty( "requestId", requestId );
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
|
||||
connect( reply, SIGNAL( finished() ), SLOT( chartReturned() ) );
|
||||
return;
|
||||
}
|
||||
|
||||
case InfoChartCapabilities:
|
||||
{
|
||||
QList<Chart> track_charts;
|
||||
track_charts.append(Chart("chart.getTopTracks", "Top Tracks", "tracks"));
|
||||
track_charts.append(Chart("chart.getLovedTracks", "Loved Tracks", "tracks"));
|
||||
track_charts.append(Chart("chart.getHypedTracks", "Hyped Tracks", "tracks"));
|
||||
|
||||
QList<Chart> artist_charts;
|
||||
artist_charts.append(Chart("chart.getTopArtists", "Top Artists", "artists"));
|
||||
artist_charts.append(Chart("chart.getHypedArtists", "Hyped Artists", "artists"));
|
||||
|
||||
QVariantMap charts;
|
||||
charts.insert("Tracks", QVariant::fromValue<QList<Chart> >(track_charts));
|
||||
charts.insert("Artists", QVariant::fromValue<QList<Chart> >(artist_charts));
|
||||
|
||||
QVariantMap result;
|
||||
result.insert("Last.fm", QVariant::fromValue<QVariantMap>(charts));
|
||||
|
||||
emit info(
|
||||
requestId,
|
||||
requestData,
|
||||
result
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
case InfoArtistSimilars:
|
||||
{
|
||||
lastfm::Artist a( criteria["artist"] );
|
||||
@@ -447,6 +533,51 @@ LastFmPlugin::similarArtistsReturned()
|
||||
emit updateCache( criteria, 2419200000, requestData.type, returnedData );
|
||||
}
|
||||
|
||||
void
|
||||
LastFmPlugin::chartReturned()
|
||||
{
|
||||
tDebug() << "LastfmPlugin: InfoChart data returned!";
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
|
||||
|
||||
QVariantMap returnedData;
|
||||
const QRegExp tracks_rx( "chart\\.\\S+tracks\\S*", Qt::CaseInsensitive );
|
||||
const QRegExp artists_rx( "chart\\.\\S+artists\\S*", Qt::CaseInsensitive );
|
||||
const QString url = reply->url().toString();
|
||||
|
||||
if( url.contains( tracks_rx ) ) {
|
||||
QList<lastfm::Track> tracks = parseTrackList( reply );
|
||||
QList<ArtistTrackPair> top_tracks;
|
||||
foreach( const lastfm::Track &t, tracks ) {
|
||||
ArtistTrackPair pair;
|
||||
pair.artist = t.artist().toString();
|
||||
pair.track = t.title();
|
||||
top_tracks << pair;
|
||||
}
|
||||
tDebug() << "LastFmPlugin:" << "\tgot " << top_tracks.size() << " tracks";
|
||||
returnedData["tracks"] = QVariant::fromValue( top_tracks );
|
||||
returnedData["type"] = "tracks";
|
||||
|
||||
} else if( url.contains( artists_rx ) ) {
|
||||
QList<lastfm::Artist> list = lastfm::Artist::list( reply );
|
||||
QStringList al;
|
||||
tDebug() << "LastFmPlugin:"<< "\tgot " << list.size() << " artists";
|
||||
foreach ( const lastfm::Artist& a, list )
|
||||
al << a.toString();
|
||||
returnedData["artists"] = al;
|
||||
returnedData["type"] = "artists";
|
||||
} else {
|
||||
tDebug() << "LastfmPlugin:: got non tracks and non artists";
|
||||
}
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
|
||||
|
||||
emit info(
|
||||
reply->property( "requestId" ).toUInt(),
|
||||
requestData,
|
||||
returnedData
|
||||
);
|
||||
// TODO update cache
|
||||
}
|
||||
|
||||
void
|
||||
LastFmPlugin::topTracksReturned()
|
||||
@@ -468,7 +599,7 @@ LastFmPlugin::topTracksReturned()
|
||||
Tomahawk::InfoSystem::InfoCriteriaHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash>();
|
||||
Tomahawk::InfoSystem::InfoCriteriaHash criteria;
|
||||
criteria["artist"] = origData["artist"];
|
||||
emit updateCache( criteria, 2419200000, requestData.type, returnedData );
|
||||
emit updateCache( criteria, 0, requestData.type, returnedData );
|
||||
}
|
||||
|
||||
|
||||
@@ -604,7 +735,10 @@ LastFmPlugin::settingsChanged()
|
||||
m_pw = TomahawkSettings::instance()->lastFmPassword();
|
||||
// credentials have changed, have to re-create scrobbler for them to take effect
|
||||
if( m_scrobbler )
|
||||
{
|
||||
delete m_scrobbler;
|
||||
m_scrobbler = 0;
|
||||
}
|
||||
|
||||
createScrobbler();
|
||||
}
|
||||
@@ -675,3 +809,21 @@ LastFmPlugin::createScrobbler()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QList<lastfm::Track>
|
||||
LastFmPlugin::parseTrackList( QNetworkReply * reply )
|
||||
{
|
||||
QList<lastfm::Track> tracks;
|
||||
try {
|
||||
lastfm::XmlQuery lfm = lastfm::ws::parse(reply);
|
||||
foreach (lastfm::XmlQuery xq, lfm.children( "track" )) {
|
||||
tracks.append( lastfm::Track( xq ) );
|
||||
}
|
||||
}
|
||||
catch (lastfm::ws::ParseError& e)
|
||||
{
|
||||
qWarning() << e.what();
|
||||
}
|
||||
return tracks;
|
||||
}
|
||||
|
||||
|
@@ -52,6 +52,7 @@ public slots:
|
||||
void artistImagesReturned();
|
||||
void similarArtistsReturned();
|
||||
void topTracksReturned();
|
||||
void chartReturned();
|
||||
|
||||
void namChangedSlot( QNetworkAccessManager *nam );
|
||||
|
||||
@@ -66,6 +67,8 @@ private:
|
||||
void fetchArtistImages( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchSimilarArtists( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchTopTracks( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchChart( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchChartCapabilities( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
|
||||
void createScrobbler();
|
||||
void nowPlaying( const QVariant &input );
|
||||
@@ -74,6 +77,8 @@ private:
|
||||
|
||||
void dataError( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
|
||||
QList<lastfm::Track> parseTrackList( QNetworkReply * reply );
|
||||
|
||||
lastfm::MutableTrack m_track;
|
||||
lastfm::Audioscrobbler* m_scrobbler;
|
||||
QString m_pw;
|
||||
|
@@ -96,8 +96,6 @@ void
|
||||
AdiumPlugin::settingsChanged()
|
||||
{
|
||||
m_active = TomahawkSettings::instance()->nowPlayingEnabled();
|
||||
if( !m_active )
|
||||
setStatus( "" );
|
||||
}
|
||||
|
||||
|
||||
|
672
src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.cpp
Normal file
@@ -0,0 +1,672 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QApplication>
|
||||
#include <QImage>
|
||||
#include <QtDBus/QtDBus>
|
||||
|
||||
#include "audio/audioengine.h"
|
||||
#include "infosystem/infosystemworker.h"
|
||||
#include "album.h"
|
||||
#include "artist.h"
|
||||
#include "result.h"
|
||||
#include "tomahawksettings.h"
|
||||
#include "globalactionmanager.h"
|
||||
#include "utils/logger.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
|
||||
#include "mprisplugin.h"
|
||||
#include "mprispluginrootadaptor.h"
|
||||
#include "mprispluginplayeradaptor.h"
|
||||
|
||||
using namespace Tomahawk::InfoSystem;
|
||||
|
||||
static QString s_mpInfoIdentifier = QString( "MPRISPLUGIN" );
|
||||
|
||||
MprisPlugin::MprisPlugin()
|
||||
: InfoPlugin()
|
||||
, m_coverTempFile( 0 )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
// init
|
||||
m_playbackStatus = "Stopped";
|
||||
|
||||
// Types of pushInfo we care about
|
||||
m_supportedPushTypes << InfoNowPlaying << InfoNowPaused << InfoNowResumed << InfoNowStopped;
|
||||
|
||||
// DBus connection
|
||||
new MprisPluginRootAdaptor( this );
|
||||
new MprisPluginPlayerAdaptor( this );
|
||||
QDBusConnection dbus = QDBusConnection::sessionBus();
|
||||
dbus.registerObject("/org/mpris/MediaPlayer2", this);
|
||||
dbus.registerService("org.mpris.MediaPlayer2.tomahawk");
|
||||
|
||||
// Listen to volume changes
|
||||
connect( AudioEngine::instance(), SIGNAL( volumeChanged( int ) ),
|
||||
SLOT( onVolumeChanged( int ) ) );
|
||||
|
||||
// When the playlist changes, signals for several properties are sent
|
||||
connect( AudioEngine::instance(), SIGNAL( playlistChanged( Tomahawk::PlaylistInterface* ) ),
|
||||
SLOT( onPlaylistChanged( Tomahawk::PlaylistInterface* ) ) );
|
||||
|
||||
// When a track is added or removed, CanGoNext updated signal is sent
|
||||
PlaylistInterface *playlist = AudioEngine::instance()->playlist();
|
||||
if( playlist )
|
||||
connect( playlist->object(), SIGNAL( trackCountChanged( unsigned int ) ),
|
||||
SLOT( onTrackCountChanged( unsigned int ) ) );
|
||||
|
||||
// Connect to AudioEngine's seeked signal
|
||||
connect( AudioEngine::instance(), SIGNAL( seeked( qint64 ) ),
|
||||
SLOT( onSeeked( qint64 ) ) );
|
||||
|
||||
// Connect to the InfoSystem (we need to get album covers via getInfo)
|
||||
|
||||
connect( Tomahawk::InfoSystem::InfoSystem::instance(),
|
||||
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
SLOT( infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ) );
|
||||
|
||||
connect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ), SLOT( infoSystemFinished( QString ) ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
MprisPlugin::~MprisPlugin()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
delete m_coverTempFile;
|
||||
}
|
||||
|
||||
// org.mpris.MediaPlayer2
|
||||
|
||||
bool
|
||||
MprisPlugin::canQuit() const
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MprisPlugin::canRaise() const
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
MprisPlugin::hasTrackList() const
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
return false;
|
||||
}
|
||||
|
||||
QString
|
||||
MprisPlugin::identity() const
|
||||
{
|
||||
return QString("Tomahawk");
|
||||
}
|
||||
|
||||
QString
|
||||
MprisPlugin::desktopEntry() const
|
||||
{
|
||||
return QString("tomahawk");
|
||||
}
|
||||
|
||||
QStringList
|
||||
MprisPlugin::supportedUriSchemes() const
|
||||
{
|
||||
QStringList uriSchemes;
|
||||
uriSchemes << "tomahawk" << "spotify";
|
||||
return uriSchemes;
|
||||
}
|
||||
|
||||
QStringList
|
||||
MprisPlugin::supportedMimeTypes() const
|
||||
{
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::Raise()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::Quit()
|
||||
{
|
||||
QApplication::quit();
|
||||
}
|
||||
|
||||
// org.mpris.MediaPlayer2.Player
|
||||
|
||||
bool
|
||||
MprisPlugin::canControl() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MprisPlugin::canGoNext() const
|
||||
{
|
||||
return AudioEngine::instance()->canGoNext();
|
||||
}
|
||||
|
||||
bool
|
||||
MprisPlugin::canGoPrevious() const
|
||||
{
|
||||
return AudioEngine::instance()->canGoPrevious();
|
||||
}
|
||||
|
||||
bool
|
||||
MprisPlugin::canPause() const
|
||||
{
|
||||
return AudioEngine::instance()->currentTrack();
|
||||
}
|
||||
|
||||
bool
|
||||
MprisPlugin::canPlay() const
|
||||
{
|
||||
// If there is a currently playing track, or if there is a playlist with at least 1 track, you can hit play
|
||||
PlaylistInterface *p = AudioEngine::instance()->playlist();
|
||||
return AudioEngine::instance()->currentTrack() || ( p && p->trackCount() );
|
||||
}
|
||||
|
||||
bool
|
||||
MprisPlugin::canSeek() const
|
||||
{
|
||||
PlaylistInterface *p = AudioEngine::instance()->playlist();
|
||||
if (!p)
|
||||
return false;
|
||||
return p->seekRestrictions() != PlaylistInterface::NoSeek;
|
||||
|
||||
}
|
||||
|
||||
QString
|
||||
MprisPlugin::loopStatus() const
|
||||
{
|
||||
PlaylistInterface *p = AudioEngine::instance()->playlist();
|
||||
if (!p)
|
||||
return "None";
|
||||
PlaylistInterface::RepeatMode mode = p->repeatMode();
|
||||
switch( mode )
|
||||
{
|
||||
case PlaylistInterface::RepeatOne:
|
||||
return "Track";
|
||||
break;
|
||||
case PlaylistInterface::RepeatAll:
|
||||
return "Playlist";
|
||||
break;
|
||||
case PlaylistInterface::NoRepeat:
|
||||
return "None";
|
||||
break;
|
||||
default:
|
||||
return QString("None");
|
||||
break;
|
||||
}
|
||||
|
||||
return QString("None");
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::setLoopStatus( const QString &value )
|
||||
{
|
||||
PlaylistInterface *p = AudioEngine::instance()->playlist();
|
||||
if (!p)
|
||||
return;
|
||||
if( value == "Track")
|
||||
p->setRepeatMode( PlaylistInterface::RepeatOne );
|
||||
else if( value == "Playlist" )
|
||||
p->setRepeatMode( PlaylistInterface::RepeatAll );
|
||||
else if( value == "None" )
|
||||
p->setRepeatMode( PlaylistInterface::NoRepeat );
|
||||
}
|
||||
|
||||
double
|
||||
MprisPlugin::maximumRate() const
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
QVariantMap
|
||||
MprisPlugin::metadata() const
|
||||
{
|
||||
QVariantMap metadataMap;
|
||||
Tomahawk::result_ptr track = AudioEngine::instance()->currentTrack();
|
||||
if( track )
|
||||
{
|
||||
metadataMap.insert( "mpris:trackid", QString( "/track/" ) + track->id().replace( "-", "" ) );
|
||||
metadataMap.insert( "mpris:length", track->duration() );
|
||||
metadataMap.insert( "xesam:album", track->album()->name() );
|
||||
metadataMap.insert( "xesam:artist", track->artist()->name() );
|
||||
metadataMap.insert( "xesam:title", track->track() );
|
||||
|
||||
// Only return art if tempfile exists, and if its name contains the same "artist_album_tomahawk_cover.png"
|
||||
if( m_coverTempFile && m_coverTempFile->exists() &&
|
||||
m_coverTempFile->fileName().contains( track->artist()->name() + "_" + track->album()->name() + "_tomahawk_cover.png" ) )
|
||||
metadataMap.insert( "mpris:artUrl", QFileInfo( *m_coverTempFile ).absoluteFilePath() );
|
||||
else
|
||||
{
|
||||
// Need to fetch the album cover
|
||||
|
||||
Tomahawk::InfoSystem::InfoCriteriaHash trackInfo;
|
||||
trackInfo["artist"] = track->artist()->name();
|
||||
trackInfo["album"] = track->album()->name();
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData;
|
||||
requestData.caller = s_mpInfoIdentifier;
|
||||
requestData.type = Tomahawk::InfoSystem::InfoAlbumCoverArt;
|
||||
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo );
|
||||
requestData.customData = QVariantMap();
|
||||
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return metadataMap;
|
||||
}
|
||||
|
||||
double
|
||||
MprisPlugin::minimumRate() const
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
QString
|
||||
MprisPlugin::playbackStatus() const
|
||||
{
|
||||
return m_playbackStatus;
|
||||
}
|
||||
|
||||
qlonglong
|
||||
MprisPlugin::position() const
|
||||
{
|
||||
// Convert Tomahawk's milliseconds to microseconds
|
||||
return (qlonglong) ( AudioEngine::instance()->currentTime() * 1000 );
|
||||
}
|
||||
|
||||
double
|
||||
MprisPlugin::rate() const
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::setRate( double value )
|
||||
{
|
||||
Q_UNUSED( value );
|
||||
}
|
||||
|
||||
bool
|
||||
MprisPlugin::shuffle() const
|
||||
{
|
||||
PlaylistInterface *p = AudioEngine::instance()->playlist();
|
||||
if (!p)
|
||||
return false;
|
||||
return p->shuffled();
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::setShuffle( bool value )
|
||||
{
|
||||
PlaylistInterface *p = AudioEngine::instance()->playlist();
|
||||
if (!p)
|
||||
return;
|
||||
return p->setShuffled( value );
|
||||
}
|
||||
|
||||
double
|
||||
MprisPlugin::volume() const
|
||||
{
|
||||
return AudioEngine::instance()->volume();
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::setVolume( double value )
|
||||
{
|
||||
AudioEngine::instance()->setVolume( value );
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::Next()
|
||||
{
|
||||
AudioEngine::instance()->next();
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::OpenUri( const QString &Uri )
|
||||
{
|
||||
if( Uri.contains( "tomahawk://" ) )
|
||||
GlobalActionManager::instance()->parseTomahawkLink( Uri );
|
||||
else if( Uri.contains( "spotify:" ) )
|
||||
GlobalActionManager::instance()->openSpotifyLink( Uri );
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::Pause()
|
||||
{
|
||||
AudioEngine::instance()->pause();
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::Play()
|
||||
{
|
||||
AudioEngine::instance()->play();
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::PlayPause()
|
||||
{
|
||||
AudioEngine::instance()->playPause();
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::Previous()
|
||||
{
|
||||
AudioEngine::instance()->previous();
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::Seek( qlonglong Offset )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
if( !canSeek() )
|
||||
return;
|
||||
|
||||
qlonglong seekTime = position() + Offset;
|
||||
qDebug() << "seekTime: " << seekTime;
|
||||
if( seekTime < 0 )
|
||||
AudioEngine::instance()->seek( 0 );
|
||||
else if( seekTime > AudioEngine::instance()->currentTrackTotalTime()*1000 )
|
||||
Next();
|
||||
// seekTime is in microseconds, but we work internally in milliseconds
|
||||
else
|
||||
AudioEngine::instance()->seek( (qint64) ( seekTime / 1000 ) );
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::SetPosition( const QDBusObjectPath &TrackId, qlonglong Position )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if( !canSeek() )
|
||||
return;
|
||||
|
||||
qDebug() << "path: " << TrackId.path();
|
||||
qDebug() << "position: " << Position;
|
||||
|
||||
if( TrackId.path() != QString("/track/") + AudioEngine::instance()->currentTrack()->id().replace( "-", "" ) )
|
||||
return;
|
||||
|
||||
if( ( Position < 0) || ( Position > AudioEngine::instance()->currentTrackTotalTime()*1000 ) )
|
||||
return;
|
||||
|
||||
qDebug() << "seeking to: " << Position/1000 << "ms";
|
||||
|
||||
AudioEngine::instance()->seek( (qint64) (Position / 1000 ) );
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::Stop()
|
||||
{
|
||||
AudioEngine::instance()->stop();
|
||||
}
|
||||
|
||||
// InfoPlugin Methods
|
||||
|
||||
void
|
||||
MprisPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
bool isPlayingInfo = false;
|
||||
|
||||
switch ( type )
|
||||
{
|
||||
case InfoNowPlaying:
|
||||
isPlayingInfo = true;
|
||||
audioStarted( input );
|
||||
break;
|
||||
case InfoNowPaused:
|
||||
isPlayingInfo = true;
|
||||
audioPaused();
|
||||
break;
|
||||
case InfoNowResumed:
|
||||
isPlayingInfo = true;
|
||||
audioResumed( input );
|
||||
break;
|
||||
case InfoNowStopped:
|
||||
isPlayingInfo = true;
|
||||
audioStopped();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( isPlayingInfo )
|
||||
notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "PlaybackStatus");
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::stateChanged( AudioState newState, AudioState oldState )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/** Audio state slots */
|
||||
void
|
||||
MprisPlugin::audioStarted( const QVariant &input )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
if ( !input.canConvert< Tomahawk::InfoSystem::InfoCriteriaHash >() )
|
||||
return;
|
||||
|
||||
InfoCriteriaHash hash = input.value< Tomahawk::InfoSystem::InfoCriteriaHash >();
|
||||
if ( !hash.contains( "title" ) || !hash.contains( "artist" ) || !hash.contains( "album" ) )
|
||||
return;
|
||||
|
||||
m_playbackStatus = "Playing";
|
||||
notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Metadata");
|
||||
|
||||
//hash["artist"];
|
||||
//hash["title"];
|
||||
//QString nowPlaying = "";
|
||||
//qDebug() << "nowPlaying: " << nowPlaying;
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::audioFinished( const QVariant &input )
|
||||
{
|
||||
//qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::audioStopped()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
m_playbackStatus = "Stopped";
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::audioPaused()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
m_playbackStatus = "Paused";
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::audioResumed( const QVariant &input )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
audioStarted( input );
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::onVolumeChanged( int volume )
|
||||
{
|
||||
Q_UNUSED( volume );
|
||||
notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Volume");
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::onPlaylistChanged( Tomahawk::PlaylistInterface* playlist )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
disconnect( this, SLOT( onTrackCountChanged( unsigned int ) ) );
|
||||
qDebug() << "disconnected";
|
||||
if( playlist )
|
||||
qDebug() << "playlist not null";
|
||||
|
||||
if( playlist )
|
||||
connect( playlist->object(), SIGNAL( trackCountChanged( unsigned int ) ),
|
||||
SLOT( onTrackCountChanged( unsigned int ) ) );
|
||||
|
||||
qDebug() << "connected new playlist";
|
||||
|
||||
// Notify relevant changes
|
||||
notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "LoopStatus" );
|
||||
notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Shuffle" );
|
||||
notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "CanSeek" );
|
||||
onTrackCountChanged( 0 );
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::onTrackCountChanged( unsigned int tracks )
|
||||
{
|
||||
Q_UNUSED( tracks );
|
||||
notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "CanGoNext" );
|
||||
notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "CanGoPrevious" );
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::onSeeked( qint64 ms )
|
||||
{
|
||||
qlonglong us = (qlonglong) ( ms*1000 );
|
||||
emit Seeked( us );
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
|
||||
{
|
||||
// If the caller for the request was not us, or not the type of info we are seeking, ignore it
|
||||
if ( requestData.caller != s_mpInfoIdentifier || requestData.type != Tomahawk::InfoSystem::InfoAlbumCoverArt )
|
||||
{
|
||||
//notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Metadata" );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !output.canConvert< QVariantMap >() )
|
||||
{
|
||||
//notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Metadata" );
|
||||
tDebug( LOGINFO ) << "Cannot convert fetched art from a QByteArray";
|
||||
return;
|
||||
}
|
||||
|
||||
// Pull image data into byte array
|
||||
QVariantMap returnedData = output.value< QVariantMap >();
|
||||
const QByteArray ba = returnedData["imgbytes"].toByteArray();
|
||||
if ( ba.length() )
|
||||
{
|
||||
// Load from byte array to image
|
||||
QImage image;
|
||||
image.loadFromData( ba );
|
||||
|
||||
// Pull out request data for album+artist
|
||||
if( !requestData.input.canConvert< Tomahawk::InfoSystem::InfoCriteriaHash >() )
|
||||
{
|
||||
qDebug() << "Cannot convert metadata input to album cover retrieval";
|
||||
return;
|
||||
}
|
||||
|
||||
Tomahawk::InfoSystem::InfoCriteriaHash hash = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash>();
|
||||
|
||||
// delete the old tempfile and make new one, to avoid caching of filename by mpris clients
|
||||
if( m_coverTempFile )
|
||||
delete m_coverTempFile;
|
||||
m_coverTempFile = new QTemporaryFile( QDir::toNativeSeparators(
|
||||
QDir::tempPath() + "/" + hash["artist"] + "_" + hash["album"] + "_tomahawk_cover.png" ) );
|
||||
if( !m_coverTempFile->open() )
|
||||
{
|
||||
qDebug() << "WARNING: could not write temporary file for cover art!";
|
||||
}
|
||||
|
||||
// Finally, save the image to the new temp file
|
||||
//if( image.save( QFileInfo( *m_coverTempFile ).absoluteFilePath(), "PNG" ) )
|
||||
if( image.save( m_coverTempFile, "PNG") )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "Image saving successful, notifying";
|
||||
qDebug() << "Saving to: " << QFileInfo( *m_coverTempFile ).absoluteFilePath();
|
||||
m_coverTempFile->close();
|
||||
notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Metadata" );
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << " failed to save image!";
|
||||
m_coverTempFile->close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
if( m_coverTempFile->open() )
|
||||
{
|
||||
QTextStream out( m_coverTempFile );
|
||||
out << ba;
|
||||
m_coverTempFile->close();
|
||||
notifyPropertyChanged( "org.mpris.MediaPlayer2.Player", "Metadata" );
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MprisPlugin::infoSystemFinished( QString target )
|
||||
{
|
||||
Q_UNUSED( target );
|
||||
}
|
||||
|
||||
void
|
||||
MprisPlugin::notifyPropertyChanged( const QString& interface,
|
||||
const QString& propertyName )
|
||||
{
|
||||
QDBusMessage signal = QDBusMessage::createSignal(
|
||||
"/org/mpris/MediaPlayer2",
|
||||
"org.freedesktop.DBus.Properties",
|
||||
"PropertiesChanged");
|
||||
signal << interface;
|
||||
QVariantMap changedProps;
|
||||
changedProps.insert(propertyName, property(propertyName.toAscii()));
|
||||
signal << changedProps;
|
||||
signal << QStringList();
|
||||
QDBusConnection::sessionBus().send(signal);
|
||||
}
|
||||
|
182
src/libtomahawk/infosystem/infoplugins/unix/mprisplugin.h
Normal file
@@ -0,0 +1,182 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MPRISPLUGIN_H
|
||||
#define MPRISPLUGIN_H
|
||||
|
||||
#include "audio/audioengine.h"
|
||||
#include "infosystem/infosystem.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
#include <QtDBus/QtDBus>
|
||||
|
||||
namespace Tomahawk {
|
||||
|
||||
namespace InfoSystem {
|
||||
|
||||
class MprisPlugin : public InfoPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MprisPlugin();
|
||||
virtual ~MprisPlugin();
|
||||
|
||||
// MPRIS DBus Methods
|
||||
|
||||
// org.mpris.MediaPlayer2
|
||||
|
||||
Q_PROPERTY(bool CanQuit READ canQuit)
|
||||
bool canQuit() const;
|
||||
|
||||
Q_PROPERTY(bool CanRaise READ canRaise)
|
||||
bool canRaise() const;
|
||||
|
||||
Q_PROPERTY(QString DesktopEntry READ desktopEntry)
|
||||
QString desktopEntry() const;
|
||||
|
||||
Q_PROPERTY(bool HasTrackList READ hasTrackList)
|
||||
bool hasTrackList() const;
|
||||
|
||||
Q_PROPERTY(QString Identity READ identity)
|
||||
QString identity() const;
|
||||
|
||||
Q_PROPERTY(QStringList SupportedMimeTypes READ supportedMimeTypes)
|
||||
QStringList supportedMimeTypes() const;
|
||||
|
||||
Q_PROPERTY(QStringList SupportedUriSchemes READ supportedUriSchemes)
|
||||
QStringList supportedUriSchemes() const;
|
||||
|
||||
// org.mpris.MediaPlayer2.Player
|
||||
|
||||
Q_PROPERTY(bool CanControl READ canControl)
|
||||
bool canControl() const;
|
||||
|
||||
Q_PROPERTY(bool CanGoNext READ canGoNext)
|
||||
bool canGoNext() const;
|
||||
|
||||
Q_PROPERTY(bool CanGoPrevious READ canGoPrevious)
|
||||
bool canGoPrevious() const;
|
||||
|
||||
Q_PROPERTY(bool CanPause READ canPause)
|
||||
bool canPause() const;
|
||||
|
||||
Q_PROPERTY(bool CanPlay READ canPlay)
|
||||
bool canPlay() const;
|
||||
|
||||
Q_PROPERTY(bool CanSeek READ canSeek)
|
||||
bool canSeek() const;
|
||||
|
||||
Q_PROPERTY(QString LoopStatus READ loopStatus WRITE setLoopStatus)
|
||||
QString loopStatus() const;
|
||||
void setLoopStatus(const QString &value);
|
||||
|
||||
Q_PROPERTY(double MaximumRate READ maximumRate)
|
||||
double maximumRate() const;
|
||||
|
||||
Q_PROPERTY(QVariantMap Metadata READ metadata)
|
||||
QVariantMap metadata() const;
|
||||
|
||||
Q_PROPERTY(double MinimumRate READ minimumRate)
|
||||
double minimumRate() const;
|
||||
|
||||
Q_PROPERTY(QString PlaybackStatus READ playbackStatus)
|
||||
QString playbackStatus() const;
|
||||
|
||||
Q_PROPERTY(qlonglong Position READ position)
|
||||
qlonglong position() const;
|
||||
|
||||
Q_PROPERTY(double Rate READ rate WRITE setRate)
|
||||
double rate() const;
|
||||
void setRate(double value);
|
||||
|
||||
Q_PROPERTY(bool Shuffle READ shuffle WRITE setShuffle)
|
||||
bool shuffle() const;
|
||||
void setShuffle(bool value);
|
||||
|
||||
Q_PROPERTY(double Volume READ volume WRITE setVolume)
|
||||
double volume() const;
|
||||
void setVolume(double value);
|
||||
|
||||
public slots:
|
||||
void namChangedSlot( QNetworkAccessManager* /*nam*/ ) {} // unused
|
||||
|
||||
virtual void notInCacheSlot( uint requestId, const Tomahawk::InfoSystem::InfoCriteriaHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
{
|
||||
Q_UNUSED( requestId );
|
||||
Q_UNUSED( criteria );
|
||||
Q_UNUSED( requestData );
|
||||
}
|
||||
|
||||
// org.mpris.MediaPlayer2
|
||||
void Raise();
|
||||
void Quit();
|
||||
|
||||
// org.mpris.MediaPlayer2.Player
|
||||
void Next();
|
||||
void OpenUri(const QString &Uri);
|
||||
void Pause();
|
||||
void Play();
|
||||
void PlayPause();
|
||||
void Previous();
|
||||
void Seek(qlonglong Offset);
|
||||
void SetPosition(const QDBusObjectPath &TrackId, qlonglong Position);
|
||||
void Stop();
|
||||
|
||||
|
||||
protected slots:
|
||||
void getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input );
|
||||
|
||||
private slots:
|
||||
void stateChanged( AudioState newState, AudioState oldState );
|
||||
void onVolumeChanged( int volume );
|
||||
void onPlaylistChanged( Tomahawk::PlaylistInterface* playlist);
|
||||
void onTrackCountChanged( unsigned int tracks );
|
||||
void onSeeked( qint64 ms );
|
||||
|
||||
void infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
|
||||
void infoSystemFinished( QString target );
|
||||
|
||||
signals:
|
||||
void Seeked( qlonglong Position );
|
||||
|
||||
private:
|
||||
// Get Info
|
||||
|
||||
// Push Info
|
||||
void audioStarted( const QVariant &input );
|
||||
void audioFinished( const QVariant &input );
|
||||
void audioStopped();
|
||||
void audioPaused();
|
||||
void audioResumed( const QVariant &input );
|
||||
|
||||
// DBus
|
||||
void notifyPropertyChanged( const QString& interface, const QString& propertyName );
|
||||
QString m_playbackStatus;
|
||||
QTemporaryFile *m_coverTempFile;
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // MPRISPLUGIN_H
|
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* This file was generated by qdbusxml2cpp version 0.7
|
||||
* Command line was: qdbusxml2cpp -a mprispluginplayeradaptor -c MprisPluginPlayerAdaptor mprispluginplayeradaptor.xml
|
||||
*
|
||||
* qdbusxml2cpp is Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
*
|
||||
* This is an auto-generated file.
|
||||
* Do not edit! All changes made to it will be lost.
|
||||
*/
|
||||
|
||||
#include "mprispluginplayeradaptor.h"
|
||||
#include <QtCore/QMetaObject>
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
/*
|
||||
* Implementation of adaptor class MprisPluginPlayerAdaptor
|
||||
*/
|
||||
|
||||
MprisPluginPlayerAdaptor::MprisPluginPlayerAdaptor(QObject *parent)
|
||||
: QDBusAbstractAdaptor(parent)
|
||||
{
|
||||
// constructor
|
||||
setAutoRelaySignals(true);
|
||||
}
|
||||
|
||||
MprisPluginPlayerAdaptor::~MprisPluginPlayerAdaptor()
|
||||
{
|
||||
// destructor
|
||||
}
|
||||
|
||||
bool MprisPluginPlayerAdaptor::canControl() const
|
||||
{
|
||||
// get the value of property CanControl
|
||||
return qvariant_cast< bool >(parent()->property("CanControl"));
|
||||
}
|
||||
|
||||
bool MprisPluginPlayerAdaptor::canGoNext() const
|
||||
{
|
||||
// get the value of property CanGoNext
|
||||
return qvariant_cast< bool >(parent()->property("CanGoNext"));
|
||||
}
|
||||
|
||||
bool MprisPluginPlayerAdaptor::canGoPrevious() const
|
||||
{
|
||||
// get the value of property CanGoPrevious
|
||||
return qvariant_cast< bool >(parent()->property("CanGoPrevious"));
|
||||
}
|
||||
|
||||
bool MprisPluginPlayerAdaptor::canPause() const
|
||||
{
|
||||
// get the value of property CanPause
|
||||
return qvariant_cast< bool >(parent()->property("CanPause"));
|
||||
}
|
||||
|
||||
bool MprisPluginPlayerAdaptor::canPlay() const
|
||||
{
|
||||
// get the value of property CanPlay
|
||||
return qvariant_cast< bool >(parent()->property("CanPlay"));
|
||||
}
|
||||
|
||||
bool MprisPluginPlayerAdaptor::canSeek() const
|
||||
{
|
||||
// get the value of property CanSeek
|
||||
return qvariant_cast< bool >(parent()->property("CanSeek"));
|
||||
}
|
||||
|
||||
QString MprisPluginPlayerAdaptor::loopStatus() const
|
||||
{
|
||||
// get the value of property LoopStatus
|
||||
return qvariant_cast< QString >(parent()->property("LoopStatus"));
|
||||
}
|
||||
|
||||
void MprisPluginPlayerAdaptor::setLoopStatus(const QString &value)
|
||||
{
|
||||
// set the value of property LoopStatus
|
||||
parent()->setProperty("LoopStatus", qVariantFromValue(value));
|
||||
}
|
||||
|
||||
double MprisPluginPlayerAdaptor::maximumRate() const
|
||||
{
|
||||
// get the value of property MaximumRate
|
||||
return qvariant_cast< double >(parent()->property("MaximumRate"));
|
||||
}
|
||||
|
||||
QVariantMap MprisPluginPlayerAdaptor::metadata() const
|
||||
{
|
||||
// get the value of property Metadata
|
||||
return qvariant_cast< QVariantMap >(parent()->property("Metadata"));
|
||||
}
|
||||
|
||||
double MprisPluginPlayerAdaptor::minimumRate() const
|
||||
{
|
||||
// get the value of property MinimumRate
|
||||
return qvariant_cast< double >(parent()->property("MinimumRate"));
|
||||
}
|
||||
|
||||
QString MprisPluginPlayerAdaptor::playbackStatus() const
|
||||
{
|
||||
// get the value of property PlaybackStatus
|
||||
return qvariant_cast< QString >(parent()->property("PlaybackStatus"));
|
||||
}
|
||||
|
||||
qlonglong MprisPluginPlayerAdaptor::position() const
|
||||
{
|
||||
// get the value of property Position
|
||||
return qvariant_cast< qlonglong >(parent()->property("Position"));
|
||||
}
|
||||
|
||||
double MprisPluginPlayerAdaptor::rate() const
|
||||
{
|
||||
// get the value of property Rate
|
||||
return qvariant_cast< double >(parent()->property("Rate"));
|
||||
}
|
||||
|
||||
void MprisPluginPlayerAdaptor::setRate(double value)
|
||||
{
|
||||
// set the value of property Rate
|
||||
parent()->setProperty("Rate", qVariantFromValue(value));
|
||||
}
|
||||
|
||||
bool MprisPluginPlayerAdaptor::shuffle() const
|
||||
{
|
||||
// get the value of property Shuffle
|
||||
return qvariant_cast< bool >(parent()->property("Shuffle"));
|
||||
}
|
||||
|
||||
void MprisPluginPlayerAdaptor::setShuffle(bool value)
|
||||
{
|
||||
// set the value of property Shuffle
|
||||
parent()->setProperty("Shuffle", qVariantFromValue(value));
|
||||
}
|
||||
|
||||
double MprisPluginPlayerAdaptor::volume() const
|
||||
{
|
||||
// get the value of property Volume
|
||||
return qvariant_cast< double >(parent()->property("Volume"));
|
||||
}
|
||||
|
||||
void MprisPluginPlayerAdaptor::setVolume(double value)
|
||||
{
|
||||
// set the value of property Volume
|
||||
parent()->setProperty("Volume", qVariantFromValue(value));
|
||||
}
|
||||
|
||||
void MprisPluginPlayerAdaptor::Next()
|
||||
{
|
||||
// handle method call org.mpris.MediaPlayer2.Player.Next
|
||||
QMetaObject::invokeMethod(parent(), "Next");
|
||||
}
|
||||
|
||||
void MprisPluginPlayerAdaptor::OpenUri(const QString &Uri)
|
||||
{
|
||||
// handle method call org.mpris.MediaPlayer2.Player.OpenUri
|
||||
QMetaObject::invokeMethod(parent(), "OpenUri", Q_ARG(QString, Uri));
|
||||
}
|
||||
|
||||
void MprisPluginPlayerAdaptor::Pause()
|
||||
{
|
||||
// handle method call org.mpris.MediaPlayer2.Player.Pause
|
||||
QMetaObject::invokeMethod(parent(), "Pause");
|
||||
}
|
||||
|
||||
void MprisPluginPlayerAdaptor::Play()
|
||||
{
|
||||
// handle method call org.mpris.MediaPlayer2.Player.Play
|
||||
QMetaObject::invokeMethod(parent(), "Play");
|
||||
}
|
||||
|
||||
void MprisPluginPlayerAdaptor::PlayPause()
|
||||
{
|
||||
// handle method call org.mpris.MediaPlayer2.Player.PlayPause
|
||||
QMetaObject::invokeMethod(parent(), "PlayPause");
|
||||
}
|
||||
|
||||
void MprisPluginPlayerAdaptor::Previous()
|
||||
{
|
||||
// handle method call org.mpris.MediaPlayer2.Player.Previous
|
||||
QMetaObject::invokeMethod(parent(), "Previous");
|
||||
}
|
||||
|
||||
void MprisPluginPlayerAdaptor::Seek(qlonglong Offset)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
// handle method call org.mpris.MediaPlayer2.Player.Seek
|
||||
QMetaObject::invokeMethod(parent(), "Seek", Q_ARG(qlonglong, Offset));
|
||||
}
|
||||
|
||||
void MprisPluginPlayerAdaptor::SetPosition(const QDBusObjectPath &TrackId, qlonglong Position)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
// handle method call org.mpris.MediaPlayer2.Player.SetPosition
|
||||
QMetaObject::invokeMethod(parent(), "SetPosition", Q_ARG(QDBusObjectPath, TrackId), Q_ARG(qlonglong, Position));
|
||||
}
|
||||
|
||||
void MprisPluginPlayerAdaptor::Stop()
|
||||
{
|
||||
// handle method call org.mpris.MediaPlayer2.Player.Stop
|
||||
QMetaObject::invokeMethod(parent(), "Stop");
|
||||
}
|
||||
|
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* This file was generated by qdbusxml2cpp version 0.7
|
||||
* Command line was: qdbusxml2cpp -a mprispluginplayeradaptor -c MprisPluginPlayerAdaptor mprispluginplayeradaptor.xml
|
||||
*
|
||||
* qdbusxml2cpp is Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
*
|
||||
* This is an auto-generated file.
|
||||
* This file may have been hand-edited. Look for HAND-EDIT comments
|
||||
* before re-generating it.
|
||||
*/
|
||||
|
||||
#ifndef MPRISPLUGINPLAYERADAPTOR_H_1313089554
|
||||
#define MPRISPLUGINPLAYERADAPTOR_H_1313089554
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtDBus/QtDBus>
|
||||
class QByteArray;
|
||||
template<class T> class QList;
|
||||
template<class Key, class Value> class QMap;
|
||||
class QString;
|
||||
class QStringList;
|
||||
class QVariant;
|
||||
|
||||
/*
|
||||
* Adaptor class for interface org.mpris.MediaPlayer2.Player
|
||||
*/
|
||||
class MprisPluginPlayerAdaptor: public QDBusAbstractAdaptor
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.mpris.MediaPlayer2.Player")
|
||||
Q_CLASSINFO("D-Bus Introspection", ""
|
||||
" <interface name=\"org.mpris.MediaPlayer2.Player\">\n"
|
||||
" <method name=\"Next\"/>\n"
|
||||
" <method name=\"Previous\"/>\n"
|
||||
" <method name=\"Pause\"/>\n"
|
||||
" <method name=\"PlayPause\"/>\n"
|
||||
" <method name=\"Stop\"/>\n"
|
||||
" <method name=\"Play\"/>\n"
|
||||
" <method name=\"Seek\">\n"
|
||||
" <arg direction=\"in\" type=\"x\" name=\"Offset\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetPosition\">\n"
|
||||
" <arg direction=\"in\" type=\"o\" name=\"TrackId\"/>\n"
|
||||
" <arg direction=\"in\" type=\"x\" name=\"Position\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"OpenUri\">\n"
|
||||
" <arg direction=\"in\" type=\"s\" name=\"Uri\"/>\n"
|
||||
" </method>\n"
|
||||
" <signal name=\"Seeked\">\n"
|
||||
" <arg direction=\"out\" type=\"x\" name=\"Position\"/>\n"
|
||||
" </signal>\n"
|
||||
" <property access=\"read\" type=\"s\" name=\"PlaybackStatus\"/>\n"
|
||||
" <property access=\"readwrite\" type=\"s\" name=\"LoopStatus\"/>\n"
|
||||
" <property access=\"readwrite\" type=\"d\" name=\"Rate\"/>\n"
|
||||
" <property access=\"readwrite\" type=\"b\" name=\"Shuffle\"/>\n"
|
||||
" <property access=\"read\" type=\"a{sv}\" name=\"Metadata\">\n"
|
||||
" <annotation value=\"QVariantMap\" name=\"com.trolltech.QtDBus.QtTypeName\"/>\n"
|
||||
" </property>\n"
|
||||
" <property access=\"readwrite\" type=\"d\" name=\"Volume\"/>\n"
|
||||
" <property access=\"read\" type=\"x\" name=\"Position\"/>\n"
|
||||
" <property access=\"read\" type=\"d\" name=\"MinimumRate\"/>\n"
|
||||
" <property access=\"read\" type=\"d\" name=\"MaximumRate\"/>\n"
|
||||
" <property access=\"read\" type=\"b\" name=\"CanGoNext\"/>\n"
|
||||
" <property access=\"read\" type=\"b\" name=\"CanGoPrevious\"/>\n"
|
||||
" <property access=\"read\" type=\"b\" name=\"CanPlay\"/>\n"
|
||||
" <property access=\"read\" type=\"b\" name=\"CanPause\"/>\n"
|
||||
" <property access=\"read\" type=\"b\" name=\"CanSeek\"/>\n"
|
||||
" <property access=\"read\" type=\"b\" name=\"CanControl\"/>\n"
|
||||
" </interface>\n"
|
||||
"")
|
||||
public:
|
||||
MprisPluginPlayerAdaptor(QObject *parent);
|
||||
virtual ~MprisPluginPlayerAdaptor();
|
||||
|
||||
public: // PROPERTIES
|
||||
Q_PROPERTY(bool CanControl READ canControl)
|
||||
bool canControl() const;
|
||||
|
||||
Q_PROPERTY(bool CanGoNext READ canGoNext)
|
||||
bool canGoNext() const;
|
||||
|
||||
Q_PROPERTY(bool CanGoPrevious READ canGoPrevious)
|
||||
bool canGoPrevious() const;
|
||||
|
||||
Q_PROPERTY(bool CanPause READ canPause)
|
||||
bool canPause() const;
|
||||
|
||||
Q_PROPERTY(bool CanPlay READ canPlay)
|
||||
bool canPlay() const;
|
||||
|
||||
Q_PROPERTY(bool CanSeek READ canSeek)
|
||||
bool canSeek() const;
|
||||
|
||||
Q_PROPERTY(QString LoopStatus READ loopStatus WRITE setLoopStatus)
|
||||
QString loopStatus() const;
|
||||
void setLoopStatus(const QString &value);
|
||||
|
||||
Q_PROPERTY(double MaximumRate READ maximumRate)
|
||||
double maximumRate() const;
|
||||
|
||||
Q_PROPERTY(QVariantMap Metadata READ metadata)
|
||||
QVariantMap metadata() const;
|
||||
|
||||
Q_PROPERTY(double MinimumRate READ minimumRate)
|
||||
double minimumRate() const;
|
||||
|
||||
Q_PROPERTY(QString PlaybackStatus READ playbackStatus)
|
||||
QString playbackStatus() const;
|
||||
|
||||
Q_PROPERTY(qlonglong Position READ position)
|
||||
qlonglong position() const;
|
||||
|
||||
Q_PROPERTY(double Rate READ rate WRITE setRate)
|
||||
double rate() const;
|
||||
void setRate(double value);
|
||||
|
||||
Q_PROPERTY(bool Shuffle READ shuffle WRITE setShuffle)
|
||||
bool shuffle() const;
|
||||
void setShuffle(bool value);
|
||||
|
||||
Q_PROPERTY(double Volume READ volume WRITE setVolume)
|
||||
double volume() const;
|
||||
void setVolume(double value);
|
||||
|
||||
public Q_SLOTS: // METHODS
|
||||
void Next();
|
||||
void OpenUri(const QString &Uri);
|
||||
void Pause();
|
||||
void Play();
|
||||
void PlayPause();
|
||||
void Previous();
|
||||
void Seek(qlonglong Offset);
|
||||
void SetPosition(const QDBusObjectPath &TrackId, qlonglong Position);
|
||||
void Stop();
|
||||
Q_SIGNALS: // SIGNALS
|
||||
void Seeked(qlonglong Position);
|
||||
};
|
||||
|
||||
#endif
|
@@ -0,0 +1,41 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.mpris.MediaPlayer2.Player">
|
||||
<method name="Next"/>
|
||||
<method name="Previous"/>
|
||||
<method name="Pause"/>
|
||||
<method name="PlayPause"/>
|
||||
<method name="Stop"/>
|
||||
<method name="Play"/>
|
||||
<method name="Seek">
|
||||
<arg type="x" name="Offset" direction="in" />
|
||||
</method>
|
||||
<method name="SetPosition">
|
||||
<arg type="o" name="TrackId" direction="in" />
|
||||
<arg type="x" name="Position" direction="in" />
|
||||
</method>
|
||||
<method name="OpenUri">
|
||||
<arg type="s" name="Uri" direction="in" />
|
||||
</method>
|
||||
<signal name="Seeked">
|
||||
<arg type="x" name="Position" direction="out" />
|
||||
</signal>
|
||||
<property name="PlaybackStatus" type="s" access="read"/>
|
||||
<property name="LoopStatus" type="s" access="readwrite"/>
|
||||
<property name="Rate" type="d" access="readwrite"/>
|
||||
<property name="Shuffle" type="b" access="readwrite"/>
|
||||
<property name="Metadata" type="a{sv}" access="read">
|
||||
<annotation name="com.trolltech.QtDBus.QtTypeName" value="QVariantMap"/>
|
||||
</property>
|
||||
<property name="Volume" type="d" access="readwrite"/>
|
||||
<property name="Position" type="x" access="read"/>
|
||||
<property name="MinimumRate" type="d" access="read"/>
|
||||
<property name="MaximumRate" type="d" access="read"/>
|
||||
<property name="CanGoNext" type="b" access="read"/>
|
||||
<property name="CanGoPrevious" type="b" access="read"/>
|
||||
<property name="CanPlay" type="b" access="read"/>
|
||||
<property name="CanPause" type="b" access="read"/>
|
||||
<property name="CanSeek" type="b" access="read"/>
|
||||
<property name="CanControl" type="b" access="read"/>
|
||||
</interface>
|
||||
</node>
|
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* This file was generated by qdbusxml2cpp version 0.7
|
||||
* Command line was: qdbusxml2cpp -a mprispluginrootadaptor -c MprisPluginRootAdaptor mprispluginrootadaptor.xml
|
||||
*
|
||||
* qdbusxml2cpp is Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
*
|
||||
* This is an auto-generated file.
|
||||
* Do not edit! All changes made to it will be lost.
|
||||
*/
|
||||
|
||||
#include "mprispluginrootadaptor.h"
|
||||
#include <QtCore/QMetaObject>
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
/*
|
||||
* Implementation of adaptor class MprisPluginRootAdaptor
|
||||
*/
|
||||
|
||||
MprisPluginRootAdaptor::MprisPluginRootAdaptor(QObject *parent)
|
||||
: QDBusAbstractAdaptor(parent)
|
||||
{
|
||||
// constructor
|
||||
setAutoRelaySignals(true);
|
||||
}
|
||||
|
||||
MprisPluginRootAdaptor::~MprisPluginRootAdaptor()
|
||||
{
|
||||
// destructor
|
||||
}
|
||||
|
||||
bool MprisPluginRootAdaptor::canQuit() const
|
||||
{
|
||||
// get the value of property CanQuit
|
||||
return qvariant_cast< bool >(parent()->property("CanQuit"));
|
||||
}
|
||||
|
||||
bool MprisPluginRootAdaptor::canRaise() const
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
// get the value of property CanRaise
|
||||
bool ret = qvariant_cast< bool >(parent()->property("CanRaise"));
|
||||
qDebug() << "ret: " << ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString MprisPluginRootAdaptor::desktopEntry() const
|
||||
{
|
||||
// get the value of property DesktopEntry
|
||||
return qvariant_cast< QString >(parent()->property("DesktopEntry"));
|
||||
}
|
||||
|
||||
bool MprisPluginRootAdaptor::hasTrackList() const
|
||||
{
|
||||
// get the value of property HasTrackList
|
||||
return qvariant_cast< bool >(parent()->property("HasTrackList"));
|
||||
}
|
||||
|
||||
QString MprisPluginRootAdaptor::identity() const
|
||||
{
|
||||
// get the value of property Identity
|
||||
return qvariant_cast< QString >(parent()->property("Identity"));
|
||||
}
|
||||
|
||||
QStringList MprisPluginRootAdaptor::supportedMimeTypes() const
|
||||
{
|
||||
// get the value of property SupportedMimeTypes
|
||||
return qvariant_cast< QStringList >(parent()->property("SupportedMimeTypes"));
|
||||
}
|
||||
|
||||
QStringList MprisPluginRootAdaptor::supportedUriSchemes() const
|
||||
{
|
||||
// get the value of property SupportedUriSchemes
|
||||
return qvariant_cast< QStringList >(parent()->property("SupportedUriSchemes"));
|
||||
}
|
||||
|
||||
void MprisPluginRootAdaptor::Quit()
|
||||
{
|
||||
// handle method call org.mpris.MediaPlayer2.Quit
|
||||
QMetaObject::invokeMethod(parent(), "Quit");
|
||||
}
|
||||
|
||||
void MprisPluginRootAdaptor::Raise()
|
||||
{
|
||||
// handle method call org.mpris.MediaPlayer2.Raise
|
||||
QMetaObject::invokeMethod(parent(), "Raise");
|
||||
}
|
||||
|
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* This file was generated by qdbusxml2cpp version 0.7
|
||||
* Command line was: qdbusxml2cpp -a mprispluginrootadaptor -c MprisPluginRootAdaptor mprispluginrootadaptor.xml
|
||||
*
|
||||
* qdbusxml2cpp is Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||||
*
|
||||
* This is an auto-generated file.
|
||||
* This file may have been hand-edited. Look for HAND-EDIT comments
|
||||
* before re-generating it.
|
||||
*/
|
||||
|
||||
#ifndef MPRISPLUGINROOTADAPTOR_H_1312900930
|
||||
#define MPRISPLUGINROOTADAPTOR_H_1312900930
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtDBus/QtDBus>
|
||||
class QByteArray;
|
||||
template<class T> class QList;
|
||||
template<class Key, class Value> class QMap;
|
||||
class QString;
|
||||
class QStringList;
|
||||
class QVariant;
|
||||
|
||||
/*
|
||||
* Adaptor class for interface org.mpris.MediaPlayer2
|
||||
*/
|
||||
class MprisPluginRootAdaptor: public QDBusAbstractAdaptor
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.mpris.MediaPlayer2")
|
||||
Q_CLASSINFO("D-Bus Introspection", ""
|
||||
" <interface name=\"org.mpris.MediaPlayer2\">\n"
|
||||
" <method name=\"Raise\"/>\n"
|
||||
" <method name=\"Quit\"/>\n"
|
||||
" <property access=\"read\" type=\"b\" name=\"CanQuit\"/>\n"
|
||||
" <property access=\"read\" type=\"b\" name=\"CanRaise\"/>\n"
|
||||
" <property access=\"read\" type=\"b\" name=\"HasTrackList\"/>\n"
|
||||
" <property access=\"read\" type=\"s\" name=\"Identity\"/>\n"
|
||||
" <property access=\"read\" type=\"s\" name=\"DesktopEntry\"/>\n"
|
||||
" <property access=\"read\" type=\"as\" name=\"SupportedUriSchemes\"/>\n"
|
||||
" <property access=\"read\" type=\"as\" name=\"SupportedMimeTypes\"/>\n"
|
||||
" </interface>\n"
|
||||
"")
|
||||
public:
|
||||
MprisPluginRootAdaptor(QObject *parent);
|
||||
virtual ~MprisPluginRootAdaptor();
|
||||
|
||||
public: // PROPERTIES
|
||||
Q_PROPERTY(bool CanQuit READ canQuit)
|
||||
bool canQuit() const;
|
||||
|
||||
Q_PROPERTY(bool CanRaise READ canRaise)
|
||||
bool canRaise() const;
|
||||
|
||||
Q_PROPERTY(QString DesktopEntry READ desktopEntry)
|
||||
QString desktopEntry() const;
|
||||
|
||||
Q_PROPERTY(bool HasTrackList READ hasTrackList)
|
||||
bool hasTrackList() const;
|
||||
|
||||
Q_PROPERTY(QString Identity READ identity)
|
||||
QString identity() const;
|
||||
|
||||
Q_PROPERTY(QStringList SupportedMimeTypes READ supportedMimeTypes)
|
||||
QStringList supportedMimeTypes() const;
|
||||
|
||||
Q_PROPERTY(QStringList SupportedUriSchemes READ supportedUriSchemes)
|
||||
QStringList supportedUriSchemes() const;
|
||||
|
||||
public Q_SLOTS: // METHODS
|
||||
void Quit();
|
||||
void Raise();
|
||||
Q_SIGNALS: // SIGNALS
|
||||
};
|
||||
|
||||
#endif
|
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.mpris.MediaPlayer2">
|
||||
<method name="Raise"/>
|
||||
<method name="Quit"/>
|
||||
<property name="CanQuit" type="b" access="read"/>
|
||||
<property name="CanRaise" type="b" access="read"/>
|
||||
<property name="HasTrackList" type="b" access="read"/>
|
||||
<property name="Identity" type="s" access="read"/>
|
||||
<property name="DesktopEntry" type="s" access="read"/>
|
||||
<property name="SupportedUriSchemes" type="as" access="read"/>
|
||||
<property name="SupportedMimeTypes" type="as" access="read"/>
|
||||
</interface>
|
||||
</node>
|
@@ -58,14 +58,16 @@ InfoSystem::InfoSystem( QObject *parent )
|
||||
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
m_infoSystemCacheThreadController = new QThread( this );
|
||||
m_infoSystemCacheThreadController = new InfoSystemCacheThread( this );
|
||||
m_cache = QWeakPointer< InfoSystemCache >( new InfoSystemCache() );
|
||||
m_cache.data()->moveToThread( m_infoSystemCacheThreadController );
|
||||
m_infoSystemCacheThreadController->setCache( m_cache );
|
||||
m_infoSystemCacheThreadController->start( QThread::IdlePriority );
|
||||
|
||||
m_infoSystemWorkerThreadController = new QThread( this );
|
||||
m_worker = QWeakPointer< InfoSystemWorker>( new InfoSystemWorker() );
|
||||
m_infoSystemWorkerThreadController = new InfoSystemWorkerThread( this );
|
||||
m_worker = QWeakPointer< InfoSystemWorker >( new InfoSystemWorker() );
|
||||
m_worker.data()->moveToThread( m_infoSystemWorkerThreadController );
|
||||
m_infoSystemWorkerThreadController->setWorker( m_worker );
|
||||
m_infoSystemWorkerThreadController->start();
|
||||
|
||||
QMetaObject::invokeMethod( m_worker.data(), "init", Qt::QueuedConnection, Q_ARG( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache >, m_cache ) );
|
||||
@@ -89,7 +91,7 @@ InfoSystem::~InfoSystem()
|
||||
m_infoSystemWorkerThreadController->quit();
|
||||
m_infoSystemWorkerThreadController->wait( 60000 );
|
||||
|
||||
delete m_worker.data();
|
||||
//delete m_worker.data();
|
||||
delete m_infoSystemWorkerThreadController;
|
||||
m_infoSystemWorkerThreadController = 0;
|
||||
}
|
||||
@@ -100,7 +102,7 @@ InfoSystem::~InfoSystem()
|
||||
m_infoSystemCacheThreadController->quit();
|
||||
m_infoSystemCacheThreadController->wait( 60000 );
|
||||
|
||||
delete m_cache.data();
|
||||
//delete m_cache.data();
|
||||
delete m_infoSystemCacheThreadController;
|
||||
m_infoSystemCacheThreadController = 0;
|
||||
}
|
||||
@@ -118,15 +120,15 @@ InfoSystem::newNam() const
|
||||
|
||||
|
||||
void
|
||||
InfoSystem::getInfo( const InfoRequestData &requestData, uint timeoutMillis )
|
||||
InfoSystem::getInfo( const InfoRequestData &requestData, uint timeoutMillis, bool allSources )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
QMetaObject::invokeMethod( m_worker.data(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ), Q_ARG( uint, timeoutMillis ) );
|
||||
QMetaObject::invokeMethod( m_worker.data(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ), Q_ARG( uint, timeoutMillis ), Q_ARG( bool, allSources ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoSystem::getInfo( const QString &caller, const InfoTypeMap &inputMap, const QVariantMap &customData, const InfoTimeoutMap &timeoutMap )
|
||||
InfoSystem::getInfo( const QString &caller, const InfoTypeMap &inputMap, const QVariantMap &customData, const InfoTimeoutMap &timeoutMap, bool allSources )
|
||||
{
|
||||
InfoRequestData requestData;
|
||||
requestData.caller = caller;
|
||||
@@ -135,7 +137,7 @@ InfoSystem::getInfo( const QString &caller, const InfoTypeMap &inputMap, const Q
|
||||
{
|
||||
requestData.type = type;
|
||||
requestData.input = inputMap[ type ];
|
||||
QMetaObject::invokeMethod( m_worker.data(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ), Q_ARG( uint, ( timeoutMap.contains( type ) ? timeoutMap[ type ] : 0 ) ) );
|
||||
QMetaObject::invokeMethod( m_worker.data(), "getInfo", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ), Q_ARG( uint, ( timeoutMap.contains( type ) ? timeoutMap[ type ] : 0 ) ), Q_ARG( bool, allSources ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,6 +157,65 @@ InfoSystem::pushInfo( const QString &caller, const InfoTypeMap &input )
|
||||
QMetaObject::invokeMethod( m_worker.data(), "pushInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input[ type ] ) );
|
||||
}
|
||||
|
||||
|
||||
InfoSystemCacheThread::InfoSystemCacheThread( QObject *parent )
|
||||
: QThread( parent )
|
||||
{
|
||||
}
|
||||
|
||||
InfoSystemCacheThread::~InfoSystemCacheThread()
|
||||
{
|
||||
delete m_cache.data();
|
||||
}
|
||||
|
||||
void
|
||||
InfoSystemCacheThread::InfoSystemCacheThread::run()
|
||||
{
|
||||
exec();
|
||||
}
|
||||
|
||||
QWeakPointer< InfoSystemCache >
|
||||
InfoSystemCacheThread::cache() const
|
||||
{
|
||||
return m_cache;
|
||||
}
|
||||
|
||||
void
|
||||
InfoSystemCacheThread::setCache( QWeakPointer< InfoSystemCache > cache )
|
||||
{
|
||||
m_cache = cache;
|
||||
}
|
||||
|
||||
InfoSystemWorkerThread::InfoSystemWorkerThread( QObject *parent )
|
||||
: QThread( parent )
|
||||
{
|
||||
}
|
||||
|
||||
InfoSystemWorkerThread::~InfoSystemWorkerThread()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
InfoSystemWorkerThread::InfoSystemWorkerThread::run()
|
||||
{
|
||||
exec();
|
||||
if( m_worker )
|
||||
delete m_worker.data();
|
||||
}
|
||||
|
||||
QWeakPointer< InfoSystemWorker >
|
||||
InfoSystemWorkerThread::worker() const
|
||||
{
|
||||
return m_worker;
|
||||
}
|
||||
|
||||
void
|
||||
InfoSystemWorkerThread::setWorker( QWeakPointer< InfoSystemWorker > worker )
|
||||
{
|
||||
m_worker = worker;
|
||||
}
|
||||
|
||||
|
||||
} //namespace InfoSystem
|
||||
|
||||
} //namespace Tomahawk
|
||||
|
@@ -92,6 +92,18 @@ enum InfoType { // as items are saved in cache, mark them here to not change the
|
||||
InfoAlbumComposer = 48,
|
||||
InfoAlbumSongs = 49,
|
||||
|
||||
/** \var Tomahawk::InfoSystem::InfoType Tomahawk::InfoSystem::InfoType::InfoChartCapabilities
|
||||
* Documentation for InfoChartCapabilities
|
||||
*
|
||||
* Clients of this InfoType expect a QVariant
|
||||
*
|
||||
*/
|
||||
InfoChartCapabilities = 50,
|
||||
/**
|
||||
* Documentation for InfoChartArtists
|
||||
*/
|
||||
InfoChart = 51,
|
||||
|
||||
InfoMiscTopHotttness = 60,
|
||||
InfoMiscTopTerms = 61,
|
||||
|
||||
@@ -103,7 +115,6 @@ enum InfoType { // as items are saved in cache, mark them here to not change the
|
||||
InfoNowResumed = 82,
|
||||
InfoNowStopped = 83,
|
||||
|
||||
|
||||
InfoLove = 90,
|
||||
InfoUnLove = 91,
|
||||
|
||||
@@ -119,6 +130,23 @@ struct InfoRequestData {
|
||||
QVariantMap customData;
|
||||
};
|
||||
|
||||
struct ArtistTrackPair {
|
||||
QString artist;
|
||||
QString track;
|
||||
};
|
||||
|
||||
struct Chart {
|
||||
Chart(){}
|
||||
Chart(const QString _id, const QString _label, const QString _type) {
|
||||
id = _id;
|
||||
label = _label;
|
||||
type = _type;
|
||||
}
|
||||
QString id;
|
||||
QString label;
|
||||
QString type;
|
||||
};
|
||||
|
||||
typedef QMap< InfoType, QVariant > InfoTypeMap;
|
||||
typedef QMap< InfoType, uint > InfoTimeoutMap;
|
||||
typedef QMap< QString, QMap< QString, QString > > InfoGenericMap;
|
||||
@@ -160,6 +188,38 @@ private:
|
||||
|
||||
typedef QWeakPointer< InfoPlugin > InfoPluginPtr;
|
||||
|
||||
class InfoSystemCacheThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
InfoSystemCacheThread( QObject *parent );
|
||||
virtual ~InfoSystemCacheThread();
|
||||
|
||||
void run();
|
||||
QWeakPointer< InfoSystemCache > cache() const;
|
||||
void setCache( QWeakPointer< InfoSystemCache > cache );
|
||||
|
||||
private:
|
||||
QWeakPointer< InfoSystemCache > m_cache;
|
||||
};
|
||||
|
||||
class InfoSystemWorkerThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
InfoSystemWorkerThread( QObject *parent );
|
||||
virtual ~InfoSystemWorkerThread();
|
||||
|
||||
void run();
|
||||
QWeakPointer< InfoSystemWorker > worker() const;
|
||||
void setWorker( QWeakPointer< InfoSystemWorker > worker );
|
||||
|
||||
private:
|
||||
QWeakPointer< InfoSystemWorker > m_worker;
|
||||
};
|
||||
|
||||
class DLLEXPORT InfoSystem : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -170,9 +230,9 @@ public:
|
||||
InfoSystem( QObject *parent );
|
||||
~InfoSystem();
|
||||
|
||||
void getInfo( const InfoRequestData &requestData, uint timeoutMillis = 0 );
|
||||
void getInfo( const InfoRequestData &requestData, uint timeoutMillis = 0, bool allSources = false );
|
||||
//WARNING: if changing timeoutMillis above, also change in below function in .cpp file
|
||||
void getInfo( const QString &caller, const InfoTypeMap &inputMap, const QVariantMap &customData, const InfoTimeoutMap &timeoutMap = InfoTimeoutMap() );
|
||||
void getInfo( const QString &caller, const InfoTypeMap &inputMap, const QVariantMap &customData, const InfoTimeoutMap &timeoutMap = InfoTimeoutMap(), bool allSources = false );
|
||||
void pushInfo( const QString &caller, const InfoType type, const QVariant &input );
|
||||
void pushInfo( const QString &caller, const InfoTypeMap &input );
|
||||
|
||||
@@ -186,8 +246,8 @@ public slots:
|
||||
private:
|
||||
QWeakPointer< InfoSystemCache > m_cache;
|
||||
QWeakPointer< InfoSystemWorker > m_worker;
|
||||
QThread* m_infoSystemCacheThreadController;
|
||||
QThread* m_infoSystemWorkerThreadController;
|
||||
InfoSystemCacheThread* m_infoSystemCacheThreadController;
|
||||
InfoSystemWorkerThread* m_infoSystemWorkerThreadController;
|
||||
|
||||
static InfoSystem* s_instance;
|
||||
};
|
||||
@@ -196,6 +256,8 @@ private:
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline uint qHash( Tomahawk::InfoSystem::InfoCriteriaHash hash )
|
||||
{
|
||||
QCryptographicHash md5( QCryptographicHash::Md5 );
|
||||
@@ -221,5 +283,9 @@ Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoRequestData );
|
||||
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoGenericMap );
|
||||
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoCriteriaHash );
|
||||
Q_DECLARE_METATYPE( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache > );
|
||||
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::ArtistTrackPair );
|
||||
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::Chart );
|
||||
Q_DECLARE_METATYPE( QList<Tomahawk::InfoSystem::ArtistTrackPair> );
|
||||
Q_DECLARE_METATYPE( QList<Tomahawk::InfoSystem::Chart> );
|
||||
|
||||
#endif // TOMAHAWK_INFOSYSTEM_H
|
||||
|
@@ -35,6 +35,7 @@
|
||||
#endif
|
||||
#ifdef Q_WS_X11
|
||||
#include "infoplugins/unix/fdonotifyplugin.h"
|
||||
#include "infoplugins/unix/mprisplugin.h"
|
||||
#endif
|
||||
|
||||
#include "lastfm/NetworkAccessManager"
|
||||
@@ -97,6 +98,9 @@ InfoSystemWorker::init( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache> cac
|
||||
InfoPluginPtr fdonotifyptr( new FdoNotifyPlugin() );
|
||||
m_plugins.append( fdonotifyptr );
|
||||
registerInfoTypes( fdonotifyptr, fdonotifyptr.data()->supportedGetTypes(), fdonotifyptr.data()->supportedPushTypes() );
|
||||
InfoPluginPtr mprisptr( new MprisPlugin() );
|
||||
m_plugins.append( mprisptr );
|
||||
registerInfoTypes( mprisptr, mprisptr.data()->supportedGetTypes(), mprisptr.data()->supportedPushTypes() );
|
||||
#endif
|
||||
|
||||
Q_FOREACH( InfoPluginPtr plugin, m_plugins )
|
||||
@@ -149,12 +153,12 @@ InfoSystemWorker::registerInfoTypes( const InfoPluginPtr &plugin, const QSet< In
|
||||
}
|
||||
|
||||
|
||||
QLinkedList< InfoPluginPtr >
|
||||
QList< InfoPluginPtr >
|
||||
InfoSystemWorker::determineOrderedMatches( const InfoType type ) const
|
||||
{
|
||||
//Dummy function for now that returns the various items in the QSet; at some point this will
|
||||
//probably need to support ordering based on the data source
|
||||
QLinkedList< InfoPluginPtr > providers;
|
||||
QList< InfoPluginPtr > providers;
|
||||
Q_FOREACH( InfoPluginPtr ptr, m_infoGetMap[type] )
|
||||
providers << ptr;
|
||||
return providers;
|
||||
@@ -162,11 +166,11 @@ InfoSystemWorker::determineOrderedMatches( const InfoType type ) const
|
||||
|
||||
|
||||
void
|
||||
InfoSystemWorker::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData, uint timeoutMillis )
|
||||
InfoSystemWorker::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData, uint timeoutMillis, bool allSources )
|
||||
{
|
||||
// qDebug() << Q_FUNC_INFO;
|
||||
|
||||
QLinkedList< InfoPluginPtr > providers = determineOrderedMatches( requestData.type );
|
||||
QList< InfoPluginPtr > providers = determineOrderedMatches( requestData.type );
|
||||
if ( providers.isEmpty() )
|
||||
{
|
||||
emit info( requestData, QVariant() );
|
||||
@@ -174,33 +178,42 @@ InfoSystemWorker::getInfo( Tomahawk::InfoSystem::InfoRequestData requestData, ui
|
||||
return;
|
||||
}
|
||||
|
||||
InfoPluginPtr ptr = providers.first();
|
||||
if ( !ptr )
|
||||
if ( !allSources )
|
||||
providers = QList< InfoPluginPtr >( providers.mid( 0, 1 ) );
|
||||
|
||||
bool foundOne = false;
|
||||
foreach ( InfoPluginPtr ptr, providers )
|
||||
{
|
||||
if ( !ptr )
|
||||
continue;
|
||||
|
||||
foundOne = true;
|
||||
uint requestId = ++m_nextRequest;
|
||||
m_requestSatisfiedMap[ requestId ] = false;
|
||||
if ( timeoutMillis != 0 )
|
||||
{
|
||||
qint64 currMs = QDateTime::currentMSecsSinceEpoch();
|
||||
m_timeRequestMapper.insert( currMs + timeoutMillis, requestId );
|
||||
}
|
||||
// qDebug() << "Assigning request with requestId" << requestId << "and type" << requestData.type;
|
||||
m_dataTracker[ requestData.caller ][ requestData.type ] = m_dataTracker[ requestData.caller ][ requestData.type ] + 1;
|
||||
// qDebug() << "Current count in dataTracker for target" << requestData.caller << "and type" << requestData.type << "is" << m_dataTracker[ requestData.caller ][ requestData.type ];
|
||||
|
||||
InfoRequestData* data = new InfoRequestData;
|
||||
data->caller = requestData.caller;
|
||||
data->type = requestData.type;
|
||||
data->input = requestData.input;
|
||||
data->customData = requestData.customData;
|
||||
m_savedRequestMap[ requestId ] = data;
|
||||
|
||||
QMetaObject::invokeMethod( ptr.data(), "getInfo", Qt::QueuedConnection, Q_ARG( uint, requestId ), Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ) );
|
||||
}
|
||||
|
||||
if ( !foundOne )
|
||||
{
|
||||
emit info( requestData, QVariant() );
|
||||
checkFinished( requestData.caller );
|
||||
return;
|
||||
}
|
||||
|
||||
uint requestId = ++m_nextRequest;
|
||||
m_requestSatisfiedMap[ requestId ] = false;
|
||||
if ( timeoutMillis != 0 )
|
||||
{
|
||||
qint64 currMs = QDateTime::currentMSecsSinceEpoch();
|
||||
m_timeRequestMapper.insert( currMs + timeoutMillis, requestId );
|
||||
}
|
||||
// qDebug() << "Assigning request with requestId" << requestId << "and type" << requestData.type;
|
||||
m_dataTracker[ requestData.caller ][ requestData.type ] = m_dataTracker[ requestData.caller ][ requestData.type ] + 1;
|
||||
// qDebug() << "Current count in dataTracker for target" << requestData.caller << "and type" << requestData.type << "is" << m_dataTracker[ requestData.caller ][ requestData.type ];
|
||||
|
||||
InfoRequestData* data = new InfoRequestData;
|
||||
data->caller = requestData.caller;
|
||||
data->type = requestData.type;
|
||||
data->input = requestData.input;
|
||||
data->customData = requestData.customData;
|
||||
m_savedRequestMap[ requestId ] = data;
|
||||
|
||||
QMetaObject::invokeMethod( ptr.data(), "getInfo", Qt::QueuedConnection, Q_ARG( uint, requestId ), Q_ARG( Tomahawk::InfoSystem::InfoRequestData, requestData ) );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -21,13 +21,13 @@
|
||||
|
||||
#include "infosystem/infosystem.h"
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QtDebug>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QWeakPointer>
|
||||
#include <QtCore/QSet>
|
||||
#include <QtCore/QLinkedList>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
@@ -57,7 +57,7 @@ signals:
|
||||
|
||||
public slots:
|
||||
void init( QWeakPointer< Tomahawk::InfoSystem::InfoSystemCache > cache );
|
||||
void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData, uint timeoutMillis );
|
||||
void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData, uint timeoutMillis, bool allSources );
|
||||
void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input );
|
||||
|
||||
void infoSlot( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
|
||||
@@ -76,13 +76,13 @@ private:
|
||||
QHash< uint, bool > m_requestSatisfiedMap;
|
||||
QHash< uint, InfoRequestData* > m_savedRequestMap;
|
||||
|
||||
QLinkedList< InfoPluginPtr > determineOrderedMatches( const InfoType type ) const;
|
||||
QList< InfoPluginPtr > determineOrderedMatches( const InfoType type ) const;
|
||||
|
||||
// For now, statically instantiate plugins; this is just somewhere to keep them
|
||||
QLinkedList< InfoPluginPtr > m_plugins;
|
||||
QList< InfoPluginPtr > m_plugins;
|
||||
|
||||
QMap< InfoType, QLinkedList< InfoPluginPtr > > m_infoGetMap;
|
||||
QMap< InfoType, QLinkedList< InfoPluginPtr > > m_infoPushMap;
|
||||
QMap< InfoType, QList< InfoPluginPtr > > m_infoGetMap;
|
||||
QMap< InfoType, QList< InfoPluginPtr > > m_infoPushMap;
|
||||
|
||||
QWeakPointer< QNetworkAccessManager> m_nam;
|
||||
|
||||
|
@@ -134,27 +134,23 @@ DBSyncConnection::check()
|
||||
}
|
||||
|
||||
m_uscache.clear();
|
||||
m_themcache.clear();
|
||||
m_us.clear();
|
||||
|
||||
changeState( CHECKING );
|
||||
|
||||
// load last-modified etc data for our collection and theirs from our DB:
|
||||
DatabaseCommand_CollectionStats* cmd_us =
|
||||
new DatabaseCommand_CollectionStats( SourceList::instance()->getLocal() );
|
||||
|
||||
DatabaseCommand_CollectionStats* cmd_them =
|
||||
new DatabaseCommand_CollectionStats( m_source );
|
||||
|
||||
connect( cmd_us, SIGNAL( done( QVariantMap ) ),
|
||||
SLOT( gotUs( QVariantMap ) ) );
|
||||
|
||||
connect( cmd_them, SIGNAL( done( QVariantMap ) ),
|
||||
SLOT( gotThemCache( QVariantMap ) ) );
|
||||
|
||||
|
||||
DatabaseCommand_CollectionStats* cmd_us = new DatabaseCommand_CollectionStats( SourceList::instance()->getLocal() );
|
||||
connect( cmd_us, SIGNAL( done( QVariantMap ) ), SLOT( gotUs( QVariantMap ) ) );
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>(cmd_us) );
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>(cmd_them) );
|
||||
|
||||
if ( m_lastop.isEmpty() )
|
||||
{
|
||||
DatabaseCommand_CollectionStats* cmd_them = new DatabaseCommand_CollectionStats( m_source );
|
||||
connect( cmd_them, SIGNAL( done( QVariantMap ) ), SLOT( gotThem( QVariantMap ) ) );
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>(cmd_them) );
|
||||
}
|
||||
else
|
||||
fetchOpsData( m_lastop );
|
||||
|
||||
// restarts idle countdown
|
||||
m_timer.start();
|
||||
@@ -174,16 +170,24 @@ DBSyncConnection::gotUs( const QVariantMap& m )
|
||||
|
||||
/// Called once we've loaded our cached data about their collection
|
||||
void
|
||||
DBSyncConnection::gotThemCache( const QVariantMap& m )
|
||||
DBSyncConnection::gotThem( const QVariantMap& m )
|
||||
{
|
||||
m_lastop = m.value( "lastop" ).toString();
|
||||
|
||||
fetchOpsData( m_lastop );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DBSyncConnection::fetchOpsData( const QString& sinceguid )
|
||||
{
|
||||
m_themcache = m;
|
||||
changeState( FETCHING );
|
||||
|
||||
tLog() << "Sending a FETCHOPS cmd since:" << m_themcache.value( "lastop" ).toString();
|
||||
tLog() << "Sending a FETCHOPS cmd since:" << sinceguid;
|
||||
|
||||
QVariantMap msg;
|
||||
msg.insert( "method", "fetchops" );
|
||||
msg.insert( "lastop", m_themcache.value( "lastop" ).toString() );
|
||||
msg.insert( "lastop", sinceguid );
|
||||
sendMsg( msg );
|
||||
}
|
||||
|
||||
@@ -234,8 +238,7 @@ DBSyncConnection::handleMsg( msg_ptr msg )
|
||||
lastOpApplied();
|
||||
return;
|
||||
}
|
||||
|
||||
// qDebug() << "APPLYING CMD" << cmd->commandname() << cmd->guid();
|
||||
QSharedPointer<DatabaseCommand> cmdsp = QSharedPointer<DatabaseCommand>(cmd);
|
||||
|
||||
if ( !msg->is( Msg::FRAGMENT ) ) // last msg in this batch
|
||||
{
|
||||
@@ -243,10 +246,21 @@ DBSyncConnection::handleMsg( msg_ptr msg )
|
||||
connect( cmd, SIGNAL( finished() ), SLOT( lastOpApplied() ) );
|
||||
}
|
||||
|
||||
if ( !cmd->singletonCmd() )
|
||||
m_source->setLastOpGuid( cmd->guid() );
|
||||
if ( m_recentTempOps.contains( cmd->guid() ) )
|
||||
{
|
||||
qDebug() << "Ignoring dupe temporary command:" << cmd->guid();
|
||||
return;
|
||||
}
|
||||
|
||||
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||
if ( !cmd->singletonCmd() )
|
||||
{
|
||||
m_lastop = cmd->guid();
|
||||
m_recentTempOps.clear();
|
||||
}
|
||||
else
|
||||
m_recentTempOps << cmd->guid();
|
||||
|
||||
Database::instance()->enqueue( cmdsp );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -283,7 +297,7 @@ DBSyncConnection::lastOpApplied()
|
||||
void
|
||||
DBSyncConnection::sendOps()
|
||||
{
|
||||
tLog() << "Will send peer all ops since" << m_uscache.value( "lastop" ).toString();
|
||||
tLog() << "Will send peer" << m_source->id() << "all ops since" << m_uscache.value( "lastop" ).toString();
|
||||
|
||||
source_ptr src = SourceList::instance()->getLocal();
|
||||
|
||||
|
@@ -64,9 +64,13 @@ public slots:
|
||||
|
||||
private slots:
|
||||
void gotUs( const QVariantMap& m );
|
||||
void gotThemCache( const QVariantMap& m );
|
||||
void lastOpApplied();
|
||||
void gotThem( const QVariantMap& m );
|
||||
|
||||
void fetchOpsData( const QString& sinceguid );
|
||||
void sendOpsData( QString sinceguid, QString lastguid, QList< dbop_ptr > ops );
|
||||
|
||||
void lastOpApplied();
|
||||
|
||||
void check();
|
||||
void idleTimeout();
|
||||
|
||||
@@ -76,11 +80,13 @@ private:
|
||||
void changeState( State newstate );
|
||||
|
||||
Tomahawk::source_ptr m_source;
|
||||
QVariantMap m_us, m_uscache, m_themcache;
|
||||
State m_state;
|
||||
QVariantMap m_us, m_uscache;
|
||||
|
||||
QString m_lastop;
|
||||
QString m_lastSentOp;
|
||||
QStringList m_recentTempOps;
|
||||
|
||||
State m_state;
|
||||
QTimer m_timer;
|
||||
};
|
||||
|
||||
|
@@ -60,6 +60,7 @@ Servent::Servent( QObject* parent )
|
||||
: QTcpServer( parent )
|
||||
, m_port( 0 )
|
||||
, m_externalPort( 0 )
|
||||
, m_ready( false )
|
||||
, m_portfwd( 0 )
|
||||
{
|
||||
s_instance = this;
|
||||
@@ -133,6 +134,7 @@ Servent::startListening( QHostAddress ha, bool upnp, int port )
|
||||
tLog() << "Forcing static preferred host and port";
|
||||
m_externalHostname = TomahawkSettings::instance()->externalHostname();
|
||||
m_externalPort = TomahawkSettings::instance()->externalPort();
|
||||
m_ready = true;
|
||||
emit ready();
|
||||
return true;
|
||||
}
|
||||
@@ -151,11 +153,14 @@ Servent::startListening( QHostAddress ha, bool upnp, int port )
|
||||
|
||||
if ( qApp->arguments().contains( "--lanhack" ) )
|
||||
{
|
||||
qDebug() << "LANHACK: set external address to lan address" << ha.toString();
|
||||
tLog() << "LANHACK: set external address to lan address" << ha.toString();
|
||||
QMetaObject::invokeMethod( this, "setExternalAddress", Qt::QueuedConnection, Q_ARG( QHostAddress, ha ), Q_ARG( unsigned int, m_port ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ready = true;
|
||||
emit ready();
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -186,7 +191,7 @@ Servent::createConnectionKey( const QString& name, const QString &nodeid, const
|
||||
cc->setId( nodeid );
|
||||
cc->setOnceOnly( onceOnly );
|
||||
|
||||
qDebug() << "Creating connection key with name of " << cc->name() << " and id of " << cc->id() << " and key of " << _key << "; key is once only? : " << (onceOnly ? "true" : "false");
|
||||
qDebug() << "Creating connection key with name of" << cc->name() << "and id of" << cc->id() << "and key of" << _key << "; key is once only? :" << (onceOnly ? "true" : "false");
|
||||
registerOffer( _key, cc );
|
||||
return _key;
|
||||
}
|
||||
@@ -224,9 +229,10 @@ Servent::setExternalAddress( QHostAddress ha, unsigned int port )
|
||||
qDebug() << m_externalHostname << m_externalPort;
|
||||
}
|
||||
else
|
||||
qDebug() << "No external access, LAN and outbound connections only!";
|
||||
tLog() << "No external access, LAN and outbound connections only!";
|
||||
}
|
||||
|
||||
m_ready = true;
|
||||
emit ready();
|
||||
}
|
||||
|
||||
@@ -348,7 +354,7 @@ Servent::readyRead()
|
||||
// qDebug() << con->socket() << sock;
|
||||
if( con->id() == nodeid )
|
||||
{
|
||||
qDebug() << "Duplicate control connection detected, dropping:" << nodeid << conntype;
|
||||
tLog() << "Duplicate control connection detected, dropping:" << nodeid << conntype;
|
||||
goto closeconnection;
|
||||
}
|
||||
}
|
||||
@@ -372,7 +378,7 @@ Servent::readyRead()
|
||||
Connection* conn = claimOffer( cc, nodeid, key, sock->peerAddress() );
|
||||
if( !conn )
|
||||
{
|
||||
qDebug() << "claimOffer FAILED, key:" << key;
|
||||
tLog() << "claimOffer FAILED, key:" << key;
|
||||
goto closeconnection;
|
||||
}
|
||||
qDebug() << "claimOffer OK:" << key;
|
||||
@@ -390,7 +396,7 @@ Servent::readyRead()
|
||||
|
||||
// fallthru to cleanup:
|
||||
closeconnection:
|
||||
qDebug() << "Closing incoming connection, something was wrong.";
|
||||
tLog() << "Closing incoming connection, something was wrong.";
|
||||
sock->_msg.clear();
|
||||
sock->disconnectFromHost();
|
||||
}
|
||||
@@ -405,7 +411,7 @@ Servent::createParallelConnection( Connection* orig_conn, Connection* new_conn,
|
||||
// if we can connect to them directly:
|
||||
if( orig_conn && orig_conn->outbound() )
|
||||
{
|
||||
qDebug() << "Connecting directly";
|
||||
tLog() << "Connecting directly";
|
||||
connectToPeer( orig_conn->socket()->peerAddress().toString(),
|
||||
orig_conn->peerPort(),
|
||||
key,
|
||||
@@ -414,7 +420,7 @@ Servent::createParallelConnection( Connection* orig_conn, Connection* new_conn,
|
||||
else // ask them to connect to us:
|
||||
{
|
||||
QString tmpkey = uuid();
|
||||
qDebug() << "Asking them to connect to us using" << tmpkey ;
|
||||
tLog() << "Asking them to connect to us using" << tmpkey ;
|
||||
registerOffer( tmpkey, new_conn );
|
||||
|
||||
QVariantMap m;
|
||||
@@ -470,12 +476,18 @@ Servent::socketError( QAbstractSocket::SocketError e )
|
||||
QTcpSocketExtra* sock = (QTcpSocketExtra*)sender();
|
||||
if( !sock )
|
||||
{
|
||||
qDebug() << "SocketError, sock is null";
|
||||
tLog() << "SocketError, sock is null";
|
||||
return;
|
||||
}
|
||||
|
||||
Connection* conn = sock->_conn;
|
||||
qDebug() << "Servent::SocketError:" << e << conn->id() << conn->name();
|
||||
if ( !conn )
|
||||
{
|
||||
tLog() << "SocketError, connection is null";
|
||||
return;
|
||||
}
|
||||
|
||||
tLog() << "Servent::SocketError:" << e << conn->id() << conn->name();
|
||||
if( !sock->_disowned )
|
||||
{
|
||||
// connection will delete if we already transferred ownership, otherwise:
|
||||
@@ -601,7 +613,7 @@ Servent::claimOffer( ControlConnection* cc, const QString &nodeid, const QString
|
||||
}
|
||||
if( !authed )
|
||||
{
|
||||
qDebug() << "File transfer request rejected, invalid source IP";
|
||||
tLog() << "File transfer request rejected, invalid source IP";
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -635,7 +647,7 @@ Servent::claimOffer( ControlConnection* cc, const QString &nodeid, const QString
|
||||
// This can happen if it's a streamconnection, but the audioengine has
|
||||
// already closed the iodevice, causing the connection to be deleted before
|
||||
// the peer connects and provides the first byte
|
||||
qDebug() << Q_FUNC_INFO << "invalid/expired offer:" << key;
|
||||
tLog() << Q_FUNC_INFO << "invalid/expired offer:" << key;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -644,12 +656,12 @@ Servent::claimOffer( ControlConnection* cc, const QString &nodeid, const QString
|
||||
// If there isn't a nodeid it's not the first connection and will already have been stopped
|
||||
if( !checkACL( conn, nodeid, true ) )
|
||||
{
|
||||
qDebug() << "Connection not allowed due to ACL";
|
||||
tLog() << "Connection not allowed due to ACL";
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "ACL has allowed the connection";
|
||||
tLog() << "ACL has allowed the connection";
|
||||
|
||||
if( conn->onceOnly() )
|
||||
{
|
||||
@@ -670,7 +682,7 @@ Servent::claimOffer( ControlConnection* cc, const QString &nodeid, const QString
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Invalid offer key:" << key;
|
||||
tLog() << "Invalid offer key:" << key;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -823,7 +835,6 @@ Servent::isIPWhitelisted( QHostAddress ip )
|
||||
bool
|
||||
Servent::connectedToSession( const QString& session )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
// qDebug() << "Checking against" << session;
|
||||
foreach( ControlConnection* cc, m_controlconnections )
|
||||
{
|
||||
@@ -839,8 +850,6 @@ Servent::connectedToSession( const QString& session )
|
||||
void
|
||||
Servent::triggerDBSync()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
// tell peers we have new stuff they should sync
|
||||
QList<source_ptr> sources = SourceList::instance()->sources();
|
||||
foreach( const source_ptr& src, sources )
|
||||
@@ -866,7 +875,6 @@ Servent::registerIODeviceFactory( const QString &proto, boost::function<QSharedP
|
||||
QSharedPointer<QIODevice>
|
||||
Servent::getIODeviceForUrl( const Tomahawk::result_ptr& result )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << thread();
|
||||
QSharedPointer<QIODevice> sp;
|
||||
|
||||
QRegExp rx( "^([a-zA-Z0-9]+)://(.+)$" );
|
||||
@@ -897,7 +905,6 @@ Servent::localFileIODeviceFactory( const Tomahawk::result_ptr& result )
|
||||
QSharedPointer<QIODevice>
|
||||
Servent::httpIODeviceFactory( const Tomahawk::result_ptr& result )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << result->url();
|
||||
QNetworkRequest req( result->url() );
|
||||
QNetworkReply* reply = TomahawkUtils::nam()->get( req );
|
||||
return QSharedPointer<QIODevice>( reply, &QObject::deleteLater );
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
@@ -123,6 +123,8 @@ public:
|
||||
QSharedPointer<QIODevice> localFileIODeviceFactory( const Tomahawk::result_ptr& result );
|
||||
QSharedPointer<QIODevice> httpIODeviceFactory( const Tomahawk::result_ptr& result );
|
||||
|
||||
bool isReady() const { return m_ready; };
|
||||
|
||||
signals:
|
||||
void streamStarted( StreamConnection* );
|
||||
void streamFinished( StreamConnection* );
|
||||
@@ -159,6 +161,7 @@ private:
|
||||
int m_port, m_externalPort;
|
||||
QHostAddress m_externalAddress;
|
||||
QString m_externalHostname;
|
||||
bool m_ready;
|
||||
|
||||
// currently active file transfers:
|
||||
QList< StreamConnection* > m_scsessions;
|
||||
|
@@ -116,11 +116,13 @@ Pipeline::resolve( const QList<query_ptr>& qlist, bool prioritized, bool tempora
|
||||
int i = 0;
|
||||
foreach( const query_ptr& q, qlist )
|
||||
{
|
||||
if ( !m_qids.contains( q->id() ) )
|
||||
m_qids.insert( q->id(), q );
|
||||
|
||||
if ( m_queries_pending.contains( q ) )
|
||||
continue;
|
||||
if ( m_qidsState.contains( q->id() ) )
|
||||
continue;
|
||||
|
||||
if ( !m_qids.contains( q->id() ) )
|
||||
m_qids.insert( q->id(), q );
|
||||
|
||||
if ( prioritized )
|
||||
m_queries_pending.insert( i++, q );
|
||||
@@ -169,8 +171,7 @@ Pipeline::reportResults( QID qid, const QList< result_ptr >& results )
|
||||
|
||||
if ( !m_qids.contains( qid ) )
|
||||
{
|
||||
qDebug() << "reportResults called for unknown QID" << qid;
|
||||
Q_ASSERT( false );
|
||||
tDebug() << "Result arrived too late for:" << qid;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -183,35 +184,14 @@ Pipeline::reportResults( QID qid, const QList< result_ptr >& results )
|
||||
m_rids.insert( r->id(), r );
|
||||
}
|
||||
|
||||
if ( q->solved() && !q->isFullTextQuery() )
|
||||
if ( q->playable() && !q->isFullTextQuery() )
|
||||
{
|
||||
q->onResolvingFinished();
|
||||
|
||||
setQIDState( q, 0 );
|
||||
if ( m_qidsTimeout.contains( q->id() ) )
|
||||
m_qidsTimeout.remove( q->id() );
|
||||
|
||||
shuntNext();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( decQIDState( q ) == 0 )
|
||||
{
|
||||
if ( !q->solved() || q->isFullTextQuery() )
|
||||
q->onResolvingFinished();
|
||||
|
||||
if ( !m_queries_temporary.contains( q ) )
|
||||
m_qids.remove( q->id() );
|
||||
if ( m_qidsTimeout.contains( q->id() ) )
|
||||
m_qidsTimeout.remove( q->id() );
|
||||
|
||||
shuntNext();
|
||||
}
|
||||
else
|
||||
{
|
||||
new FuncTimeout( 0, boost::bind( &Pipeline::timeoutShunt, this, q ), this );
|
||||
}
|
||||
decQIDState( q );
|
||||
}
|
||||
|
||||
|
||||
@@ -247,7 +227,6 @@ Pipeline::shuntNext()
|
||||
}
|
||||
|
||||
setQIDState( q, rc );
|
||||
new FuncTimeout( 0, boost::bind( &Pipeline::shunt, this, q ), this );
|
||||
}
|
||||
|
||||
|
||||
@@ -260,8 +239,7 @@ Pipeline::timeoutShunt( const query_ptr& q )
|
||||
// are we still waiting for a timeout?
|
||||
if ( m_qidsTimeout.contains( q->id() ) )
|
||||
{
|
||||
m_qidsTimeout.remove( q->id() );
|
||||
shunt( q );
|
||||
decQIDState( q );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,7 +256,7 @@ Pipeline::shunt( const query_ptr& q )
|
||||
|
||||
if ( r )
|
||||
{
|
||||
qDebug() << "Dispatching to resolver" << r->name() << q->toString() << q->solved() << q->id();
|
||||
tDebug() << "Dispatching to resolver" << r->name() << q->toString() << q->solved() << q->id();
|
||||
|
||||
q->setCurrentResolver( r );
|
||||
r->resolve( q );
|
||||
@@ -291,7 +269,9 @@ Pipeline::shunt( const query_ptr& q )
|
||||
}
|
||||
else
|
||||
{
|
||||
// we get here if we disable a resolver while a query is resolving
|
||||
setQIDState( q, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
shuntNext();
|
||||
@@ -327,14 +307,24 @@ Pipeline::setQIDState( const Tomahawk::query_ptr& query, int state )
|
||||
{
|
||||
QMutexLocker lock( &m_mut );
|
||||
|
||||
if ( m_qidsTimeout.contains( query->id() ) )
|
||||
m_qidsTimeout.remove( query->id() );
|
||||
|
||||
if ( state > 0 )
|
||||
{
|
||||
m_qidsState.insert( query->id(), state );
|
||||
|
||||
new FuncTimeout( 0, boost::bind( &Pipeline::shunt, this, query ), this );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_qidsState.remove( query->id() );
|
||||
// qDebug() << "Queries running:" << m_qidsState.count();
|
||||
query->onResolvingFinished();
|
||||
|
||||
if ( !m_queries_temporary.contains( query ) )
|
||||
m_qids.remove( query->id() );
|
||||
|
||||
new FuncTimeout( 0, boost::bind( &Pipeline::shuntNext, this ), this );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,22 +348,17 @@ Pipeline::incQIDState( const Tomahawk::query_ptr& query )
|
||||
int
|
||||
Pipeline::decQIDState( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
QMutexLocker lock( &m_mut );
|
||||
|
||||
if ( !m_qidsState.contains( query->id() ) )
|
||||
return 0;
|
||||
|
||||
int state = m_qidsState.value( query->id() ) - 1;
|
||||
if ( state )
|
||||
int state = 0;
|
||||
{
|
||||
m_qidsState.insert( query->id(), state );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_qidsState.remove( query->id() );
|
||||
// qDebug() << "Queries running:" << m_qidsState.count();
|
||||
QMutexLocker lock( &m_mut );
|
||||
|
||||
if ( !m_qidsState.contains( query->id() ) )
|
||||
return 0;
|
||||
|
||||
state = m_qidsState.value( query->id() ) - 1;
|
||||
}
|
||||
|
||||
setQIDState( query, state );
|
||||
return state;
|
||||
}
|
||||
|
||||
|
@@ -119,7 +119,7 @@ Playlist::Playlist( const source_ptr& src,
|
||||
, m_currentItem( 0 )
|
||||
, m_busy( false )
|
||||
{
|
||||
// qDebug() << Q_FUNC_INFO << "1";
|
||||
qDebug() << Q_FUNC_INFO << "1" << title;
|
||||
init();
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ Playlist::Playlist( const source_ptr& author,
|
||||
, m_initEntries( entries )
|
||||
, m_busy( false )
|
||||
{
|
||||
// qDebug() << Q_FUNC_INFO << "2";
|
||||
qDebug() << Q_FUNC_INFO << "2" << title;
|
||||
init();
|
||||
}
|
||||
|
||||
@@ -398,12 +398,6 @@ Playlist::setNewRevision( const QString& rev,
|
||||
QList<plentry_ptr> entries;
|
||||
foreach( const QString& id, neworderedguids )
|
||||
{
|
||||
/* qDebug() << "id:" << id;
|
||||
qDebug() << "newordered:" << neworderedguids.count() << neworderedguids;
|
||||
qDebug() << "entriesmap:" << entriesmap.count() << entriesmap;
|
||||
qDebug() << "addedmap:" << addedmap.count() << addedmap;
|
||||
qDebug() << "m_entries" << m_entries; */
|
||||
|
||||
if( entriesmap.contains( id ) )
|
||||
{
|
||||
entries.append( entriesmap.value( id ) );
|
||||
@@ -416,6 +410,13 @@ Playlist::setNewRevision( const QString& rev,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* qDebug() << "id:" << id;
|
||||
* qDebug() << "newordered:" << neworderedguids.count() << neworderedguids;
|
||||
* qDebug() << "entriesmap:" << entriesmap.count() << entriesmap;
|
||||
* qDebug() << "addedmap:" << addedmap.count() << addedmap;
|
||||
* qDebug() << "m_entries" << m_entries; */
|
||||
|
||||
tLog() << "Playlist error for playlist with guid" << guid() << "from source" << author()->friendlyName();
|
||||
Q_ASSERT( false ); // XXX
|
||||
}
|
||||
}
|
||||
|
@@ -33,6 +33,7 @@
|
||||
#include <QQueue>
|
||||
|
||||
class DatabaseCommand_LoadAllPlaylists;
|
||||
class DatabaseCommand_LoadAllSortedPlaylists;
|
||||
class DatabaseCommand_SetPlaylistRevision;
|
||||
class DatabaseCommand_CreatePlaylist;
|
||||
|
||||
@@ -124,6 +125,7 @@ Q_PROPERTY( unsigned int createdon READ createdOn WRITE setCreatedOn )
|
||||
Q_PROPERTY( bool shared READ shared WRITE setShared )
|
||||
|
||||
friend class ::DatabaseCommand_LoadAllPlaylists;
|
||||
friend class ::DatabaseCommand_LoadAllSortedPlaylists;
|
||||
friend class ::DatabaseCommand_SetPlaylistRevision;
|
||||
friend class ::DatabaseCommand_CreatePlaylist;
|
||||
friend class DynamicPlaylist;
|
||||
|
143
src/libtomahawk/playlist/ViewHeader.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ViewHeader.h"
|
||||
|
||||
#include <QContextMenuEvent>
|
||||
#include <QMenu>
|
||||
|
||||
#include "tomahawksettings.h"
|
||||
#include "utils/logger.h"
|
||||
|
||||
|
||||
ViewHeader::ViewHeader( QAbstractItemView* parent )
|
||||
: QHeaderView( Qt::Horizontal, parent )
|
||||
, m_parent( parent )
|
||||
, m_menu( new QMenu( this ) )
|
||||
, m_sigmap( new QSignalMapper( this ) )
|
||||
, m_init( false )
|
||||
{
|
||||
setResizeMode( QHeaderView::Interactive );
|
||||
setMinimumSectionSize( 60 );
|
||||
setDefaultAlignment( Qt::AlignLeft );
|
||||
setMovable( true );
|
||||
setStretchLastSection( true );
|
||||
|
||||
// m_menu->addAction( tr( "Resize columns to fit window" ), this, SLOT( onToggleResizeColumns() ) );
|
||||
// m_menu->addSeparator();
|
||||
|
||||
connect( m_sigmap, SIGNAL( mapped( int ) ), SLOT( toggleVisibility( int ) ) );
|
||||
}
|
||||
|
||||
|
||||
ViewHeader::~ViewHeader()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ViewHeader::visibleSectionCount() const
|
||||
{
|
||||
return count() - hiddenSectionCount();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ViewHeader::onSectionsChanged()
|
||||
{
|
||||
TomahawkSettings::instance()->setPlaylistColumnSizes( m_guid, saveState() );
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ViewHeader::checkState()
|
||||
{
|
||||
if ( !count() || m_init )
|
||||
return false;
|
||||
|
||||
QByteArray state = TomahawkSettings::instance()->playlistColumnSizes( m_guid );
|
||||
if ( !state.isEmpty() )
|
||||
{
|
||||
restoreState( state );
|
||||
|
||||
if ( m_guid.startsWith( "playlistview" ) ) // HACK
|
||||
setSortIndicator( -1, Qt::AscendingOrder );
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( int i = 0; i < count() - 1; i++ )
|
||||
{
|
||||
if ( isSectionHidden( i ) )
|
||||
continue;
|
||||
|
||||
double nw = (double)m_parent->width() * m_columnWeights.at( i );
|
||||
resizeSection( i, qMax( minimumSectionSize(), int( nw - 0.5 ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
m_init = true;
|
||||
connect( this, SIGNAL( sectionMoved( int, int, int ) ), SLOT( onSectionsChanged() ) );
|
||||
connect( this, SIGNAL( sectionResized( int, int, int ) ), SLOT( onSectionsChanged() ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ViewHeader::addColumnToMenu( int index )
|
||||
{
|
||||
QString title = m_parent->model()->headerData( index, Qt::Horizontal, Qt::DisplayRole ).toString();
|
||||
|
||||
QAction* action = m_menu->addAction( title, m_sigmap, SLOT( map() ) );
|
||||
action->setCheckable( true );
|
||||
action->setChecked( !isSectionHidden( index ) );
|
||||
m_visActions << action;
|
||||
|
||||
m_sigmap->setMapping( action, index );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ViewHeader::contextMenuEvent( QContextMenuEvent* e )
|
||||
{
|
||||
qDeleteAll( m_visActions );
|
||||
m_visActions.clear();
|
||||
|
||||
for ( int i = 0; i < count(); i++ )
|
||||
addColumnToMenu( i );
|
||||
|
||||
m_menu->popup( e->globalPos() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ViewHeader::onToggleResizeColumns()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ViewHeader::toggleVisibility( int index )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << index;
|
||||
|
||||
if ( isSectionHidden( index ) )
|
||||
showSection( index );
|
||||
else
|
||||
hideSection( index );
|
||||
}
|
65
src/libtomahawk/playlist/ViewHeader.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VIEWHEADER_H
|
||||
#define VIEWHEADER_H
|
||||
|
||||
#include <QHeaderView>
|
||||
#include <QSignalMapper>
|
||||
|
||||
#include "dllmacro.h"
|
||||
|
||||
class DLLEXPORT ViewHeader : public QHeaderView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ViewHeader( QAbstractItemView* parent = 0 );
|
||||
~ViewHeader();
|
||||
|
||||
int visibleSectionCount() const;
|
||||
|
||||
void setDefaultColumnWeights( QList<double> weights ) { m_columnWeights = weights; }
|
||||
|
||||
QString guid() const { return m_guid; }
|
||||
void setGuid( const QString& guid ) { m_guid = guid; }
|
||||
|
||||
public slots:
|
||||
void toggleVisibility( int index );
|
||||
bool checkState();
|
||||
|
||||
protected:
|
||||
void contextMenuEvent( QContextMenuEvent* e );
|
||||
|
||||
private slots:
|
||||
virtual void onSectionsChanged();
|
||||
void onToggleResizeColumns();
|
||||
|
||||
private:
|
||||
void addColumnToMenu( int index );
|
||||
|
||||
QAbstractItemView* m_parent;
|
||||
QString m_guid;
|
||||
QList<double> m_columnWeights;
|
||||
QMenu* m_menu;
|
||||
QSignalMapper* m_sigmap;
|
||||
QList<QAction*> m_visActions;
|
||||
bool m_init;
|
||||
};
|
||||
|
||||
#endif
|
@@ -35,6 +35,7 @@ using namespace Tomahawk;
|
||||
AlbumModel::AlbumModel( QObject* parent )
|
||||
: QAbstractItemModel( parent )
|
||||
, m_rootItem( new AlbumItem( 0, this ) )
|
||||
, m_overwriteOnAdd( false )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
@@ -195,12 +196,13 @@ AlbumModel::mimeData( const QModelIndexList &indexes ) const
|
||||
if ( item )
|
||||
{
|
||||
const album_ptr& album = item->album();
|
||||
queryStream << qlonglong( &album );
|
||||
queryStream << album->artist()->name();
|
||||
queryStream << album->name();
|
||||
}
|
||||
}
|
||||
|
||||
QMimeData* mimeData = new QMimeData();
|
||||
mimeData->setData( "application/tomahawk.query.list", queryData );
|
||||
mimeData->setData( "application/tomahawk.metadata.album", queryData );
|
||||
|
||||
return mimeData;
|
||||
}
|
||||
@@ -235,13 +237,14 @@ AlbumModel::removeIndexes( const QList<QModelIndex>& indexes )
|
||||
|
||||
|
||||
void
|
||||
AlbumModel::addCollection( const collection_ptr& collection )
|
||||
AlbumModel::addCollection( const collection_ptr& collection, bool overwrite )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << collection->name()
|
||||
<< collection->source()->id()
|
||||
<< collection->source()->userName();
|
||||
|
||||
DatabaseCommand_AllAlbums* cmd = new DatabaseCommand_AllAlbums( collection );
|
||||
m_overwriteOnAdd = overwrite;
|
||||
|
||||
connect( cmd, SIGNAL( albums( QList<Tomahawk::album_ptr>, QVariant ) ),
|
||||
SLOT( addAlbums( QList<Tomahawk::album_ptr> ) ) );
|
||||
@@ -253,7 +256,7 @@ AlbumModel::addCollection( const collection_ptr& collection )
|
||||
|
||||
|
||||
void
|
||||
AlbumModel::addFilteredCollection( const collection_ptr& collection, unsigned int amount, DatabaseCommand_AllAlbums::SortOrder order )
|
||||
AlbumModel::addFilteredCollection( const collection_ptr& collection, unsigned int amount, DatabaseCommand_AllAlbums::SortOrder order, bool overwrite )
|
||||
{
|
||||
/* qDebug() << Q_FUNC_INFO << collection->name()
|
||||
<< collection->source()->id()
|
||||
@@ -264,6 +267,7 @@ AlbumModel::addFilteredCollection( const collection_ptr& collection, unsigned in
|
||||
cmd->setLimit( amount );
|
||||
cmd->setSortOrder( order );
|
||||
cmd->setSortDescending( true );
|
||||
m_overwriteOnAdd = overwrite;
|
||||
|
||||
connect( cmd, SIGNAL( albums( QList<Tomahawk::album_ptr>, QVariant ) ),
|
||||
SLOT( addAlbums( QList<Tomahawk::album_ptr> ) ) );
|
||||
@@ -283,6 +287,9 @@ AlbumModel::addAlbums( const QList<Tomahawk::album_ptr>& albums )
|
||||
if ( !albums.count() )
|
||||
return;
|
||||
|
||||
if ( m_overwriteOnAdd )
|
||||
clear();
|
||||
|
||||
int c = rowCount( QModelIndex() );
|
||||
QPair< int, int > crows;
|
||||
crows.first = c;
|
||||
@@ -313,6 +320,30 @@ AlbumModel::clear()
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
AlbumModel::getCover( const QModelIndex& index )
|
||||
{
|
||||
AlbumItem* item = itemFromIndex( index );
|
||||
if ( !item || !item->cover.isNull() )
|
||||
return false;
|
||||
|
||||
Tomahawk::InfoSystem::InfoCriteriaHash trackInfo;
|
||||
trackInfo["artist"] = item->album()->artist()->name();
|
||||
trackInfo["album"] = item->album()->name();
|
||||
trackInfo["pptr"] = QString::number( (qlonglong)item );
|
||||
m_coverHash.insert( (qlonglong)item, index );
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData;
|
||||
requestData.caller = s_tmInfoIdentifier;
|
||||
requestData.type = Tomahawk::InfoSystem::InfoAlbumCoverArt;
|
||||
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo );
|
||||
requestData.customData = QVariantMap();
|
||||
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlbumModel::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
|
||||
{
|
||||
@@ -341,12 +372,15 @@ AlbumModel::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, Q
|
||||
|
||||
bool ok;
|
||||
qlonglong p = pptr["pptr"].toLongLong( &ok );
|
||||
AlbumItem* ai = reinterpret_cast<AlbumItem*>(p);
|
||||
AlbumItem* ai = itemFromIndex( m_coverHash.take( p ) );
|
||||
if ( !ai )
|
||||
return;
|
||||
|
||||
if ( !pm.isNull() )
|
||||
ai->cover = pm;
|
||||
|
||||
emit dataChanged( ai->index, ai->index.sibling( ai->index.row(), columnCount( QModelIndex() ) - 1 ) );
|
||||
if ( ai->index.isValid() )
|
||||
emit dataChanged( ai->index, ai->index.sibling( ai->index.row(), columnCount( QModelIndex() ) - 1 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|