Compare commits
268 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
a78a25baa6 | ||
|
375ffd1445 | ||
|
c3d223d8cb | ||
|
b2f3dedaff | ||
|
a3ae74dc10 | ||
|
4dfb989676 | ||
|
e0d1289a16 | ||
|
cc5ba35a08 | ||
|
e0e79c09a4 | ||
|
03f726f46c | ||
|
c0edc3a989 | ||
|
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 | ||
|
b8bf7420d0 | ||
|
16f32253c3 | ||
|
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 )
|
||||
|
||||
@@ -72,6 +72,10 @@ ELSE()
|
||||
LIST(APPEND NEEDED_QT4_COMPONENTS "QtGui" "QtWebkit" )
|
||||
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 +102,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
|
||||
|
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."
|
||||
|
29
ChangeLog
@@ -1,4 +1,33 @@
|
||||
Version 0.3.0:
|
||||
* 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.
|
||||
* Fixed searching with 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/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 |
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
|
||||
@@ -101,11 +104,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,6 +126,8 @@ SET( tomahawkHeadersGui ${tomahawkHeadersGui}
|
||||
resolversmodel.h
|
||||
delegateconfigwrapper.h
|
||||
tomahawkwindow.h
|
||||
|
||||
Qocoa/qsearchfield.h
|
||||
)
|
||||
|
||||
SET( tomahawkUI ${tomahawkUI}
|
||||
@@ -127,7 +135,6 @@ SET( tomahawkUI ${tomahawkUI}
|
||||
diagnosticsdialog.ui
|
||||
stackedsettingsdialog.ui
|
||||
proxydialog.ui
|
||||
searchbox.ui
|
||||
|
||||
audiocontrols.ui
|
||||
)
|
||||
@@ -171,12 +178,13 @@ 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( tomahawkSources ${tomahawkSources} mac/tomahawkapp_mac.mm mac/macshortcuthandler.cpp Qocoa/qsearchfield_mac.mm )
|
||||
|
||||
IF(HAVE_SPARKLE)
|
||||
SET( tomahawkHeaders ${tomahawkHeaders} ${SPARKLE}/Headers )
|
||||
ENDIF(HAVE_SPARKLE)
|
||||
|
||||
ELSE( APPLE )
|
||||
SET( tomahawkSources ${tomahawkSources} Qocoa/qsearchfield.cpp )
|
||||
ENDIF( APPLE )
|
||||
|
||||
IF(GLOOX_FOUND)
|
||||
@@ -186,6 +194,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,6 +238,10 @@ IF(GLOOX_FOUND)
|
||||
SET(LINK_LIBRARIES ${LINK_LIBRARIES} ${GLOOX_LIBRARIES} )
|
||||
ENDIF(GLOOX_FOUND)
|
||||
|
||||
IF(QCA2_FOUND)
|
||||
SET(LINK_LIBRARIES ${LINK_LIBRARIES} ${QCA2_LIBRARIES} )
|
||||
ENDIF(QCA2_FOUND)
|
||||
|
||||
TARGET_LINK_LIBRARIES( tomahawk
|
||||
${LINK_LIBRARIES}
|
||||
${TOMAHAWK_LIBRARIES}
|
||||
@@ -237,10 +253,8 @@ TARGET_LINK_LIBRARIES( tomahawk
|
||||
${QXTWEB_LIBRARIES}
|
||||
${QJSON_LIBRARIES}
|
||||
${TAGLIB_LIBRARIES}
|
||||
${CLUCENE_LIBRARIES}
|
||||
)
|
||||
|
||||
|
||||
IF( APPLE )
|
||||
IF(HAVE_SPARKLE)
|
||||
MESSAGE("Sparkle Found, installing framekwork in bundle")
|
||||
|
51
src/Qocoa/qocoa_mac.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
Copyright (C) 2011 by Mike McQuaid
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QCOCOA_MAC_H
|
||||
#define QCOCOA_MAC_H
|
||||
|
||||
#include <Foundation/NSString.h>
|
||||
#include <QString>
|
||||
#include <QVBoxLayout>
|
||||
#include <QMacCocoaViewContainer>
|
||||
|
||||
static inline NSString* fromQString(const QString &string)
|
||||
{
|
||||
char* cString = string.toUtf8().data();
|
||||
return [[NSString alloc] initWithUTF8String:cString];
|
||||
}
|
||||
|
||||
static inline QString toQString(NSString *string)
|
||||
{
|
||||
if (!string)
|
||||
return QString();
|
||||
return QString::fromUtf8([string UTF8String]);
|
||||
}
|
||||
|
||||
static inline void zeroLayout(void *cocoaView, QWidget *parent)
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout(parent);
|
||||
layout->setMargin(0);
|
||||
layout->addWidget(new QMacCocoaViewContainer(cocoaView, parent));
|
||||
}
|
||||
|
||||
#endif
|
78
src/Qocoa/qsearchfield.cpp
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
Copyright (C) 2011 by Mike McQuaid
|
||||
Copyright (C) 2011 by Leo Franchi
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qsearchfield.h"
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "playlist/topbar/searchlineedit.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
|
||||
class QSearchFieldPrivate
|
||||
{
|
||||
public:
|
||||
QSearchFieldPrivate(SearchLineEdit *lineEdit) : lineEdit(lineEdit) {}
|
||||
SearchLineEdit *lineEdit;
|
||||
};
|
||||
|
||||
QSearchField::QSearchField(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
SearchLineEdit *lineEdit = new SearchLineEdit(this);
|
||||
connect(lineEdit, SIGNAL(textChanged(QString)),
|
||||
this, SIGNAL(textChanged(QString)));
|
||||
connect(lineEdit, SIGNAL(returnPressed()),
|
||||
this, SIGNAL(returnPressed()));
|
||||
|
||||
pimpl = new QSearchFieldPrivate(lineEdit);
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
layout->addWidget(lineEdit);
|
||||
TomahawkUtils::unmarginLayout(layout);
|
||||
setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
lineEdit->setStyleSheet( "QLineEdit { border: 1px solid gray; border-radius: 6px; margin-right: 2px; }" );
|
||||
lineEdit->setContentsMargins(0, 0, 0, 0);
|
||||
lineEdit->setMinimumHeight(27);
|
||||
setFixedHeight(27);
|
||||
}
|
||||
|
||||
void QSearchField::setText(const QString &text)
|
||||
{
|
||||
pimpl->lineEdit->setText(text);
|
||||
}
|
||||
|
||||
void QSearchField::setPlaceholderText(const QString& text)
|
||||
{
|
||||
pimpl->lineEdit->setInactiveText( text );
|
||||
}
|
||||
|
||||
void QSearchField::clear()
|
||||
{
|
||||
pimpl->lineEdit->clear();
|
||||
}
|
||||
|
||||
QString QSearchField::text() const
|
||||
{
|
||||
return pimpl->lineEdit->text();
|
||||
}
|
29
src/Qocoa/qsearchfield.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef QSEARCHFIELD_H
|
||||
#define QSEARCHFIELD_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class QSearchFieldPrivate;
|
||||
class QSearchField : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit QSearchField(QWidget* parent);
|
||||
|
||||
QString text() const;
|
||||
|
||||
public slots:
|
||||
void setText(const QString &text);
|
||||
void setPlaceholderText(const QString& text);
|
||||
|
||||
void clear();
|
||||
signals:
|
||||
void textChanged(const QString &text);
|
||||
void returnPressed();
|
||||
|
||||
private:
|
||||
friend class QSearchFieldPrivate;
|
||||
QSearchFieldPrivate *pimpl;
|
||||
};
|
||||
|
||||
#endif // QSEARCHFIELD_H
|
118
src/Qocoa/qsearchfield_mac.mm
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
Copyright (C) 2011 by Mike McQuaid
|
||||
Copyright (C) 2011 by Leo Franchi
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qsearchfield.h"
|
||||
|
||||
#include "qocoa_mac.h"
|
||||
|
||||
#include "qsearchfield.h"
|
||||
|
||||
#import "Foundation/NSAutoreleasePool.h"
|
||||
#import "Foundation/NSNotification.h"
|
||||
#import "AppKit/NSSearchField.h"
|
||||
|
||||
class QSearchFieldPrivate
|
||||
{
|
||||
public:
|
||||
QSearchFieldPrivate(QSearchField *qSearchField, NSSearchField *nsSearchField)
|
||||
: qSearchField(qSearchField), nsSearchField(nsSearchField) {}
|
||||
|
||||
void textDidChange(const QString &text)
|
||||
{
|
||||
emit qSearchField->textChanged(text);
|
||||
}
|
||||
|
||||
void textDidEndEditing()
|
||||
{
|
||||
emit qSearchField->returnPressed();
|
||||
}
|
||||
|
||||
QSearchField *qSearchField;
|
||||
NSSearchField *nsSearchField;
|
||||
};
|
||||
|
||||
@interface QSearchFieldDelegate : NSObject<NSTextFieldDelegate>
|
||||
{
|
||||
@public
|
||||
QSearchFieldPrivate* pimpl;
|
||||
}
|
||||
-(void)controlTextDidChange:(NSNotification*)notification;
|
||||
-(void)controlTextDidEndEditing:(NSNotification*)aNotification;
|
||||
@end
|
||||
|
||||
@implementation QSearchFieldDelegate
|
||||
-(void)controlTextDidChange:(NSNotification*)notification {
|
||||
pimpl->textDidChange(toQString([[notification object] stringValue]));
|
||||
}
|
||||
|
||||
-(void)controlTextDidEndEditing:(NSNotification*)notification {
|
||||
pimpl->textDidEndEditing();
|
||||
}
|
||||
@end
|
||||
|
||||
QSearchField::QSearchField(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
NSSearchField *search = [[NSSearchField alloc] init];
|
||||
pimpl = new QSearchFieldPrivate(this, search);
|
||||
|
||||
QSearchFieldDelegate *delegate = [[QSearchFieldDelegate alloc] init];
|
||||
delegate->pimpl = pimpl;
|
||||
[search setDelegate:delegate];
|
||||
|
||||
zeroLayout(search, this);
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
|
||||
layout()->setContentsMargins(2, 0, 2, 0);
|
||||
setStyleSheet( "* { background: #DDE4EB; }" );
|
||||
|
||||
setMinimumSize(layout()->sizeHint().width(), 20);
|
||||
|
||||
[search release];
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
void QSearchField::setText(const QString &text)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
[pimpl->nsSearchField setStringValue:fromQString(text)];
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
void QSearchField::setPlaceholderText(const QString& text)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
[[pimpl->nsSearchField cell] setPlaceholderString:fromQString(text)];
|
||||
[pool drain];
|
||||
}
|
||||
|
||||
void QSearchField::clear()
|
||||
{
|
||||
[pimpl->nsSearchField setStringValue:@""];
|
||||
}
|
||||
|
||||
QString QSearchField::text() const
|
||||
{
|
||||
return toQString([pimpl->nsSearchField stringValue]);
|
||||
}
|
@@ -35,6 +35,7 @@
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "utils/logger.h"
|
||||
#include <globalactionmanager.h>
|
||||
#include "dropjob.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
@@ -46,6 +47,7 @@ AudioControls::AudioControls( QWidget* parent )
|
||||
, ui( new Ui::AudioControls )
|
||||
, m_repeatMode( PlaylistInterface::NoRepeat )
|
||||
, m_shuffled( false )
|
||||
, m_dropAreaExpanded( false )
|
||||
{
|
||||
ui->setupUi( this );
|
||||
setAcceptDrops( true );
|
||||
@@ -89,58 +91,16 @@ 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;"
|
||||
"}"
|
||||
|
||||
"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() ) ); */
|
||||
m_sliderTimeLine.setCurveShape( QTimeLine::LinearCurve );
|
||||
ui->seekSlider->setTimeLine( &m_sliderTimeLine );
|
||||
|
||||
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 ) ) );
|
||||
connect( ui->prevButton, SIGNAL( clicked() ), AudioEngine::instance(), SLOT( previous() ) );
|
||||
@@ -167,6 +127,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 +140,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 );
|
||||
@@ -189,6 +149,46 @@ AudioControls::AudioControls( QWidget* parent )
|
||||
ui->stackedLayout->setSizeConstraint( QLayout::SetFixedSize );
|
||||
|
||||
onPlaybackStopped(); // initial state
|
||||
|
||||
|
||||
m_dragAnimation = new QPropertyAnimation( this, "dropAreaSize", this );
|
||||
m_dragAnimation->setStartValue( 0 );
|
||||
m_dragAnimation->setDuration( 300 );
|
||||
m_dragAnimation->setEasingCurve( QEasingCurve::Linear );
|
||||
connect( m_dragAnimation, SIGNAL( finished() ), SLOT(dragAnimationFinished()));
|
||||
|
||||
m_dropAreaCollapseTimer.setInterval( 300 );
|
||||
m_dropAreaCollapseTimer.setSingleShot( true );
|
||||
connect( &m_dropAreaCollapseTimer, SIGNAL( timeout() ), this, SLOT( collapseDropMenu() ) );
|
||||
|
||||
connect( ui->metaDataDropArea, SIGNAL( dropReceived( QDropEvent* ) ), this, SLOT( dropReceived( QDropEvent* ) ) );
|
||||
connect( ui->metaDataDropArea, SIGNAL( mouseLeft() ), &m_dropAreaCollapseTimer, SLOT( start() ) );
|
||||
|
||||
DropMenuEntry *trackEntry = new DropMenuEntry( QPixmap(":/data/images/drop-song.png" ).scaledToWidth( 32, Qt::SmoothTransformation ),
|
||||
"Track",
|
||||
DropJob::DropFlagTrack );
|
||||
ui->metaDataDropArea->addEntry( trackEntry, true );
|
||||
|
||||
DropMenuEntry *albumEntry = new DropMenuEntry( QPixmap(":/data/images/drop-album.png" ).scaledToWidth( 32, Qt::SmoothTransformation ),
|
||||
"Album",
|
||||
DropJob::DropFlagAlbum );
|
||||
ui->metaDataDropArea->addEntry( albumEntry );
|
||||
|
||||
DropMenuEntry *artistEntry = new DropMenuEntry( QPixmap(":/data/images/drop-all-songs.png" ).scaledToWidth( 32, Qt::SmoothTransformation ),
|
||||
"Artist",
|
||||
DropJob::DropFlagArtist );
|
||||
ui->metaDataDropArea->addEntry( artistEntry );
|
||||
|
||||
DropMenuEntry *localEntry = new DropMenuEntry( QPixmap(":/data/images/drop-local-songs.png" ).scaledToWidth( 32, Qt::SmoothTransformation ),
|
||||
"Local",
|
||||
DropJob::DropFlagAlbum | DropJob::DropFlagLocal );
|
||||
ui->metaDataDropArea->addEntry( localEntry );
|
||||
|
||||
DropMenuEntry *top10Entry = new DropMenuEntry( QPixmap(":/data/images/drop-top-songs.png" ).scaledToWidth( 32, Qt::SmoothTransformation ),
|
||||
"Top 10",
|
||||
DropJob::DropFlagArtist | DropJob::DropFlagTop10 );
|
||||
ui->metaDataDropArea->addEntry( top10Entry );
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -228,8 +228,28 @@ 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();
|
||||
trackInfo["album"] = result->album()->name();
|
||||
@@ -299,14 +319,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 +356,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 +394,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 +415,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,8 +561,37 @@ AudioControls::onTrackClicked()
|
||||
void
|
||||
AudioControls::dragEnterEvent( QDragEnterEvent* e )
|
||||
{
|
||||
if ( GlobalActionManager::instance()->acceptsMimeData( e->mimeData() ) )
|
||||
if ( DropJob::acceptsMimeData( e->mimeData() ) )
|
||||
{
|
||||
e->acceptProposedAction();
|
||||
|
||||
m_dropAreaCollapseTimer.stop();
|
||||
|
||||
DropJob::DropFlags flags = DropJob::DropFlagsNone;
|
||||
|
||||
if ( e->mimeData()->hasFormat( "application/tomahawk.query.list" )
|
||||
|| e->mimeData()->hasFormat( "application/tomahawk.result.list" )
|
||||
|| e->mimeData()->hasFormat( "application/tomahawk.result" ) )
|
||||
flags = DropJob::DropFlagsAll;
|
||||
|
||||
if ( e->mimeData()->hasFormat( "application/tomahawk.metadata.album" ) )
|
||||
flags = DropJob::DropFlagAlbum | DropJob::DropFlagArtist | DropJob::DropFlagLocal | DropJob::DropFlagTop10;
|
||||
|
||||
if ( e->mimeData()->hasFormat( "application/tomahawk.metadata.artist" ) )
|
||||
flags = DropJob::DropFlagArtist | DropJob::DropFlagLocal | DropJob::DropFlagTop10;
|
||||
|
||||
ui->metaDataDropArea->setFilter( flags );
|
||||
|
||||
if( !m_dropAreaExpanded )
|
||||
{
|
||||
m_dragAnimation->stop();
|
||||
m_dragAnimation->setDirection( QAbstractAnimation::Forward );
|
||||
m_dragAnimation->setStartValue( dropAreaSize() );
|
||||
m_dragAnimation->setEndValue( ui->metaDataArea->height() );
|
||||
m_dragAnimation->start();
|
||||
m_dropAreaExpanded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -534,14 +603,44 @@ AudioControls::dragMoveEvent( QDragMoveEvent* /* e */ )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioControls::dragLeaveEvent( QDragLeaveEvent * )
|
||||
{
|
||||
qDebug() << "******************************** dragLeaveEvent" << ui->metaDataDropArea->hovered();
|
||||
if( !ui->metaDataDropArea->hovered() )
|
||||
m_dropAreaCollapseTimer.start();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioControls::collapseDropMenu()
|
||||
{
|
||||
// Check if the menu is hovered now...
|
||||
if( ui->metaDataDropArea->hovered() )
|
||||
return;
|
||||
|
||||
m_dropAreaExpanded = false;
|
||||
|
||||
m_dragAnimation->stop();
|
||||
// m_dragAnimation->setDirection( QAbstractAnimation::Backward );
|
||||
m_dragAnimation->setStartValue( dropAreaSize() );
|
||||
m_dragAnimation->setEndValue( 0 );
|
||||
m_dragAnimation->start();
|
||||
}
|
||||
|
||||
|
||||
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->setDropFlags( ui->metaDataDropArea->activeEntry()->dropFlags() );
|
||||
dj->tracksFromMimeData( e->mimeData() );
|
||||
|
||||
QTimer::singleShot( 0, this, SLOT( collapseDropMenu() ) );
|
||||
|
||||
e->accept();
|
||||
}
|
||||
@@ -551,8 +650,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
|
||||
@@ -597,3 +694,28 @@ AudioControls::onLoveButtonClicked( bool checked )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioControls::dragAnimationFinished()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
AudioControls::dropAreaSize()
|
||||
{
|
||||
return ui->metaDataDropArea->maximumHeight();
|
||||
}
|
||||
|
||||
void
|
||||
AudioControls::setDropAreaSize( int size )
|
||||
{
|
||||
ui->metaDataDropArea->setMaximumHeight( size );
|
||||
ui->metaDataInfoArea->setMaximumHeight( ui->metaDataArea->height() - size );
|
||||
}
|
||||
|
||||
void
|
||||
AudioControls::dropReceived( QDropEvent *event )
|
||||
{
|
||||
dropEvent( event );
|
||||
}
|
||||
|
@@ -20,10 +20,14 @@
|
||||
#define AUDIOCONTROLS_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QTimeLine>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QTimer>
|
||||
|
||||
#include "result.h"
|
||||
#include "playlistinterface.h"
|
||||
#include "infosystem/infosystem.h"
|
||||
#include "utils/dropmenu.h"
|
||||
|
||||
class QDropEvent;
|
||||
class QDragEnterEvent;
|
||||
@@ -36,6 +40,7 @@ namespace Ui
|
||||
class AudioControls : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY( int dropAreaSize READ dropAreaSize WRITE setDropAreaSize )
|
||||
|
||||
public:
|
||||
AudioControls( QWidget* parent = 0 );
|
||||
@@ -53,13 +58,18 @@ protected:
|
||||
void changeEvent( QEvent* e );
|
||||
void dragEnterEvent ( QDragEnterEvent* );
|
||||
void dragMoveEvent ( QDragMoveEvent* );
|
||||
void dragLeaveEvent( QDragLeaveEvent * );
|
||||
void dropEvent ( QDropEvent* );
|
||||
|
||||
int dropAreaSize();
|
||||
void setDropAreaSize( int size );
|
||||
|
||||
private slots:
|
||||
void onPlaybackStarted( const Tomahawk::result_ptr& result );
|
||||
void onPlaybackLoading( const Tomahawk::result_ptr& result );
|
||||
void onPlaybackPaused();
|
||||
void onPlaybackResumed();
|
||||
void onPlaybackSeeked( qint64 msec );
|
||||
void onPlaybackStopped();
|
||||
|
||||
void onPlaybackTimer( qint64 msElapsed );
|
||||
@@ -79,19 +89,26 @@ private slots:
|
||||
void droppedTracks( QList<Tomahawk::query_ptr> );
|
||||
|
||||
void socialActionsLoaded();
|
||||
|
||||
void collapseDropMenu();
|
||||
void dragAnimationFinished();
|
||||
void dropReceived( QDropEvent *event );
|
||||
|
||||
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;
|
||||
|
||||
QPropertyAnimation *m_dragAnimation;
|
||||
bool m_dropAreaExpanded;
|
||||
QTimer m_dropAreaCollapseTimer;
|
||||
};
|
||||
|
||||
#endif // AUDIOCONTROLS_H
|
||||
|
@@ -84,14 +84,14 @@
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<item row="0" column="0">
|
||||
<widget class="ImageButton" name="playPauseButton">
|
||||
<property name="text">
|
||||
<string>Play</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<item row="0" column="0">
|
||||
<widget class="ImageButton" name="pauseButton">
|
||||
<property name="text">
|
||||
<string>Pause</string>
|
||||
@@ -125,248 +125,269 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="metaDataArea" native="true">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>74</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="coverImage">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>58</width>
|
||||
<height>58</height>
|
||||
</size>
|
||||
</property>
|
||||
<widget class="DropMenu" name="metaDataDropArea" native="true">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>58</width>
|
||||
<height>58</height>
|
||||
<width>16777215</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>4</number>
|
||||
<widget class="QWidget" name="metaDataInfoArea" native="true">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>74</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,0,0">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="trackLabelLayout">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QueryLabel" name="artistTrackLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>PointingHandCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Artist</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QueryLabel" name="albumLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>PointingHandCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Album</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>4</width>
|
||||
<height>8</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="ImageButton" name="loveButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>PointingHandCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>love</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>13</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="ownerLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>7</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Owner</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>4</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="timeLabel">
|
||||
<property name="text">
|
||||
<string>Time</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="seekSlider">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="timeLeftLabel">
|
||||
<property name="text">
|
||||
<string>Time Left</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="coverImage">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>58</width>
|
||||
<height>58</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>58</width>
|
||||
<height>58</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="1,0,0,0">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="trackLabelLayout">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QueryLabel" name="artistTrackLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>PointingHandCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Artist</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QueryLabel" name="albumLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>PointingHandCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Album</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>4</width>
|
||||
<height>8</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="ImageButton" name="loveButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>PointingHandCursor</cursorShape>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>love</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>13</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="ownerLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>7</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Owner</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>4</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="timeLabel">
|
||||
<property name="text">
|
||||
<string>Time</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="SeekSlider" name="seekSlider">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="timeLeftLabel">
|
||||
<property name="text">
|
||||
<string>Time Left</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<zorder>metaDataInfoArea</zorder>
|
||||
<zorder>metaDataDropArea</zorder>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
@@ -489,7 +510,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="volumeSlider">
|
||||
<widget class="SeekSlider" name="volumeSlider">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
@@ -529,6 +550,11 @@
|
||||
</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>
|
||||
@@ -539,6 +565,12 @@
|
||||
<extends>QLabel</extends>
|
||||
<header>utils/querylabel.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>DropMenu</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>utils/dropmenu.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
@@ -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
|
||||
@@ -173,18 +182,30 @@ set( libSources
|
||||
utils/spotifyparser.cpp
|
||||
utils/rdioparser.cpp
|
||||
utils/shortenedlinkparser.cpp
|
||||
utils/stylehelper.cpp
|
||||
utils/dropmenu.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
|
||||
@@ -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
|
||||
@@ -351,18 +381,31 @@ set( libHeaders
|
||||
utils/spotifyparser.h
|
||||
utils/rdioparser.h
|
||||
utils/shortenedlinkparser.h
|
||||
utils/stylehelper.h
|
||||
utils/dropmenu.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
|
||||
)
|
||||
@@ -383,12 +426,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
|
||||
)
|
||||
|
||||
include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/.. ..
|
||||
@@ -406,16 +452,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 +499,9 @@ IF( APPLE )
|
||||
SET( libSources ${libSources}
|
||||
infosystem/infoplugins/mac/adium.mm
|
||||
infosystem/infoplugins/mac/adiumplugin.cpp
|
||||
widgets/maclineedit.mm
|
||||
utils/tomahawkutils_mac.mm )
|
||||
|
||||
SET( libHeaders ${libHeaders}
|
||||
widgets/maclineedit.h
|
||||
infosystem/infoplugins/mac/adium.h
|
||||
infosystem/infoplugins/mac/adiumplugin.h )
|
||||
|
||||
|
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
|
@@ -137,7 +137,7 @@ AudioEngine::play()
|
||||
QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo ) );
|
||||
}
|
||||
else
|
||||
loadNextTrack();
|
||||
next();
|
||||
}
|
||||
|
||||
|
||||
@@ -188,55 +188,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 +343,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 +511,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 )
|
||||
@@ -510,7 +557,7 @@ AudioEngine::playlistNextTrackReady()
|
||||
return;
|
||||
|
||||
m_waitingOnNewTrack = false;
|
||||
next();
|
||||
loadNextTrack();
|
||||
}
|
||||
|
||||
|
||||
@@ -562,7 +609,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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -594,10 +648,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 )
|
||||
|
@@ -69,6 +69,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 +81,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 ); }
|
||||
@@ -102,6 +110,8 @@ signals:
|
||||
void paused();
|
||||
void resumed();
|
||||
|
||||
void seeked( qint64 ms );
|
||||
|
||||
void stateChanged( AudioState newState, AudioState oldState );
|
||||
void volumeChanged( int volume /* in percent */ );
|
||||
|
||||
|
94
src/libtomahawk/context/ContextPage.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
/* === 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;
|
||||
|
||||
QGraphicsWebView* testWebView = qobject_cast<QGraphicsWebView*>( page->widget() );
|
||||
if ( testWebView )
|
||||
{
|
||||
setContentsMargins( 4, 4, 4, 4 );
|
||||
}
|
||||
|
||||
QGraphicsLinearLayout* layout = new QGraphicsLinearLayout();
|
||||
layout->setContentsMargins( 4, 20, 4, 4 );
|
||||
layout->addItem( page->widget() );
|
||||
setLayout( layout );
|
||||
|
||||
page->widget()->installEventFilter( this );
|
||||
page->widget()->installSceneEventFilter( 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 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -74,8 +74,7 @@ DatabaseCommand_AllAlbums::execForArtist( DatabaseImpl* dbi )
|
||||
al << album;
|
||||
}
|
||||
|
||||
if ( al.count() )
|
||||
emit albums( al, data() );
|
||||
emit albums( al, data() );
|
||||
emit done();
|
||||
}
|
||||
|
||||
@@ -124,8 +123,7 @@ DatabaseCommand_AllAlbums::execForCollection( DatabaseImpl* dbi )
|
||||
al << album;
|
||||
}
|
||||
|
||||
if ( al.count() )
|
||||
emit albums( al, data() );
|
||||
emit albums( al, data() );
|
||||
emit done();
|
||||
}
|
||||
|
||||
|
@@ -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() )
|
||||
|
554
src/libtomahawk/dropjob.cpp
Normal file
@@ -0,0 +1,554 @@
|
||||
/* === 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 )
|
||||
, m_dropFlags( DropFlagsNone )
|
||||
{
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
if( getWholeArtists )
|
||||
m_dropFlags |= DropFlagArtist;
|
||||
else
|
||||
m_dropFlags &= !DropFlagArtist;
|
||||
}
|
||||
|
||||
void
|
||||
DropJob::setGetWholeAlbums( bool getWholeAlbums )
|
||||
{
|
||||
if ( getWholeAlbums )
|
||||
m_dropFlags |= DropFlagAlbum;
|
||||
else
|
||||
m_dropFlags &= !DropFlagAlbum;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DropJob::setGetTop10( bool top10 )
|
||||
{
|
||||
if( top10 )
|
||||
m_dropFlags |= DropFlagTop10;
|
||||
else
|
||||
m_dropFlags &= !DropFlagTop10;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DropJob::setOnlyLocal( bool onlyLocal )
|
||||
{
|
||||
if( onlyLocal )
|
||||
m_dropFlags |= DropFlagLocal;
|
||||
else
|
||||
m_dropFlags &= !DropFlagLocal;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DropJob::setAllowDuplicates( bool allowDuplicates )
|
||||
{
|
||||
if( allowDuplicates )
|
||||
m_dropFlags |= DropFlagAllowDuplicates;
|
||||
else
|
||||
m_dropFlags &= !DropFlagAllowDuplicates;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DropJob::setDropFlags( DropFlags flags )
|
||||
{
|
||||
m_dropFlags = flags;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DropJob::tracksFromMimeData( const QMimeData* data )
|
||||
{
|
||||
|
||||
|
||||
parseMimeData( data );
|
||||
|
||||
if ( m_queryCount == 0 )
|
||||
{
|
||||
if ( m_dropFlags.testFlag( DropFlagLocal ) )
|
||||
removeRemoteSources();
|
||||
|
||||
if ( !m_dropFlags.testFlag( DropFlagAllowDuplicates ) )
|
||||
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_dropFlags.testFlag( DropFlagTop10 ) )
|
||||
{
|
||||
getTopTen( query->data()->artist() );
|
||||
}
|
||||
else if ( m_dropFlags.testFlag( DropFlagArtist ) )
|
||||
{
|
||||
queries << getArtist( query->data()->artist() );
|
||||
}
|
||||
else if ( m_dropFlags.testFlag( DropFlagAlbum ) )
|
||||
{
|
||||
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_dropFlags.testFlag( DropFlagTop10 ) )
|
||||
{
|
||||
getTopTen( q->artist() );
|
||||
}
|
||||
else if ( m_dropFlags.testFlag( DropFlagArtist ) )
|
||||
{
|
||||
queries << getArtist( q->artist() );
|
||||
}
|
||||
else if ( m_dropFlags.testFlag( DropFlagAlbum ) )
|
||||
{
|
||||
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_dropFlags.testFlag( DropFlagTop10 ) )
|
||||
getTopTen( artist );
|
||||
else if ( m_dropFlags.testFlag( DropFlagArtist ) )
|
||||
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_dropFlags.testFlag( DropFlagTop10 ) )
|
||||
getTopTen( artist );
|
||||
else
|
||||
queries << getArtist( 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_dropFlags.testFlag( DropFlagLocal ) )
|
||||
removeRemoteSources();
|
||||
|
||||
if ( !m_dropFlags.testFlag( DropFlagAllowDuplicates ) )
|
||||
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++;
|
||||
|
||||
}
|
134
src/libtomahawk/dropjob.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/* === 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 DropJob
|
||||
* Allows you to process dropped mimedata in different ways:
|
||||
* Configure the DropJob using setDropFlags() or the set*() functions to do
|
||||
* what you want and then feed it with MimeMata. Connect to the tracks() signal
|
||||
* to receive the results.
|
||||
*
|
||||
* Possible configuration flags are:
|
||||
* - DropFlagTrack: Get the dropped track (only valid if the dropped item is acutally a track)
|
||||
* - DropFlagAlbum: Get this album (only valid if the dropped item is an album or a track with album information)
|
||||
* - DropFlagArtist: Get this artist
|
||||
* - DropFlagTop10: Query the Top 10 for this artist in the Network
|
||||
* - DropFlagLocal: Only get local items (Filters out all remote ones)
|
||||
* - DropFlagAllowDuplicates: Allow duplicate results, e.g. same song from different sources.
|
||||
*
|
||||
* Note: The largest possible set of the configured Flags applies. E.g. Artist is greater than Album.
|
||||
* If you set both of them only the album will be fetched. Requesting the Top 10 items always results in a
|
||||
* query for the whole artist. It is not possible to e.g. request the Top 10 tracks of a given album.
|
||||
*
|
||||
* If you configure nothing or dropping incompatible data (e.g. configured DropTrack but dropping an album),
|
||||
* the DropJob will do this default actions:
|
||||
* - Get this track for dropped tracks
|
||||
* - Get whole album for dropped albums
|
||||
* - Get whole artist for dropped artists
|
||||
*/
|
||||
|
||||
class DLLEXPORT DropJob : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum DropFlag
|
||||
{
|
||||
DropFlagsNone = 0x00,
|
||||
DropFlagTrack = 0x01,
|
||||
DropFlagAlbum = 0x02,
|
||||
DropFlagArtist = 0x04,
|
||||
DropFlagTop10 = 0x08,
|
||||
DropFlagLocal = 0x10,
|
||||
DropFlagAllowDuplicates = 0x20,
|
||||
DropFlagsAll = 0xff
|
||||
};
|
||||
Q_DECLARE_FLAGS( DropFlags, DropFlag )
|
||||
|
||||
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 setDropFlags( DropFlags flags );
|
||||
|
||||
void setGetWholeArtists( bool getWholeArtists );
|
||||
void setGetWholeAlbums( bool getWholeAlbums );
|
||||
void setGetTop10( bool top10 );
|
||||
void setOnlyLocal( bool onlyLocal );
|
||||
void setAllowDuplicates( bool allowDuplicates );
|
||||
|
||||
void tracksFromMimeData( const QMimeData* data );
|
||||
|
||||
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;
|
||||
DropFlags m_dropFlags;
|
||||
|
||||
QList< Tomahawk::query_ptr > m_resultList;
|
||||
};
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS( DropJob::DropFlags )
|
||||
|
||||
#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
|
||||
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
|
@@ -33,6 +33,8 @@
|
||||
#include <lastfm/ws.h>
|
||||
#include <lastfm/XmlQuery>
|
||||
|
||||
#include <qjson/parser.h>
|
||||
|
||||
using namespace Tomahawk::InfoSystem;
|
||||
|
||||
static QString
|
||||
@@ -47,7 +49,7 @@ LastFmPlugin::LastFmPlugin()
|
||||
: InfoPlugin()
|
||||
, m_scrobbler( 0 )
|
||||
{
|
||||
m_supportedGetTypes << InfoAlbumCoverArt << InfoArtistImages << InfoArtistSimilars << InfoArtistSongs;
|
||||
m_supportedGetTypes << InfoAlbumCoverArt << InfoArtistImages << InfoArtistSimilars << InfoArtistSongs << InfoChartArtists << InfoChartTracks << InfoChartCapabilities;
|
||||
m_supportedPushTypes << InfoSubmitScrobble << InfoSubmitNowPlaying << InfoLove << InfoUnLove;
|
||||
|
||||
/*
|
||||
@@ -87,6 +89,7 @@ LastFmPlugin::~LastFmPlugin()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
delete m_scrobbler;
|
||||
m_scrobbler = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -147,6 +150,16 @@ LastFmPlugin::getInfo( uint requestId, Tomahawk::InfoSystem::InfoRequestData req
|
||||
fetchTopTracks( requestId, requestData );
|
||||
break;
|
||||
|
||||
case InfoChartArtists:
|
||||
fetchChartArtists( requestId, requestData );
|
||||
break;
|
||||
|
||||
case InfoChartTracks:
|
||||
fetchChartTracks( requestId, requestData );
|
||||
break;
|
||||
case InfoChartCapabilities:
|
||||
fetchChartCapabilities( requestId, requestData );
|
||||
break;
|
||||
default:
|
||||
dataError( requestId, requestData );
|
||||
}
|
||||
@@ -298,6 +311,57 @@ LastFmPlugin::fetchTopTracks( uint requestId, Tomahawk::InfoSystem::InfoRequestD
|
||||
emit getCachedInfo( requestId, criteria, 2419200000, requestData );
|
||||
}
|
||||
|
||||
void
|
||||
LastFmPlugin::fetchChartArtists( 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( "country" ) )
|
||||
{
|
||||
criteria["country"] = hash["country"];
|
||||
}
|
||||
|
||||
emit getCachedInfo( requestId, criteria, 2419200000, requestData );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmPlugin::fetchChartTracks( 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( "country" ) )
|
||||
{
|
||||
criteria["country"] = hash["country"];
|
||||
}
|
||||
|
||||
emit getCachedInfo( requestId, criteria, 2419200000, 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, 2419200000, requestData );
|
||||
}
|
||||
|
||||
void
|
||||
LastFmPlugin::fetchCoverArt( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData )
|
||||
@@ -356,6 +420,65 @@ LastFmPlugin::notInCacheSlot( uint requestId, QHash<QString, QString> criteria,
|
||||
|
||||
switch ( requestData.type )
|
||||
{
|
||||
case InfoChartArtists:
|
||||
{
|
||||
tDebug() << "LastfmPlugin: InfoChartArtists notin cache, fetching";
|
||||
QMap<QString, QString> args;
|
||||
if( criteria.contains( "country" ) ) {
|
||||
args["method"] = "geo.getTopArtists";
|
||||
args["country"] = criteria["country"];
|
||||
} else {
|
||||
args["method"] = "chart.getTopArtists";
|
||||
}
|
||||
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( chartTopArtistsReturned() ) );
|
||||
return;
|
||||
}
|
||||
|
||||
case InfoChartTracks:
|
||||
{
|
||||
tDebug() << "LastfmPlugin: InfoChartTracks not in cache, fetching";
|
||||
QMap<QString, QString> args;
|
||||
if( criteria.contains( "country" ) ) {
|
||||
args["method"] = "geo.getTopTracks";
|
||||
args["country"] = criteria["country"];
|
||||
} else {
|
||||
args["method"] = "chart.getTopTracks";
|
||||
}
|
||||
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( chartTopTracksReturned() ) );
|
||||
return;
|
||||
}
|
||||
|
||||
case InfoChartCapabilities:
|
||||
{
|
||||
tDebug() << "LastfmPlugin: InfoChartCapabilities not in cache, fetching";
|
||||
QString json("{'Last.fm': {'Tracks': ['Top Tracks','Hyped Tracks','Most Loved Tracks'],"
|
||||
"'Artists': ['Top Artists', 'Hyped Artists']}}");
|
||||
json.replace("'", "\"");
|
||||
QJson::Parser parser;
|
||||
bool ok = false;
|
||||
QVariantMap result = parser.parse (json.toUtf8(), &ok).toMap();
|
||||
if(!ok) {
|
||||
tDebug() << "Lastfm Plugin: parsing json failed";
|
||||
return;
|
||||
}
|
||||
emit info(
|
||||
requestId,
|
||||
requestData,
|
||||
result
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
case InfoArtistSimilars:
|
||||
{
|
||||
lastfm::Artist a( criteria["artist"] );
|
||||
@@ -447,6 +570,72 @@ LastFmPlugin::similarArtistsReturned()
|
||||
emit updateCache( criteria, 2419200000, requestData.type, returnedData );
|
||||
}
|
||||
|
||||
void
|
||||
LastFmPlugin::chartTopArtistsReturned()
|
||||
{
|
||||
tDebug() << "LastfmPlugin: InfoChartArtists data returned!";
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
|
||||
QList<lastfm::Artist> list = lastfm::Artist::list( reply );
|
||||
QStringList al;
|
||||
|
||||
tDebug() << "\tgot " << list.size() << " artists";
|
||||
|
||||
foreach ( const lastfm::Artist& a, list )
|
||||
al << a.toString();
|
||||
|
||||
QVariantMap returnedData;
|
||||
returnedData["artists"] = al;
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
|
||||
|
||||
emit info(
|
||||
reply->property( "requestId" ).toUInt(),
|
||||
requestData,
|
||||
returnedData
|
||||
);
|
||||
|
||||
Tomahawk::InfoSystem::InfoCriteriaHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash>();
|
||||
Tomahawk::InfoSystem::InfoCriteriaHash criteria;
|
||||
if( origData.contains("country") )
|
||||
criteria["country"] = origData["country"];
|
||||
emit updateCache( criteria, 2419200000, requestData.type, returnedData );
|
||||
}
|
||||
|
||||
void
|
||||
LastFmPlugin::chartTopTracksReturned()
|
||||
{
|
||||
tDebug() << "LastfmPlugin: InfoChartTracks data returned!";
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
|
||||
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() << "\tgot " << top_tracks.size() << " tracks";
|
||||
|
||||
QVariantMap returnedData;
|
||||
returnedData["tracks"] = QVariant::fromValue( top_tracks );
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData = reply->property( "requestData" ).value< Tomahawk::InfoSystem::InfoRequestData >();
|
||||
|
||||
emit info(
|
||||
reply->property( "requestId" ).toUInt(),
|
||||
requestData,
|
||||
returnedData
|
||||
);
|
||||
|
||||
Tomahawk::InfoSystem::InfoCriteriaHash origData = requestData.input.value< Tomahawk::InfoSystem::InfoCriteriaHash>();
|
||||
Tomahawk::InfoSystem::InfoCriteriaHash criteria;
|
||||
if( origData.contains("country") )
|
||||
criteria["country"] = origData["country"];
|
||||
emit updateCache( criteria, 0, requestData.type, returnedData );
|
||||
}
|
||||
|
||||
void
|
||||
LastFmPlugin::topTracksReturned()
|
||||
@@ -468,7 +657,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 +793,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 +867,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,8 @@ public slots:
|
||||
void artistImagesReturned();
|
||||
void similarArtistsReturned();
|
||||
void topTracksReturned();
|
||||
void chartTopArtistsReturned();
|
||||
void chartTopTracksReturned();
|
||||
|
||||
void namChangedSlot( QNetworkAccessManager *nam );
|
||||
|
||||
@@ -66,6 +68,9 @@ 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 fetchChartArtists( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchChartTracks( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void fetchChartCapabilities( uint requestId, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
|
||||
void createScrobbler();
|
||||
void nowPlaying( const QVariant &input );
|
||||
@@ -74,6 +79,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,20 @@ 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
|
||||
*/
|
||||
InfoChartArtists = 51,
|
||||
InfoChartAlbums = 52, /*!< Documentation for InfoChartAlbums */
|
||||
InfoChartTracks = 53,
|
||||
|
||||
InfoMiscTopHotttness = 60,
|
||||
InfoMiscTopTerms = 61,
|
||||
|
||||
@@ -103,7 +117,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 +132,11 @@ struct InfoRequestData {
|
||||
QVariantMap customData;
|
||||
};
|
||||
|
||||
struct ArtistTrackPair {
|
||||
QString artist;
|
||||
QString track;
|
||||
};
|
||||
|
||||
typedef QMap< InfoType, QVariant > InfoTypeMap;
|
||||
typedef QMap< InfoType, uint > InfoTimeoutMap;
|
||||
typedef QMap< QString, QMap< QString, QString > > InfoGenericMap;
|
||||
@@ -160,6 +178,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 +220,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 +236,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 +246,8 @@ private:
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline uint qHash( Tomahawk::InfoSystem::InfoCriteriaHash hash )
|
||||
{
|
||||
QCryptographicHash md5( QCryptographicHash::Md5 );
|
||||
@@ -221,5 +273,7 @@ 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( QList<Tomahawk::InfoSystem::ArtistTrackPair> );
|
||||
|
||||
#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;
|
||||
|
@@ -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 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -63,10 +63,11 @@ public:
|
||||
virtual QStringList mimeTypes() const;
|
||||
virtual Qt::ItemFlags flags( const QModelIndex& index ) const;
|
||||
|
||||
void addCollection( const Tomahawk::collection_ptr& collection );
|
||||
void addFilteredCollection( const Tomahawk::collection_ptr& collection, unsigned int amount, DatabaseCommand_AllAlbums::SortOrder order );
|
||||
|
||||
void clear();
|
||||
void addCollection( const Tomahawk::collection_ptr& collection, bool overwrite = false );
|
||||
void addFilteredCollection( const Tomahawk::collection_ptr& collection, unsigned int amount, DatabaseCommand_AllAlbums::SortOrder order, bool overwrite = false );
|
||||
|
||||
bool getCover( const QModelIndex& index );
|
||||
|
||||
virtual QString title() const { return m_title; }
|
||||
virtual QString description() const { return m_description; }
|
||||
@@ -95,8 +96,6 @@ signals:
|
||||
|
||||
void trackCountChanged( unsigned int tracks );
|
||||
|
||||
protected:
|
||||
|
||||
private slots:
|
||||
void onDataChanged();
|
||||
|
||||
@@ -109,6 +108,9 @@ private:
|
||||
|
||||
QString m_title;
|
||||
QString m_description;
|
||||
bool m_overwriteOnAdd;
|
||||
|
||||
QHash<qlonglong, QPersistentModelIndex> m_coverHash;
|
||||
};
|
||||
|
||||
#endif // ALBUMMODEL_H
|
||||
|
@@ -30,8 +30,6 @@
|
||||
#include "viewmanager.h"
|
||||
#include "utils/logger.h"
|
||||
|
||||
static QString s_tmInfoIdentifier = QString( "ALBUMMODEL" );
|
||||
|
||||
#define SCROLL_TIMEOUT 280
|
||||
|
||||
using namespace Tomahawk;
|
||||
@@ -164,51 +162,13 @@ AlbumView::onScrollTimeout()
|
||||
started = true;
|
||||
done = false;
|
||||
|
||||
AlbumItem* item = m_model->itemFromIndex( m_proxyModel->mapToSource( idx ) );
|
||||
if ( !item )
|
||||
if ( !m_model->getCover( m_proxyModel->mapToSource( idx ) ) )
|
||||
break;
|
||||
if ( !item->cover.isNull() )
|
||||
break;
|
||||
|
||||
// qDebug() << "Need cover for:" << item->album()->artist()->name() << item->album()->name();
|
||||
Tomahawk::InfoSystem::InfoCriteriaHash trackInfo;
|
||||
trackInfo["artist"] = item->album()->artist()->name();
|
||||
trackInfo["album"] = item->album()->name();
|
||||
trackInfo["pptr"] = QString::number( (qlonglong)item );
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlbumView::dragEnterEvent( QDragEnterEvent* event )
|
||||
{
|
||||
QListView::dragEnterEvent( event );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlbumView::dragMoveEvent( QDragMoveEvent* event )
|
||||
{
|
||||
QListView::dragMoveEvent( event );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlbumView::dropEvent( QDropEvent* event )
|
||||
{
|
||||
QListView::dropEvent( event );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AlbumView::paintEvent( QPaintEvent* event )
|
||||
{
|
||||
@@ -227,14 +187,30 @@ AlbumView::onFilterChanged( const QString& )
|
||||
void
|
||||
AlbumView::startDrag( Qt::DropActions supportedActions )
|
||||
{
|
||||
Q_UNUSED( supportedActions );
|
||||
}
|
||||
QList<QPersistentModelIndex> pindexes;
|
||||
QModelIndexList indexes;
|
||||
foreach( const QModelIndex& idx, selectedIndexes() )
|
||||
{
|
||||
if ( ( m_proxyModel->flags( idx ) & Qt::ItemIsDragEnabled ) )
|
||||
{
|
||||
indexes << idx;
|
||||
pindexes << idx;
|
||||
}
|
||||
}
|
||||
|
||||
if ( indexes.count() == 0 )
|
||||
return;
|
||||
|
||||
// Inspired from dolphin's draganddrophelper.cpp
|
||||
QPixmap
|
||||
AlbumView::createDragPixmap( int itemCount ) const
|
||||
{
|
||||
Q_UNUSED( itemCount );
|
||||
return QPixmap();
|
||||
qDebug() << "Dragging" << indexes.count() << "indexes";
|
||||
QMimeData* data = m_proxyModel->mimeData( indexes );
|
||||
if ( !data )
|
||||
return;
|
||||
|
||||
QDrag* drag = new QDrag( this );
|
||||
drag->setMimeData( data );
|
||||
const QPixmap p = TomahawkUtils::createDragPixmap( TomahawkUtils::MediaTypeAlbum, indexes.count() );
|
||||
drag->setPixmap( p );
|
||||
drag->setHotSpot( QPoint( -20, -20 ) );
|
||||
|
||||
Qt::DropAction action = drag->exec( supportedActions, Qt::CopyAction );
|
||||
}
|
||||
|
@@ -60,9 +60,6 @@ public slots:
|
||||
|
||||
protected:
|
||||
virtual void startDrag( Qt::DropActions supportedActions );
|
||||
virtual void dragEnterEvent( QDragEnterEvent* event );
|
||||
virtual void dragMoveEvent( QDragMoveEvent* event );
|
||||
virtual void dropEvent( QDropEvent* event );
|
||||
|
||||
void paintEvent( QPaintEvent* event );
|
||||
|
||||
@@ -73,8 +70,6 @@ private slots:
|
||||
void onScrollTimeout();
|
||||
|
||||
private:
|
||||
QPixmap createDragPixmap( int itemCount ) const;
|
||||
|
||||
AlbumModel* m_model;
|
||||
AlbumProxyModel* m_proxyModel;
|
||||
// PlaylistItemDelegate* m_delegate;
|
||||
|
@@ -32,8 +32,6 @@
|
||||
#include "viewmanager.h"
|
||||
#include "utils/logger.h"
|
||||
|
||||
static QString s_tmInfoIdentifier = QString( "TREEMODEL" );
|
||||
|
||||
#define SCROLL_TIMEOUT 280
|
||||
|
||||
using namespace Tomahawk;
|
||||
@@ -131,6 +129,17 @@ ArtistView::setTreeModel( TreeModel* model )
|
||||
connect( m_proxyModel, SIGNAL( rowsInserted( QModelIndex, int, int ) ), SLOT( onViewChanged() ) );
|
||||
|
||||
setAcceptDrops( false );
|
||||
|
||||
if ( model->columnStyle() == TreeModel::TrackOnly )
|
||||
{
|
||||
setHeaderHidden( true );
|
||||
setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
|
||||
}
|
||||
else
|
||||
{
|
||||
setHeaderHidden( false );
|
||||
setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -144,7 +153,7 @@ ArtistView::onItemActivated( const QModelIndex& index )
|
||||
ViewManager::instance()->show( item->artist() );
|
||||
else if ( !item->album().isNull() )
|
||||
ViewManager::instance()->show( item->album() );
|
||||
else if ( !item->result().isNull() )
|
||||
else if ( !item->result().isNull() && item->result()->isOnline() )
|
||||
{
|
||||
m_model->setCurrentItem( item->index );
|
||||
AudioEngine::instance()->playItem( m_proxyModel, item->result() );
|
||||
@@ -180,6 +189,11 @@ ArtistView::resizeEvent( QResizeEvent* event )
|
||||
{
|
||||
QTreeView::resizeEvent( event );
|
||||
m_header->checkState();
|
||||
|
||||
if ( model()->columnCount( QModelIndex() ) == 1 )
|
||||
{
|
||||
m_header->resizeSection( 0, event->size().width() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -215,7 +229,15 @@ ArtistView::startDrag( Qt::DropActions supportedActions )
|
||||
|
||||
QDrag* drag = new QDrag( this );
|
||||
drag->setMimeData( data );
|
||||
const QPixmap p = TomahawkUtils::createDragPixmap( indexes.count() );
|
||||
|
||||
QPixmap p;
|
||||
if ( data->hasFormat( "application/tomahawk.metadata.artist" ) )
|
||||
p = TomahawkUtils::createDragPixmap( TomahawkUtils::MediaTypeArtist, indexes.count() );
|
||||
else if ( data->hasFormat( "application/tomahawk.metadata.album" ) )
|
||||
p = TomahawkUtils::createDragPixmap( TomahawkUtils::MediaTypeAlbum, indexes.count() );
|
||||
else
|
||||
p = TomahawkUtils::createDragPixmap( TomahawkUtils::MediaTypeTrack, indexes.count() );
|
||||
|
||||
drag->setPixmap( p );
|
||||
drag->setHotSpot( QPoint( -20, -20 ) );
|
||||
|
||||
@@ -257,23 +279,7 @@ ArtistView::onScrollTimeout()
|
||||
|
||||
for ( int i = left.row(); i < max; i++ )
|
||||
{
|
||||
TreeModelItem* item = m_model->itemFromIndex( m_proxyModel->mapToSource( m_proxyModel->index( i, 0 ) ) );
|
||||
if ( item->artist().isNull() )
|
||||
continue;
|
||||
if ( !item->cover.isNull() )
|
||||
continue;
|
||||
|
||||
Tomahawk::InfoSystem::InfoCriteriaHash trackInfo;
|
||||
trackInfo["artist"] = item->artist()->name();
|
||||
trackInfo["pptr"] = QString::number( (qlonglong)item );
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData;
|
||||
requestData.caller = s_tmInfoIdentifier;
|
||||
requestData.type = Tomahawk::InfoSystem::InfoArtistImages;
|
||||
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo );
|
||||
requestData.customData = QVariantMap();
|
||||
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo( requestData );
|
||||
m_model->getCover( m_proxyModel->mapToSource( m_proxyModel->index( i, 0 ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,5 +349,8 @@ ArtistView::jumpToCurrentTrack()
|
||||
QString
|
||||
ArtistView::guid() const
|
||||
{
|
||||
return QString( "artistview/%1" ).arg( m_model->columnCount( QModelIndex() ) );
|
||||
if ( m_guid.isEmpty() )
|
||||
m_guid = QString( "artistview/%1" ).arg( m_model->columnCount( QModelIndex() ) );
|
||||
|
||||
return m_guid;
|
||||
}
|
||||
|
@@ -40,6 +40,9 @@ public:
|
||||
explicit ArtistView( QWidget* parent = 0 );
|
||||
~ArtistView();
|
||||
|
||||
virtual QString guid() const;
|
||||
virtual void setGuid( const QString& guid ) { m_guid = guid; }
|
||||
|
||||
void setProxyModel( TreeProxyModel* model );
|
||||
|
||||
TreeModel* model() const { return m_model; }
|
||||
@@ -64,8 +67,6 @@ public:
|
||||
|
||||
virtual bool jumpToCurrentTrack();
|
||||
|
||||
QString guid() const;
|
||||
|
||||
public slots:
|
||||
void onItemActivated( const QModelIndex& index );
|
||||
|
||||
@@ -96,6 +97,7 @@ private:
|
||||
|
||||
bool m_showModes;
|
||||
QTimer m_timer;
|
||||
mutable QString m_guid;
|
||||
};
|
||||
|
||||
#endif // ARTISTVIEW_H
|
||||
|
@@ -26,12 +26,14 @@
|
||||
#include "playlist.h"
|
||||
#include "typedefs.h"
|
||||
#include "playlist/dynamic/DynamicControl.h"
|
||||
#include "playlist/dynamic/DynamicPlaylistRevision.h"
|
||||
|
||||
#include "dllmacro.h"
|
||||
|
||||
class DatabaseCommand_LoadAllDynamicPlaylists;
|
||||
class DatabaseCommand_SetDynamicPlaylistRevision;
|
||||
class DatabaseCommand_CreateDynamicPlaylist;
|
||||
class DatabaseCommand_LoadAllSortedPlaylists;
|
||||
class DatabaseCollection;
|
||||
|
||||
namespace Tomahawk {
|
||||
@@ -43,27 +45,6 @@ class DatabaseCommand_LoadDynamicPlaylist;
|
||||
* It uses normal PlaylistEntries but also has a mode, a generator, and a list of controls
|
||||
*/
|
||||
|
||||
struct DLLEXPORT DynamicPlaylistRevision : PlaylistRevision
|
||||
{
|
||||
public:
|
||||
|
||||
QList< dyncontrol_ptr > controls;
|
||||
Tomahawk::GeneratorMode mode;
|
||||
QString type;
|
||||
|
||||
DynamicPlaylistRevision( const PlaylistRevision& other )
|
||||
{
|
||||
revisionguid = other.revisionguid;
|
||||
oldrevisionguid = other.oldrevisionguid;
|
||||
newlist = other.newlist;
|
||||
added = other.added;
|
||||
removed = other.removed;
|
||||
applied = other.applied;
|
||||
}
|
||||
|
||||
DynamicPlaylistRevision() {}
|
||||
};
|
||||
|
||||
struct DynQueueItem : RevisionQueueItem
|
||||
{
|
||||
QString type;
|
||||
@@ -86,6 +67,7 @@ class DLLEXPORT DynamicPlaylist : public Playlist
|
||||
friend class ::DatabaseCommand_SetDynamicPlaylistRevision;
|
||||
friend class ::DatabaseCommand_CreateDynamicPlaylist;
|
||||
friend class Tomahawk::DatabaseCommand_LoadDynamicPlaylist;
|
||||
friend class ::DatabaseCommand_LoadAllSortedPlaylists;
|
||||
friend class ::DatabaseCollection; /// :-(
|
||||
|
||||
public:
|
||||
|
51
src/libtomahawk/playlist/dynamic/DynamicPlaylistRevision.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* === 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 DYNAMIC_PLAYLIST_REVISION_H
|
||||
#define DYNAMIC_PLAYLIST_REVISION_H
|
||||
|
||||
#include "playlist.h"
|
||||
#include "dllmacro.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
struct DLLEXPORT DynamicPlaylistRevision : PlaylistRevision
|
||||
{
|
||||
public:
|
||||
|
||||
QList< dyncontrol_ptr > controls;
|
||||
Tomahawk::GeneratorMode mode;
|
||||
QString type;
|
||||
|
||||
DynamicPlaylistRevision( const PlaylistRevision& other )
|
||||
{
|
||||
revisionguid = other.revisionguid;
|
||||
oldrevisionguid = other.oldrevisionguid;
|
||||
newlist = other.newlist;
|
||||
added = other.added;
|
||||
removed = other.removed;
|
||||
applied = other.applied;
|
||||
}
|
||||
|
||||
DynamicPlaylistRevision() {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@@ -412,7 +412,7 @@ query_ptr
|
||||
EchonestGenerator::queryFromSong( const Echonest::Song& song )
|
||||
{
|
||||
// track[ "album" ] = song.release(); // TODO should we include it? can be quite specific
|
||||
return Query::get( song.artistName(), song.title(), QString(), uuid() );
|
||||
return Query::get( song.artistName(), song.title(), QString(), uuid(), false );
|
||||
}
|
||||
|
||||
|
||||
@@ -524,12 +524,10 @@ EchonestGenerator::sentenceSummary()
|
||||
suffix = ", ";
|
||||
sentence += prefix + allcontrols.value( i ).dynamicCast< EchonestControl >()->summary() + suffix;
|
||||
}
|
||||
qDebug() << "Got artists and contents:" << sentence;
|
||||
|
||||
if( !sorting.isNull() ) {
|
||||
sentence += "and " + sorting.dynamicCast< EchonestControl >()->summary() + ".";
|
||||
}
|
||||
qDebug() << "Got full summary:" << sentence;
|
||||
|
||||
return sentence;
|
||||
}
|
||||
|
@@ -105,6 +105,12 @@ DynamicWidget::~DynamicWidget()
|
||||
{
|
||||
}
|
||||
|
||||
dynplaylist_ptr
|
||||
DynamicWidget::playlist()
|
||||
{
|
||||
return m_playlist;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DynamicWidget::loadDynamicPlaylist( const Tomahawk::dynplaylist_ptr& playlist )
|
||||
@@ -427,6 +433,17 @@ DynamicWidget::paintRoundedFilledRect( QPainter& p, QPalette& /* pal */, QRect&
|
||||
p.drawRoundedRect( r, 10, 10 );
|
||||
}
|
||||
|
||||
QString
|
||||
DynamicWidget::description() const
|
||||
{
|
||||
return m_model->description();
|
||||
}
|
||||
|
||||
QString
|
||||
DynamicWidget::title() const
|
||||
{
|
||||
return m_model->title();
|
||||
}
|
||||
|
||||
QPixmap
|
||||
DynamicWidget::pixmap() const
|
||||
@@ -452,7 +469,6 @@ void
|
||||
DynamicWidget::onDeleted()
|
||||
{
|
||||
emit destroyed( widget() );
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
|
||||
|
@@ -23,10 +23,7 @@
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "viewpage.h"
|
||||
|
||||
#include "dynamic/DynamicPlaylist.h"
|
||||
#include "dynamic/DynamicControl.h"
|
||||
#include "dynamic/DynamicModel.h"
|
||||
#include "playlist/dynamic/DynamicPlaylistRevision.h"
|
||||
|
||||
class LoadingSpinner;
|
||||
class QShowEvent;
|
||||
@@ -45,10 +42,10 @@ class ReadOrWriteWidget;
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class DynamicModel;
|
||||
|
||||
class DynamicSetupWidget;
|
||||
|
||||
class DynamicView;
|
||||
|
||||
class CollapsibleControls;
|
||||
|
||||
|
||||
@@ -63,7 +60,7 @@ public:
|
||||
virtual ~DynamicWidget();
|
||||
|
||||
void loadDynamicPlaylist( const dynplaylist_ptr& playlist );
|
||||
dynplaylist_ptr playlist() { return m_playlist; }
|
||||
dynplaylist_ptr playlist();
|
||||
|
||||
virtual PlaylistInterface* playlistInterface() const;
|
||||
|
||||
@@ -75,8 +72,8 @@ public:
|
||||
|
||||
virtual QWidget* widget() { return this; }
|
||||
|
||||
virtual QString title() const { return m_model->title(); }
|
||||
virtual QString description() const { return m_model->description(); }
|
||||
virtual QString title() const;
|
||||
virtual QString description() const;
|
||||
virtual QPixmap pixmap() const;
|
||||
|
||||
virtual bool jumpToCurrentTrack();
|
||||
|
@@ -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
|
||||
@@ -21,31 +21,33 @@
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "dllmacro.h"
|
||||
|
||||
class QMovie;
|
||||
class QTimeLine;
|
||||
/**
|
||||
* A small widget that displays an animated loading spinner
|
||||
*/
|
||||
class LoadingSpinner : public QWidget {
|
||||
class DLLEXPORT LoadingSpinner : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
LoadingSpinner( QWidget* parent );
|
||||
virtual ~LoadingSpinner();
|
||||
|
||||
|
||||
virtual QSize sizeHint() const;
|
||||
virtual void paintEvent( QPaintEvent* );
|
||||
virtual void resizeEvent( QResizeEvent* );
|
||||
|
||||
public slots:
|
||||
|
||||
public slots:
|
||||
void fadeIn();
|
||||
void fadeOut();
|
||||
|
||||
|
||||
private slots:
|
||||
void hideFinished();
|
||||
|
||||
|
||||
private:
|
||||
void reposition();
|
||||
|
||||
|
||||
QTimeLine* m_showHide;
|
||||
QMovie* m_anim;
|
||||
};
|
||||
|
@@ -20,22 +20,25 @@
|
||||
#include "ui_infobar.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QPropertyAnimation>
|
||||
#include <QPixmap>
|
||||
|
||||
#include "context/ContextWidget.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 );
|
||||
|