mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-09-06 12:10:47 +02:00
Compare commits
67 Commits
whatsnew_0
...
decltest
Author | SHA1 | Date | |
---|---|---|---|
|
a4d01685cf | ||
|
467cb26006 | ||
|
8f20c828fa | ||
|
012bb49328 | ||
|
8e91ab63ca | ||
|
52d5dbaf4d | ||
|
cdfde7ecc3 | ||
|
d5935b632f | ||
|
e50c661496 | ||
|
ecc6b679a7 | ||
|
ee2670b813 | ||
|
95b43964df | ||
|
e67653dbfd | ||
|
125fa25d07 | ||
|
c77aecd59f | ||
|
d16ed39dbe | ||
|
c1df1387f0 | ||
|
6d67b129d2 | ||
|
07d91b1d58 | ||
|
87966d5636 | ||
|
83f9d86e1d | ||
|
b02f8c0d9c | ||
|
885c52a042 | ||
|
68114e1f59 | ||
|
710e570845 | ||
|
ff44238d06 | ||
|
71eb1e916a | ||
|
0314760451 | ||
|
b9a909eb56 | ||
|
73f05971e4 | ||
|
c0c2cc6234 | ||
|
ba6b14863c | ||
|
309a6843f0 | ||
|
a89d20665f | ||
|
976a2eeb0a | ||
|
6dea6dc0a5 | ||
|
6dc8e98003 | ||
|
d571a79746 | ||
|
457c916101 | ||
|
56e73fb274 | ||
|
56dd8d47db | ||
|
3c942b1249 | ||
|
68de791e8c | ||
|
41a37b4690 | ||
|
9e6dbcc7b1 | ||
|
64f4445a01 | ||
|
0a1f2304e9 | ||
|
8f465b2984 | ||
|
2d32a2db90 | ||
|
f5b3c20c4c | ||
|
abb8217286 | ||
|
b48896157d | ||
|
692a4043e8 | ||
|
e81baf0eb7 | ||
|
bbdb15c53e | ||
|
5f61e3b1bd | ||
|
6bc9f88189 | ||
|
92d7757e47 | ||
|
2fb8b57e25 | ||
|
c295514598 | ||
|
c05bae9e8c | ||
|
051282be06 | ||
|
fb0a88aa98 | ||
|
fc69e7d08d | ||
|
02708629ca | ||
|
d894116e8e | ||
|
5c47ae96ab |
@@ -88,7 +88,7 @@ IF( NOT BUILD_GUI )
|
||||
MESSAGE( STATUS "Building Tomahawk ${TOMAHAWK_VERSION} in HEADLESS mode ***" )
|
||||
ELSE()
|
||||
MESSAGE( STATUS "Building Tomahawk ${TOMAHAWK_VERSION} full GUI version ***" )
|
||||
LIST(APPEND NEEDED_QT4_COMPONENTS "QtGui" "QtWebkit" "QtUiTools" )
|
||||
LIST(APPEND NEEDED_QT4_COMPONENTS "QtGui" "QtWebkit" "QtUiTools" "QtDeclarative" )
|
||||
ENDIF()
|
||||
|
||||
IF( BUILD_GUI AND UNIX AND NOT APPLE )
|
||||
|
147
CMakeLists.txt.user.2.3pre1
Normal file
147
CMakeLists.txt.user.2.3pre1
Normal file
@@ -0,0 +1,147 @@
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value key="EditorConfiguration.AutoIndent" type="bool">true</value>
|
||||
<value key="EditorConfiguration.AutoSpacesForTabs" type="bool">false</value>
|
||||
<value key="EditorConfiguration.Codec" type="QByteArray">UTF-8</value>
|
||||
<value key="EditorConfiguration.DoubleIndentBlocks" type="bool">false</value>
|
||||
<value key="EditorConfiguration.IndentBraces" type="bool">false</value>
|
||||
<value key="EditorConfiguration.IndentSize" type="int">4</value>
|
||||
<value key="EditorConfiguration.MouseNavigation" type="bool">true</value>
|
||||
<value key="EditorConfiguration.PaddingMode" type="int">1</value>
|
||||
<value key="EditorConfiguration.ScrollWheelZooming" type="bool">true</value>
|
||||
<value key="EditorConfiguration.SmartBackspace" type="bool">false</value>
|
||||
<value key="EditorConfiguration.SpacesForTabs" type="bool">true</value>
|
||||
<value key="EditorConfiguration.TabKeyBehavior" type="int">0</value>
|
||||
<value key="EditorConfiguration.TabSize" type="int">8</value>
|
||||
<value key="EditorConfiguration.UseGlobal" type="bool">true</value>
|
||||
<value key="EditorConfiguration.Utf8BomBehavior" type="int">1</value>
|
||||
<value key="EditorConfiguration.addFinalNewLine" type="bool">true</value>
|
||||
<value key="EditorConfiguration.cleanIndentation" type="bool">true</value>
|
||||
<value key="EditorConfiguration.cleanWhitespace" type="bool">true</value>
|
||||
<value key="EditorConfiguration.inEntireDocument" type="bool">false</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Desktop</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">CMakeProjectManager.DefaultCMakeTarget</value>
|
||||
<value key="ProjectExplorer.Target.ActiveBuildConfiguration" type="int">0</value>
|
||||
<value key="ProjectExplorer.Target.ActiveDeployConfiguration" type="int">0</value>
|
||||
<value key="ProjectExplorer.Target.ActiveRunConfiguration" type="int">0</value>
|
||||
<valuemap key="ProjectExplorer.Target.BuildConfiguration.0" type="QVariantMap">
|
||||
<value key="CMakeProjectManager.CMakeBuildConfiguration.BuildDirectory" type="QString">/home/micha/Develop/tomahawk-build</value>
|
||||
<value key="CMakeProjectManager.CMakeBuildConfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value>
|
||||
<value key="ProjectExplorer.BuildCOnfiguration.ToolChain" type="QString">ProjectExplorer.ToolChain.Gcc:/usr/bin/g++.x86-linux-generic-elf-64bit.</value>
|
||||
<valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.0" type="QVariantMap">
|
||||
<valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap">
|
||||
<value key="CMakeProjectManager.MakeStep.AdditionalArguments" type="QString"></value>
|
||||
<valuelist key="CMakeProjectManager.MakeStep.BuildTargets" type="QVariantList"/>
|
||||
<value key="CMakeProjectManager.MakeStep.Clean" type="bool">false</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value key="ProjectExplorer.BuildStepList.StepsCount" type="int">1</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Build</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.1" type="QVariantMap">
|
||||
<valuemap key="ProjectExplorer.BuildStepList.Step.0" type="QVariantMap">
|
||||
<value key="CMakeProjectManager.MakeStep.AdditionalArguments" type="QString">clean</value>
|
||||
<valuelist key="CMakeProjectManager.MakeStep.BuildTargets" type="QVariantList"/>
|
||||
<value key="CMakeProjectManager.MakeStep.Clean" type="bool">true</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Make</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value key="ProjectExplorer.BuildStepList.StepsCount" type="int">1</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Clean</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value key="ProjectExplorer.BuildConfiguration.BuildStepListCount" type="int">2</value>
|
||||
<value key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment" type="bool">false</value>
|
||||
<valuelist key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges" type="QVariantList"/>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">all</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">CMakeProjectManager.CMakeBuildConfiguration</value>
|
||||
</valuemap>
|
||||
<value key="ProjectExplorer.Target.BuildConfigurationCount" type="int">1</value>
|
||||
<valuemap key="ProjectExplorer.Target.DeployConfiguration.0" type="QVariantMap">
|
||||
<valuemap key="ProjectExplorer.BuildConfiguration.BuildStepList.0" type="QVariantMap">
|
||||
<value key="ProjectExplorer.BuildStepList.StepsCount" type="int">0</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">Deploy</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value key="ProjectExplorer.BuildConfiguration.BuildStepListCount" type="int">1</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">No deployment</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value key="ProjectExplorer.Target.DeployConfigurationCount" type="int">1</value>
|
||||
<valuemap key="ProjectExplorer.Target.RunConfiguration.0" type="QVariantMap">
|
||||
<valuelist key="Analyzer.Valgrind.AddedSupressionFiles" type="QVariantList"/>
|
||||
<value key="Analyzer.Valgrind.FilterExternalIssues" type="bool">true</value>
|
||||
<value key="Analyzer.Valgrind.NumCallers" type="int">25</value>
|
||||
<valuelist key="Analyzer.Valgrind.RemovedSupressionFiles" type="QVariantList"/>
|
||||
<value key="Analyzer.Valgrind.TrackOrigins" type="bool">true</value>
|
||||
<value key="Analyzer.Valgrind.ValgrindExecutable" type="QString">valgrind</value>
|
||||
<valuelist key="Analyzer.Valgrind.VisibleErrorKinds" type="QVariantList">
|
||||
<value type="int">0</value>
|
||||
<value type="int">1</value>
|
||||
<value type="int">2</value>
|
||||
<value type="int">3</value>
|
||||
<value type="int">4</value>
|
||||
<value type="int">5</value>
|
||||
<value type="int">6</value>
|
||||
<value type="int">7</value>
|
||||
<value type="int">8</value>
|
||||
<value type="int">9</value>
|
||||
<value type="int">10</value>
|
||||
<value type="int">11</value>
|
||||
<value type="int">12</value>
|
||||
<value type="int">13</value>
|
||||
<value type="int">14</value>
|
||||
</valuelist>
|
||||
<value key="CMakeProjectManager.BaseEnvironmentBase" type="int">2</value>
|
||||
<value key="CMakeProjectManager.CMakeRunConfiguation.Title" type="QString">tomahawk</value>
|
||||
<value key="CMakeProjectManager.CMakeRunConfiguration.Arguments" type="QString">--verbose</value>
|
||||
<value key="CMakeProjectManager.CMakeRunConfiguration.UseTerminal" type="bool">false</value>
|
||||
<valuelist key="CMakeProjectManager.CMakeRunConfiguration.UserEnvironmentChanges" type="QVariantList">
|
||||
<value type="QString">Q_FATAL_WARNINGS=1</value>
|
||||
</valuelist>
|
||||
<value key="CMakeProjectManager.CMakeRunConfiguration.UserWorkingDirectory" type="QString"></value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName" type="QString">tomahawk</value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.DisplayName" type="QString"></value>
|
||||
<value key="ProjectExplorer.ProjectConfiguration.Id" type="QString">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||
<value key="RunConfiguration.QmlDebugServerPort" type="uint">3768</value>
|
||||
<value key="RunConfiguration.UseCppDebugger" type="bool">true</value>
|
||||
<value key="RunConfiguration.UseQmlDebugger" type="bool">false</value>
|
||||
</valuemap>
|
||||
<value key="ProjectExplorer.Target.RunConfigurationCount" type="int">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.EnvironmentId</variable>
|
||||
<value type="QString">{6caf061d-47d5-4e4f-a8d8-0d83c14e4267}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">9</value>
|
||||
</data>
|
||||
</qtcreator>
|
139
data/qml/ArtistInfoScene.qml
Normal file
139
data/qml/ArtistInfoScene.qml
Normal file
@@ -0,0 +1,139 @@
|
||||
import QtQuick 1.1
|
||||
|
||||
Rectangle {
|
||||
color: "black"
|
||||
anchors.fill: parent
|
||||
// height: 200
|
||||
// width: 200
|
||||
|
||||
|
||||
Component {
|
||||
id: pathDelegate
|
||||
Item {
|
||||
width: 100; height: 100
|
||||
scale: PathView.iconScale
|
||||
|
||||
// TODO: Use Image provider here
|
||||
Image {
|
||||
id: originalImage
|
||||
width: 80
|
||||
height: 80
|
||||
source: index % 2 === 0 ? "http://www.muktware.com/sites/default/files/images/applications/tomahawk_icon.png" : "http://cloud.ohloh.net/attachments/53867/tomahawk-icon-64x64_med.png"
|
||||
}
|
||||
|
||||
// mirror image - album art and a gradient filled rectangle for darkening
|
||||
Item {
|
||||
width: originalImage.width; height: originalImage.height
|
||||
anchors.horizontalCenter: originalImage.horizontalCenter
|
||||
|
||||
// transform this item (the image and rectangle) to create the
|
||||
// mirror image using the values from the Path
|
||||
transform : [
|
||||
Rotation {
|
||||
angle: 180; origin.y: originalImage.height
|
||||
axis.x: 1; axis.y: 0; axis.z: 0
|
||||
},
|
||||
Rotation {
|
||||
angle: PathView.rotateY; origin.x: originalImage.width/2
|
||||
axis.x: 0; axis.y: 1; axis.z: 0
|
||||
},
|
||||
Scale {
|
||||
xScale: PathView.scaleArt; yScale: PathView.scaleArt
|
||||
origin.x: originalImage.width/2; origin.y: originalImage.height/2
|
||||
}
|
||||
]
|
||||
|
||||
// mirror image
|
||||
Image {
|
||||
width: originalImage.width; height: originalImage.height
|
||||
source: originalImage.source
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
// mirror image dimming gradient filled rectangle
|
||||
Rectangle {
|
||||
width: originalImage.width+4; height: originalImage.height
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
gradient: Gradient {
|
||||
// TODO: no clue how to get the RGB component of the container rectangle color
|
||||
GradientStop { position: 1.0; color: Qt.rgba(0,0,0,0.4) }
|
||||
GradientStop { position: 0.3; color: reflectionContainer.color }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors { top: myIcon.bottom; horizontalCenter: parent.horizontalCenter }
|
||||
text: label
|
||||
smooth: true
|
||||
color: "white"
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: view.currentIndex = index
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PathView {
|
||||
id: view
|
||||
anchors { left: parent.left; top: parent.top; right: parent.right }
|
||||
height: 300
|
||||
preferredHighlightBegin: 0.5
|
||||
preferredHighlightEnd: 0.5
|
||||
focus: true
|
||||
model: albumsModel
|
||||
delegate: pathDelegate
|
||||
pathItemCount: 8
|
||||
path: Path {
|
||||
startX: 10
|
||||
startY: 50
|
||||
PathAttribute { name: "iconScale"; value: 0.5 }
|
||||
PathQuad { x: view.width/2; y: 150; controlX: 50; controlY: 200 }
|
||||
PathAttribute { name: "iconScale"; value: 1.0 }
|
||||
PathQuad { x: view.width; y: 50; controlX: view.width; controlY: 200 }
|
||||
PathAttribute { name: "iconScale"; value: 0.5 }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Component {
|
||||
id: gridDelegate
|
||||
Item {
|
||||
width: 100; height: 100
|
||||
scale: PathView.iconScale
|
||||
|
||||
// TODO: Use Image provider here
|
||||
Image {
|
||||
id: originalImage
|
||||
width: 80
|
||||
height: 80
|
||||
source: index % 2 === 0 ? "http://www.muktware.com/sites/default/files/images/applications/tomahawk_icon.png" : "http://cloud.ohloh.net/attachments/53867/tomahawk-icon-64x64_med.png"
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors { top: myIcon.bottom; horizontalCenter: parent.horizontalCenter }
|
||||
text: label
|
||||
smooth: true
|
||||
color: "white"
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: view.currentIndex = index
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GridView {
|
||||
id: grid
|
||||
anchors { left: parent.left; top: view.bottom; right: parent.right; bottom: parent.bottom }
|
||||
|
||||
model: albumsModel
|
||||
|
||||
delegate: gridDelegate
|
||||
}
|
||||
|
||||
}
|
155
data/qml/CoverImage.qml
Normal file
155
data/qml/CoverImage.qml
Normal file
@@ -0,0 +1,155 @@
|
||||
import QtQuick 1.1
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
// Should the artist + track labels be painted
|
||||
property bool showLabels: true
|
||||
// Should the play button be painted on mouse hover?
|
||||
property bool showPlayButton: false
|
||||
// Should the mirror be painted?
|
||||
property bool showMirror: false
|
||||
|
||||
// Labels & Cover
|
||||
property string artistName
|
||||
property string trackName
|
||||
property string artworkId
|
||||
|
||||
onArtworkIdChanged: print("!*!*!*!*!* artworkId", artworkId)
|
||||
|
||||
// The border color for the cover image
|
||||
property color borderColor: "black"
|
||||
// The border width for the cover image
|
||||
property int borderWidth: 2
|
||||
|
||||
// needed to adjust the shadow
|
||||
property color backgroundColor: "black"
|
||||
|
||||
// sets the brightness for the item and its mirror (1: brightest, 0: darkest)
|
||||
property double itemBrightness: 1
|
||||
property double mirrorBrightness: .5
|
||||
|
||||
// will be emitted when the on hower play button is clicked
|
||||
signal playClicked()
|
||||
// will be emitted when the cover is clicked
|
||||
signal clicked()
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: root.clicked();
|
||||
|
||||
}
|
||||
|
||||
Component {
|
||||
id: coverImage
|
||||
|
||||
Rectangle {
|
||||
color: "white"
|
||||
border.color: borderColor
|
||||
border.width: borderWidth
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
//anchors.margins: borderWidth
|
||||
source: "image://albumart/" + artworkId
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: textBackground
|
||||
anchors { left: parent.left; right: parent.right; bottom: parent.bottom }
|
||||
height: 32
|
||||
anchors.margins: 5
|
||||
color: "black"
|
||||
opacity: showLabels ? 0.5 : 0
|
||||
radius: 3
|
||||
}
|
||||
|
||||
Text {
|
||||
color: "white"
|
||||
font.bold: true
|
||||
text: trackName
|
||||
anchors { left: textBackground.left; right: textBackground.right; top: textBackground.top }
|
||||
anchors.margins: 2
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
elide: Text.ElideRight
|
||||
opacity: showLabels ? 1 : 0
|
||||
}
|
||||
Text {
|
||||
color: "white"
|
||||
text: artistName
|
||||
anchors { left: textBackground.left; right: textBackground.right; bottom: textBackground.bottom }
|
||||
anchors.margins: 2
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
elide: Text.ElideRight
|
||||
opacity: showLabels ? 1 : 0
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loader {
|
||||
sourceComponent: coverImage
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: mirroredCover
|
||||
sourceComponent: parent.showMirror ? coverImage : undefined
|
||||
anchors.fill: parent
|
||||
transform : [
|
||||
Rotation {
|
||||
angle: 180; origin.y: root.height
|
||||
axis.x: 1; axis.y: 0; axis.z: 0
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: itemShadow
|
||||
color: backgroundColor
|
||||
anchors.fill: parent
|
||||
anchors.bottomMargin: - parent.height
|
||||
|
||||
// scaling might be off a pixel... make sure that the shadow is at least as large as the image
|
||||
anchors.leftMargin: -2
|
||||
anchors.rightMargin: -2
|
||||
anchors.topMargin: -2
|
||||
|
||||
opacity: 1 - itemBrightness + (mouseArea.containsMouse ? .2 : 0)
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation { easing.type: Easing.Linear; duration: 300 }
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: mirrorShadow
|
||||
color: parent.backgroundColor
|
||||
height: parent.height + 2
|
||||
width: parent.width + 4
|
||||
anchors.centerIn: parent
|
||||
anchors.verticalCenterOffset: parent.height
|
||||
|
||||
gradient: Gradient {
|
||||
// TODO: no clue how to get the RGB component of the container rectangle color
|
||||
// For now the Qt.rgba needs to be manually updated to match the backgroundColor
|
||||
GradientStop { position: 0.0; color: Qt.rgba(0, 0, 0, 1-mirrorBrightness) }
|
||||
GradientStop { position: 0.5; color: backgroundColor }
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: playButton
|
||||
visible: showPlayButton ? mouseArea.containsMouse : false
|
||||
source: "../images/play-rest.png"
|
||||
anchors.centerIn: parent
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: root.playClicked();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
79
data/qml/StationConfig.qml
Normal file
79
data/qml/StationConfig.qml
Normal file
@@ -0,0 +1,79 @@
|
||||
import QtQuick 1.1
|
||||
import tomahawk 1.0
|
||||
import "tomahawkimports"
|
||||
|
||||
Item {
|
||||
id: fineTuneView
|
||||
|
||||
property color textColor: "white"
|
||||
|
||||
signal done();
|
||||
|
||||
Grid {
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.margins: 50
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: scene.width / 2
|
||||
spacing: 50
|
||||
columns: 2
|
||||
|
||||
Text {
|
||||
color: fineTuneView.textColor
|
||||
text: "Name:"
|
||||
|
||||
}
|
||||
InputField {
|
||||
text: echonestStation.name
|
||||
|
||||
onAccepted: {
|
||||
print("text changed!!!")
|
||||
echonestStation.name = text;
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: tempoText
|
||||
text: "Tempo:"
|
||||
color: "white"
|
||||
}
|
||||
DoubleSlider {
|
||||
width: 500
|
||||
height: tempoText.height
|
||||
min: 0
|
||||
max: 500
|
||||
lowerSliderPos: echonestStation.minTempo
|
||||
upperSliderPos: echonestStation.maxTempo
|
||||
onValueChanged: echonestStation.setTempo( lowerSliderPos, upperSliderPos )
|
||||
}
|
||||
|
||||
Text {
|
||||
id: hotnessText
|
||||
text: "Hotness:"
|
||||
color: "white"
|
||||
}
|
||||
DoubleSlider {
|
||||
width: 500
|
||||
height: hotnessText.height
|
||||
min: 0
|
||||
max: 100
|
||||
minLabel: "Less"
|
||||
maxLabel: "More"
|
||||
showFloatingLabel: false
|
||||
lowerSliderPos: echonestStation.minHotttness * 100
|
||||
upperSliderPos: echonestStation.maxHotttness * 100
|
||||
onValueChanged: echonestStation.setHotttness( 1.0 * lowerSliderPos / 100, 1.0 * upperSliderPos / 100 )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Button {
|
||||
id: configureButton
|
||||
onClicked: fineTuneView.done();
|
||||
text: "configure"
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 20
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
|
||||
}
|
158
data/qml/StationScene.qml
Normal file
158
data/qml/StationScene.qml
Normal file
@@ -0,0 +1,158 @@
|
||||
import QtQuick 1.1
|
||||
import tomahawk 1.0
|
||||
import "tomahawkimports"
|
||||
|
||||
Rectangle {
|
||||
id: scene
|
||||
color: "black"
|
||||
anchors.fill: parent
|
||||
state: echonestStation.configured ? "list" : "configure"
|
||||
|
||||
ListModel {
|
||||
id: styleModel
|
||||
ListElement { modelData: "acoustic" }
|
||||
ListElement { modelData: "alternative" }
|
||||
ListElement { modelData: "alternative rock" }
|
||||
ListElement { modelData: "classic" }
|
||||
ListElement { modelData: "folk" }
|
||||
ListElement { modelData: "indie" }
|
||||
ListElement { modelData: "pop" }
|
||||
ListElement { modelData: "rock" }
|
||||
ListElement { modelData: "hip-hop" }
|
||||
ListElement { modelData: "punk" }
|
||||
ListElement { modelData: "grunge" }
|
||||
ListElement { modelData: "indie" }
|
||||
ListElement { modelData: "electronic" }
|
||||
ListElement { modelData: "country" }
|
||||
ListElement { modelData: "jazz" }
|
||||
ListElement { modelData: "psychodelic" }
|
||||
ListElement { modelData: "soundtrack" }
|
||||
ListElement { modelData: "reggae" }
|
||||
ListElement { modelData: "house" }
|
||||
ListElement { modelData: "drum and base" }
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: dummyArtistModel
|
||||
ListElement { modelData: "Pink Floyd" }
|
||||
ListElement { modelData: "Tool" }
|
||||
ListElement { modelData: "Cake" }
|
||||
ListElement { modelData: "Metallica" }
|
||||
ListElement { modelData: "Red Hot Chili Peppers" }
|
||||
ListElement { modelData: "Korn" }
|
||||
ListElement { modelData: "Prodigy" }
|
||||
ListElement { modelData: "Otto Waalkes" }
|
||||
}
|
||||
|
||||
VisualItemModel {
|
||||
id: stationVisualModel
|
||||
|
||||
|
||||
Column {
|
||||
height: scene.height
|
||||
width: scene.width
|
||||
|
||||
Row {
|
||||
height: scene.height / 2
|
||||
width: scene.width
|
||||
spacing: width * .1
|
||||
|
||||
Item {
|
||||
height: parent.height
|
||||
width: (parent.width - orText.width - parent.spacing * 2 ) * 2 / 3
|
||||
GridView {
|
||||
id: gridView
|
||||
anchors.fill: parent
|
||||
anchors.margins: cellWidth / 2
|
||||
model: dummyArtistModel
|
||||
|
||||
cellWidth: gridView.width / 4 - 1 // -1 to make sure there is space for 4 items even with rounding error
|
||||
cellHeight: cellWidth
|
||||
|
||||
delegate: Item {
|
||||
height: gridView.cellHeight * .9
|
||||
width: height
|
||||
|
||||
CoverImage {
|
||||
artistName: modelData
|
||||
anchors.fill: parent
|
||||
|
||||
onClicked: {
|
||||
echonestStation.setMainControl( EchonestStation.StationTypeArtist, modelData );
|
||||
stationListView.incrementCurrentIndex();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Row {
|
||||
height: scene.height / 2
|
||||
width: scene.width * .9
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: width * .1
|
||||
|
||||
TagCloud {
|
||||
height: parent.height
|
||||
width: (parent.width - orText.width - parent.spacing * 2 ) * 2 / 3
|
||||
model: styleModel//generator.styles()
|
||||
opacity: echonestStation.configured ? 0 : 1
|
||||
|
||||
onTagClicked: {
|
||||
echonestStation.setMainControl( EchonestStation.StationTypeStyle, item );
|
||||
stationListView.incrementCurrentIndex();
|
||||
}
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 300 }
|
||||
}
|
||||
}
|
||||
Text {
|
||||
id: orText
|
||||
text: "or"
|
||||
color: "white"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
InputField {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: (parent.width - orText.width - parent.spacing * 2 ) * 1 / 3
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StationView {
|
||||
coverSize: Math.min(scene.height, scene.width) / 2
|
||||
height: scene.height
|
||||
width: scene.width
|
||||
|
||||
onConfigure: stationListView.incrementCurrentIndex();
|
||||
}
|
||||
|
||||
|
||||
StationConfig {
|
||||
height: scene.height
|
||||
width: scene.width
|
||||
|
||||
onDone: stationListView.decrementCurrentIndex();
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: stationListView
|
||||
anchors.fill: parent
|
||||
contentHeight: scene.height
|
||||
contentWidth: scene.width
|
||||
orientation: ListView.Horizontal
|
||||
model: stationVisualModel
|
||||
interactive: false
|
||||
highlightMoveDuration: 400
|
||||
|
||||
Component.onCompleted: {
|
||||
if ( echonestStation.configured ) {
|
||||
currentIndex = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
188
data/qml/StationView.qml
Normal file
188
data/qml/StationView.qml
Normal file
@@ -0,0 +1,188 @@
|
||||
import QtQuick 1.1
|
||||
import tomahawk 1.0
|
||||
import "tomahawkimports"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property int coverSize
|
||||
|
||||
signal configure()
|
||||
|
||||
PathView {
|
||||
id: coverView
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: parent.width / 3
|
||||
|
||||
preferredHighlightBegin: 0.2 // scene.width / 11000
|
||||
preferredHighlightEnd: preferredHighlightBegin
|
||||
pathItemCount: 5
|
||||
//highlightMoveDuration: 500
|
||||
|
||||
model: dynamicModel
|
||||
currentIndex: currentlyPlayedIndex
|
||||
|
||||
property int pathStartX: width / 2
|
||||
property int pathStartY: height / 2
|
||||
|
||||
delegate: CoverImage {
|
||||
height: root.coverSize
|
||||
width: root.coverSize
|
||||
|
||||
showLabels: false
|
||||
showMirror: true
|
||||
//artistName: model.artistName
|
||||
//trackName: model.trackName
|
||||
artworkId: model.coverID
|
||||
|
||||
scale: PathView.itemScale
|
||||
itemBrightness: PathView.itemBrightness
|
||||
opacity: PathView.itemOpacity
|
||||
z: x
|
||||
|
||||
onClicked: {
|
||||
if ( currentlyPlayedIndex !==-1 ) {
|
||||
echonestStation.playItem( index )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
path: Path {
|
||||
startX: coverView.pathStartX
|
||||
startY: coverView.pathStartY
|
||||
|
||||
PathAttribute { name: "itemOpacity"; value: 0 }
|
||||
PathAttribute { name: "itemBrightness"; value: 0 }
|
||||
PathAttribute { name: "itemScale"; value: 1.5 }
|
||||
PathLine { x: coverView.pathStartX * 0.9 ; y: coverView.pathStartY * 0.9 }
|
||||
PathPercent { value: .2 }
|
||||
PathAttribute { name: "itemOpacity"; value: 1 }
|
||||
PathAttribute { name: "itemBrightness"; value: 1 }
|
||||
PathAttribute { name: "itemScale"; value: 1 }
|
||||
PathLine { x: coverView.pathStartX * .5; y: coverView.pathStartY * .5}
|
||||
PathPercent { value: .3 }
|
||||
PathAttribute { name: "itemOpacity"; value: 1 }
|
||||
PathAttribute { name: "itemBrightness"; value: 1 }
|
||||
PathAttribute { name: "itemScale"; value: 0.5 }
|
||||
// PathLine { x: coverView.pathStartX * .25 ; y: coverView.pathStartY * .25 }
|
||||
// PathPercent { value: .75 }
|
||||
// PathAttribute { name: "itemOpacity"; value: 1 }
|
||||
// PathAttribute { name: "itemBrightness"; value: .5 }
|
||||
// PathAttribute { name: "itemScale"; value: 0.4 }
|
||||
PathLine { x: 0; y: 0 }
|
||||
PathPercent { value: 1 }
|
||||
PathAttribute { name: "itemOpacity"; value: 1 }
|
||||
PathAttribute { name: "itemBrightness"; value: 0 }
|
||||
PathAttribute { name: "itemScale"; value: 0.1 }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Item {
|
||||
anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
|
||||
anchors.margins: 50
|
||||
width: scene.width / 3
|
||||
|
||||
Column {
|
||||
anchors { left: parent.left; top: parent.top; right: parent.right }
|
||||
Text {
|
||||
color: "white"
|
||||
font.pointSize: 12
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
text: "Station:"
|
||||
}
|
||||
Text {
|
||||
color: "white"
|
||||
font.pointSize: 14
|
||||
font.bold: true
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
text: echonestStation.name
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: scene.width / 3
|
||||
|
||||
|
||||
Text {
|
||||
color: "white"
|
||||
font.pointSize: 12
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
text: "Now Playing:"
|
||||
visible: currentlyPlayedIndex !== -1
|
||||
}
|
||||
Rectangle {
|
||||
height: image.height + image.height / 5
|
||||
width: image.width + startPlayingText.width * 1.2
|
||||
radius: height / 2
|
||||
border.width: 2
|
||||
border.color: "white"
|
||||
color: startPlayingMouseArea.containsMouse ? "blue" : "gray"
|
||||
visible: currentlyPlayedIndex === -1
|
||||
Image {
|
||||
id: image
|
||||
source: "../images/play-rest.png"
|
||||
anchors.left: parent.left
|
||||
anchors.margins: 10
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
id: startPlayingText
|
||||
color: "white"
|
||||
font.pointSize: 20
|
||||
anchors.left: image.right
|
||||
anchors.margins: height / 5
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
//width: parent.width - 30 - image.width
|
||||
elide: Text.ElideRight
|
||||
text: "Start playing"
|
||||
}
|
||||
MouseArea {
|
||||
id: startPlayingMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: echonestStation.playItem( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
color: "white"
|
||||
font.pointSize: 16
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
text: currentlyPlayedIndex > -1 ? coverView.model.itemFromIndex( currentlyPlayedIndex ).name : ""
|
||||
}
|
||||
Text {
|
||||
color: "white"
|
||||
font.pointSize: 14
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
text: currentlyPlayedIndex > -1 ? coverView.model.itemFromIndex( currentlyPlayedIndex ).artistName : ""
|
||||
}
|
||||
Text {
|
||||
color: "white"
|
||||
font.pointSize: 14
|
||||
width: parent.width
|
||||
elide: Text.ElideRight
|
||||
text: currentlyPlayedIndex > -1 ? coverView.model.itemFromIndex( currentlyPlayedIndex ).albumName : ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: configureButton
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 20
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: "configure"
|
||||
onClicked: root.configure();
|
||||
}
|
||||
|
||||
}
|
||||
|
53
data/qml/TagCloud.qml
Normal file
53
data/qml/TagCloud.qml
Normal file
@@ -0,0 +1,53 @@
|
||||
import QtQuick 1.1
|
||||
import tomahawk 1.0
|
||||
|
||||
Item {
|
||||
id: tagCloud
|
||||
|
||||
property variant model: 10
|
||||
|
||||
signal tagClicked( string item )
|
||||
|
||||
function randomNumber(min, max) {
|
||||
var date = new Date();
|
||||
return (max - min) * Math.random(date.getSeconds()) + min
|
||||
}
|
||||
|
||||
Flow {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width
|
||||
spacing: 3
|
||||
|
||||
Repeater {
|
||||
id: cloudRepeater
|
||||
model: tagCloud.model
|
||||
|
||||
delegate: Item {
|
||||
id: cloudItem
|
||||
width: delegateText.width * 1.1
|
||||
height: delegateText.height
|
||||
property double itemScale: Math.random() + .3
|
||||
scale: itemScale
|
||||
Text {
|
||||
id: delegateText
|
||||
color: "white"
|
||||
//text: controlModel.controlAt( index ).summary
|
||||
text: modelData
|
||||
font.pointSize: 16
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.verticalCenterOffset: tagCloud.randomNumber(0, 15)
|
||||
}
|
||||
MouseArea {
|
||||
hoverEnabled: true
|
||||
anchors.fill: parent
|
||||
onClicked: tagCloud.tagClicked( modelData )
|
||||
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
NumberAnimation { easing: Easing.Linear; duration: 1000 }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
29
data/qml/tomahawkimports/Button.qml
Normal file
29
data/qml/tomahawkimports/Button.qml
Normal file
@@ -0,0 +1,29 @@
|
||||
import QtQuick 1.1
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
color: buttonMouseArea.containsMouse ? "blue" : "gray"
|
||||
border.width: 2
|
||||
border.color: "white"
|
||||
radius: height/2
|
||||
height: buttonText.height * 1.2
|
||||
width: buttonText.width * 1.5
|
||||
|
||||
property alias text: buttonText.text
|
||||
property color textColor: "white"
|
||||
|
||||
signal clicked()
|
||||
|
||||
Text {
|
||||
id: buttonText
|
||||
anchors.centerIn: parent
|
||||
color: root.textColor
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: buttonMouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: root.clicked();
|
||||
}
|
||||
}
|
151
data/qml/tomahawkimports/DoubleSlider.qml
Normal file
151
data/qml/tomahawkimports/DoubleSlider.qml
Normal file
@@ -0,0 +1,151 @@
|
||||
import QtQuick 1.1
|
||||
|
||||
Item {
|
||||
id: root
|
||||
width: 500
|
||||
height: 10
|
||||
|
||||
property int min: 0
|
||||
property int max: 100
|
||||
|
||||
/** The labels next to the slider
|
||||
* if empty, min and max values are used
|
||||
*/
|
||||
property string minLabel: ""
|
||||
property string maxLabel: ""
|
||||
|
||||
/** Should the floating label indicating the current position be shown? */
|
||||
property bool showFloatingLabel: true
|
||||
|
||||
property int lowerSliderPos: 25
|
||||
property int upperSliderPos: 75
|
||||
|
||||
signal valueChanged()
|
||||
|
||||
Row {
|
||||
anchors.fill: parent
|
||||
spacing: 10
|
||||
|
||||
Text {
|
||||
id: minText
|
||||
text: root.minLabel.length > 0 ? root.minLabel : min
|
||||
color: "white"
|
||||
}
|
||||
|
||||
Item {
|
||||
id: sliderRect
|
||||
height: root.height
|
||||
width: parent.width - minText.width - maxText.width - parent.spacing * 2
|
||||
|
||||
function sliderPosToValue( sliderPos ) {
|
||||
var percent = sliderPos * 100 / (sliderRect.width - lowerSlider.width);
|
||||
return Math.floor(percent * (root.max - root.min) / 100) + root.min
|
||||
}
|
||||
|
||||
function valueToSloderPos( value ) {
|
||||
var percent = (value - root.min) * 100 / (root.max - root.min)
|
||||
return percent * (sliderRect.width - lowerSlider.width) / 100
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: sliderBase
|
||||
height: root.height / 5
|
||||
width: parent.width
|
||||
color: "white"
|
||||
radius: height / 2
|
||||
anchors.centerIn: parent
|
||||
|
||||
}
|
||||
Rectangle {
|
||||
id: lowerSlider
|
||||
height: root.height
|
||||
width: height
|
||||
anchors.top: root.top
|
||||
radius: height/2
|
||||
border.color: "black"
|
||||
border.width: 2
|
||||
x: sliderRect.valueToSloderPos(root.lowerSliderPos)
|
||||
|
||||
Rectangle {
|
||||
id: lowerFloatingRect
|
||||
color: "white"
|
||||
anchors.bottom: lowerSlider.top
|
||||
anchors.bottomMargin: 10
|
||||
visible: root.showFloatingLabel && lowerSliderMouseArea.pressed
|
||||
width: lowerFloatingText.width * 1.2
|
||||
height: lowerFloatingText.height + height * 1.2
|
||||
x: -(width - lowerSlider.width) / 2
|
||||
radius: height / 4
|
||||
|
||||
Text {
|
||||
id: lowerFloatingText
|
||||
anchors.centerIn: parent
|
||||
text: sliderRect.sliderPosToValue(lowerSlider.x)
|
||||
}
|
||||
}
|
||||
}
|
||||
MouseArea {
|
||||
id: lowerSliderMouseArea
|
||||
anchors.fill: lowerSlider
|
||||
drag.target: lowerSlider
|
||||
drag.axis: "XAxis"
|
||||
drag.minimumX: 0
|
||||
drag.maximumX: upperSlider.x - lowerSlider.width
|
||||
onReleased: {
|
||||
root.lowerSliderPos = sliderRect.sliderPosToValue( lowerSlider.x );
|
||||
root.valueChanged();
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: upperSlider
|
||||
height: root.height
|
||||
width: height
|
||||
anchors.top: root.top
|
||||
radius: height/2
|
||||
border.color: "black"
|
||||
border.width: 2
|
||||
x: sliderRect.valueToSloderPos(root.upperSliderPos)
|
||||
Rectangle {
|
||||
id: upperFloatingRect
|
||||
color: "white"
|
||||
anchors.bottom: upperSlider.top
|
||||
anchors.bottomMargin: 10
|
||||
visible: root.showFloatingLabel && upperSliderMouseArea.pressed
|
||||
width: upperFloatingText.width * 1.2
|
||||
height: upperFloatingText.height + height * 1.2
|
||||
radius: height / 4
|
||||
x: -(width - upperSlider.width) / 2
|
||||
|
||||
Text {
|
||||
id: upperFloatingText
|
||||
anchors.centerIn: parent
|
||||
text: sliderRect.sliderPosToValue(upperSlider.x)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
MouseArea {
|
||||
id: upperSliderMouseArea
|
||||
anchors.fill: upperSlider
|
||||
onClicked: print("button pressed")
|
||||
drag.target: upperSlider
|
||||
drag.axis: "XAxis"
|
||||
drag.minimumX: lowerSlider.x + lowerSlider.width
|
||||
drag.maximumX: parent.width - upperSlider.width
|
||||
onReleased: {
|
||||
root.upperSliderPos = sliderRect.sliderPosToValue( upperSlider.x );
|
||||
root.valueChanged();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Text {
|
||||
id: maxText
|
||||
text: root.maxLabel.length > 0 ? root.maxLabel : max
|
||||
color: "white"
|
||||
}
|
||||
}
|
||||
}
|
23
data/qml/tomahawkimports/InputField.qml
Normal file
23
data/qml/tomahawkimports/InputField.qml
Normal file
@@ -0,0 +1,23 @@
|
||||
import QtQuick 1.1
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
color: "white"
|
||||
border.color: "black"
|
||||
border.width: 2
|
||||
|
||||
height: textInput.height + 4
|
||||
width: 300
|
||||
|
||||
property alias text: textInput.text
|
||||
|
||||
signal accepted( string text )
|
||||
|
||||
TextInput {
|
||||
id: textInput
|
||||
width: parent.width
|
||||
anchors.centerIn: parent
|
||||
|
||||
onAccepted: root.accepted( text );
|
||||
}
|
||||
}
|
@@ -150,5 +150,14 @@
|
||||
<file>data/images/scrollbar-horizontal-handle.png</file>
|
||||
<file>data/images/subscribe-on.png</file>
|
||||
<file>data/images/subscribe-off.png</file>
|
||||
<file>data/qml/ArtistInfoScene.qml</file>
|
||||
<file>data/qml/StationScene.qml</file>
|
||||
<file>data/qml/CoverImage.qml</file>
|
||||
<file>data/qml/TagCloud.qml</file>
|
||||
<file>data/qml/StationConfig.qml</file>
|
||||
<file>data/qml/StationView.qml</file>
|
||||
<file>data/qml/tomahawkimports/InputField.qml</file>
|
||||
<file>data/qml/tomahawkimports/Button.qml</file>
|
||||
<file>data/qml/tomahawkimports/DoubleSlider.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@@ -35,19 +35,11 @@ using namespace Tomahawk;
|
||||
|
||||
QHash< QString, album_ptr > Album::s_albumsByName = QHash< QString, album_ptr >();
|
||||
QHash< unsigned int, album_ptr > Album::s_albumsById = QHash< unsigned int, album_ptr >();
|
||||
QHash< QString, album_ptr > Album::s_albumsByCoverId = QHash< QString, album_ptr >();
|
||||
|
||||
static QMutex s_nameCacheMutex;
|
||||
static QMutex s_idCacheMutex;
|
||||
static QMutex s_mutex;
|
||||
static QReadWriteLock s_idMutex;
|
||||
|
||||
Album::~Album()
|
||||
{
|
||||
m_ownRef.clear();
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
delete m_cover;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline QString
|
||||
albumCacheKey( const Tomahawk::artist_ptr& artist, const QString& albumName )
|
||||
@@ -62,7 +54,7 @@ Album::get( const Tomahawk::artist_ptr& artist, const QString& name, bool autoCr
|
||||
if ( !Database::instance() || !Database::instance()->impl() )
|
||||
return album_ptr();
|
||||
|
||||
QMutexLocker l( &s_nameCacheMutex );
|
||||
QMutexLocker l( &s_mutex );
|
||||
|
||||
const QString key = albumCacheKey( artist, name );
|
||||
if ( s_albumsByName.contains( key ) )
|
||||
@@ -75,6 +67,7 @@ Album::get( const Tomahawk::artist_ptr& artist, const QString& name, bool autoCr
|
||||
album->setWeakRef( album.toWeakRef() );
|
||||
album->loadId( autoCreate );
|
||||
|
||||
s_albumsByCoverId[ album->coverId() ] = album;
|
||||
s_albumsByName[ key ] = album;
|
||||
|
||||
return album;
|
||||
@@ -85,9 +78,8 @@ album_ptr
|
||||
Album::get( unsigned int id, const QString& name, const Tomahawk::artist_ptr& artist )
|
||||
{
|
||||
static QHash< unsigned int, album_ptr > s_albums;
|
||||
static QMutex s_mutex;
|
||||
|
||||
QMutexLocker lock( &s_idCacheMutex );
|
||||
QMutexLocker lock( &s_mutex );
|
||||
if ( s_albumsById.contains( id ) )
|
||||
{
|
||||
return s_albumsById.value( id );
|
||||
@@ -96,6 +88,8 @@ Album::get( unsigned int id, const QString& name, const Tomahawk::artist_ptr& ar
|
||||
album_ptr a = album_ptr( new Album( id, name, artist ), &QObject::deleteLater );
|
||||
a->setWeakRef( a.toWeakRef() );
|
||||
|
||||
s_albumsByCoverId[ a->coverId() ] = a;
|
||||
s_albumsByName[ albumCacheKey( artist, name ) ] = a;
|
||||
if ( id > 0 )
|
||||
s_albumsById.insert( id, a );
|
||||
|
||||
@@ -103,6 +97,18 @@ Album::get( unsigned int id, const QString& name, const Tomahawk::artist_ptr& ar
|
||||
}
|
||||
|
||||
|
||||
album_ptr
|
||||
Album::getByCoverId( const QString& uuid )
|
||||
{
|
||||
QMutexLocker lock( &s_mutex );
|
||||
|
||||
if ( s_albumsByCoverId.contains( uuid ) )
|
||||
return s_albumsByCoverId.value( uuid );
|
||||
|
||||
return album_ptr();
|
||||
}
|
||||
|
||||
|
||||
Album::Album( unsigned int id, const QString& name, const Tomahawk::artist_ptr& artist )
|
||||
: QObject()
|
||||
, m_waitingForId( false )
|
||||
@@ -133,6 +139,23 @@ Album::Album( const QString& name, const Tomahawk::artist_ptr& artist )
|
||||
m_sortname = DatabaseImpl::sortname( name );
|
||||
}
|
||||
|
||||
|
||||
Album::~Album()
|
||||
{
|
||||
QMutexLocker lock( &s_mutex );
|
||||
s_albumsByName.remove( albumCacheKey( artist(), name() ) );
|
||||
s_albumsByCoverId.remove( coverId() );
|
||||
/* if ( id() > 0 )
|
||||
s_albumsById.remove( id() );*/
|
||||
|
||||
m_ownRef.clear();
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
delete m_cover;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Album::onTracksLoaded( Tomahawk::ModelMode mode, const Tomahawk::collection_ptr& collection )
|
||||
{
|
||||
@@ -179,9 +202,12 @@ Album::id() const
|
||||
m_waitingForId = false;
|
||||
|
||||
if ( m_id > 0 )
|
||||
{
|
||||
QMutexLocker lock( &s_mutex );
|
||||
s_albumsById[ m_id ] = m_ownRef.toStrongRef();
|
||||
s_idMutex.unlock();
|
||||
}
|
||||
|
||||
s_idMutex.unlock();
|
||||
}
|
||||
|
||||
return finalId;
|
||||
@@ -202,7 +228,7 @@ Album::cover( const QSize& size, bool forceLoad ) const
|
||||
trackInfo["album"] = name();
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData;
|
||||
requestData.caller = infoid();
|
||||
requestData.caller = uniqueId();
|
||||
requestData.type = Tomahawk::InfoSystem::InfoAlbumCoverArt;
|
||||
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( trackInfo );
|
||||
requestData.customData = QVariantMap();
|
||||
@@ -250,7 +276,7 @@ Album::cover( const QSize& size, bool forceLoad ) const
|
||||
void
|
||||
Album::infoSystemInfo( const Tomahawk::InfoSystem::InfoRequestData& requestData, const QVariant& output )
|
||||
{
|
||||
if ( requestData.caller != infoid() ||
|
||||
if ( requestData.caller != uniqueId() ||
|
||||
requestData.type != Tomahawk::InfoSystem::InfoAlbumCoverArt )
|
||||
{
|
||||
return;
|
||||
@@ -269,7 +295,13 @@ Album::infoSystemInfo( const Tomahawk::InfoSystem::InfoRequestData& requestData,
|
||||
m_coverBuffer = ba;
|
||||
}
|
||||
|
||||
m_coverLoaded = true;
|
||||
{
|
||||
QMutexLocker lock( &s_mutex );
|
||||
m_coverLoaded = true;
|
||||
s_albumsByCoverId.remove( coverId() );
|
||||
m_coverId = uuid();
|
||||
s_albumsByCoverId[ m_coverId ] = m_ownRef.toStrongRef();
|
||||
}
|
||||
emit coverChanged();
|
||||
}
|
||||
}
|
||||
@@ -278,7 +310,7 @@ Album::infoSystemInfo( const Tomahawk::InfoSystem::InfoRequestData& requestData,
|
||||
void
|
||||
Album::infoSystemFinished( const QString& target )
|
||||
{
|
||||
if ( target != infoid() )
|
||||
if ( target != uniqueId() )
|
||||
return;
|
||||
|
||||
disconnect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
@@ -319,10 +351,20 @@ Album::tracks( ModelMode mode, const Tomahawk::collection_ptr& collection )
|
||||
|
||||
|
||||
QString
|
||||
Album::infoid() const
|
||||
Album::uniqueId() const
|
||||
{
|
||||
if ( m_uuid.isEmpty() )
|
||||
m_uuid = uuid();
|
||||
|
||||
return m_uuid;
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
Album::coverId() const
|
||||
{
|
||||
if ( m_coverId.isEmpty() )
|
||||
m_coverId = uuid();
|
||||
|
||||
return m_coverId;
|
||||
}
|
||||
|
@@ -47,6 +47,7 @@ Q_OBJECT
|
||||
public:
|
||||
static album_ptr get( const Tomahawk::artist_ptr& artist, const QString& name, bool autoCreate = false );
|
||||
static album_ptr get( unsigned int id, const QString& name, const Tomahawk::artist_ptr& artist );
|
||||
static album_ptr getByCoverId( const QString& uuid );
|
||||
|
||||
Album( unsigned int id, const QString& name, const Tomahawk::artist_ptr& artist );
|
||||
Album( const QString& name, const Tomahawk::artist_ptr& artist );
|
||||
@@ -55,6 +56,8 @@ public:
|
||||
unsigned int id() const;
|
||||
QString name() const { return m_name; }
|
||||
QString sortname() const { return m_sortname; }
|
||||
QString uniqueId() const;
|
||||
QString coverId() const;
|
||||
|
||||
artist_ptr artist() const;
|
||||
#ifndef ENABLE_HEADLESS
|
||||
@@ -82,7 +85,6 @@ private slots:
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY( Album )
|
||||
QString infoid() const;
|
||||
void setIdFuture( QFuture<unsigned int> future );
|
||||
|
||||
mutable bool m_waitingForId;
|
||||
@@ -97,6 +99,7 @@ private:
|
||||
bool m_coverLoaded;
|
||||
mutable bool m_coverLoading;
|
||||
mutable QString m_uuid;
|
||||
mutable QString m_coverId;
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
mutable QPixmap* m_cover;
|
||||
@@ -109,6 +112,7 @@ private:
|
||||
|
||||
static QHash< QString, album_ptr > s_albumsByName;
|
||||
static QHash< unsigned int, album_ptr > s_albumsById;
|
||||
static QHash< QString, album_ptr > s_albumsByCoverId;
|
||||
|
||||
friend class ::IdThreadWorker;
|
||||
};
|
||||
|
@@ -38,20 +38,11 @@ using namespace Tomahawk;
|
||||
|
||||
QHash< QString, artist_ptr > Artist::s_artistsByName = QHash< QString, artist_ptr >();
|
||||
QHash< unsigned int, artist_ptr > Artist::s_artistsById = QHash< unsigned int, artist_ptr >();
|
||||
QHash< QString, artist_ptr > Artist::s_artistsByCoverId = QHash< QString, artist_ptr >();
|
||||
|
||||
static QMutex s_nameCacheMutex;
|
||||
static QMutex s_idCacheMutex;
|
||||
static QMutex s_mutex;
|
||||
static QReadWriteLock s_idMutex;
|
||||
|
||||
Artist::~Artist()
|
||||
{
|
||||
m_ownRef.clear();
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
delete m_cover;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
artist_ptr
|
||||
Artist::get( const QString& name, bool autoCreate )
|
||||
@@ -59,7 +50,7 @@ Artist::get( const QString& name, bool autoCreate )
|
||||
if ( name.isEmpty() )
|
||||
return artist_ptr();
|
||||
|
||||
QMutexLocker lock( &s_nameCacheMutex );
|
||||
QMutexLocker lock( &s_mutex );
|
||||
if ( s_artistsByName.contains( name ) )
|
||||
return s_artistsByName.value( name );
|
||||
|
||||
@@ -73,6 +64,7 @@ Artist::get( const QString& name, bool autoCreate )
|
||||
artist->setWeakRef( artist.toWeakRef() );
|
||||
artist->loadId( autoCreate );
|
||||
|
||||
s_artistsByCoverId[ artist->coverId() ] = artist;
|
||||
s_artistsByName[ name ] = artist;
|
||||
|
||||
return artist;
|
||||
@@ -82,7 +74,7 @@ Artist::get( const QString& name, bool autoCreate )
|
||||
artist_ptr
|
||||
Artist::get( unsigned int id, const QString& name )
|
||||
{
|
||||
QMutexLocker lock( &s_idCacheMutex );
|
||||
QMutexLocker lock( &s_mutex );
|
||||
if ( s_artistsById.contains( id ) )
|
||||
{
|
||||
return s_artistsById.value( id );
|
||||
@@ -91,6 +83,8 @@ Artist::get( unsigned int id, const QString& name )
|
||||
artist_ptr a = artist_ptr( new Artist( id, name ), &QObject::deleteLater );
|
||||
a->setWeakRef( a.toWeakRef() );
|
||||
|
||||
s_artistsByCoverId[ a->coverId() ] = a;
|
||||
s_artistsByName[ name ] = a;
|
||||
if ( id > 0 )
|
||||
s_artistsById.insert( id, a );
|
||||
|
||||
@@ -98,6 +92,18 @@ Artist::get( unsigned int id, const QString& name )
|
||||
}
|
||||
|
||||
|
||||
artist_ptr
|
||||
Artist::getByCoverId( const QString& uuid )
|
||||
{
|
||||
QMutexLocker lock( &s_mutex );
|
||||
|
||||
if ( s_artistsByCoverId.contains( uuid ) )
|
||||
return s_artistsByCoverId.value( uuid );
|
||||
|
||||
return artist_ptr();
|
||||
}
|
||||
|
||||
|
||||
Artist::Artist( unsigned int id, const QString& name )
|
||||
: QObject()
|
||||
, m_waitingForFuture( false )
|
||||
@@ -134,6 +140,22 @@ Artist::Artist( const QString& name )
|
||||
}
|
||||
|
||||
|
||||
Artist::~Artist()
|
||||
{
|
||||
QMutexLocker lock( &s_mutex );
|
||||
s_artistsByName.remove( name() );
|
||||
s_artistsByCoverId.remove( coverId() );
|
||||
/* if ( id() > 0 )
|
||||
s_artistsById.remove( id() );*/
|
||||
|
||||
m_ownRef.clear();
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
delete m_cover;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Artist::onTracksLoaded( Tomahawk::ModelMode mode, const Tomahawk::collection_ptr& collection )
|
||||
{
|
||||
@@ -168,7 +190,7 @@ Artist::albums( ModelMode mode, const Tomahawk::collection_ptr& collection ) con
|
||||
artistInfo["artist"] = name();
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData;
|
||||
requestData.caller = infoid();
|
||||
requestData.caller = uniqueId();
|
||||
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( artistInfo );
|
||||
requestData.type = Tomahawk::InfoSystem::InfoArtistReleases;
|
||||
|
||||
@@ -208,7 +230,7 @@ Artist::similarArtists() const
|
||||
artistInfo["artist"] = name();
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData;
|
||||
requestData.caller = infoid();
|
||||
requestData.caller = uniqueId();
|
||||
requestData.customData = QVariantMap();
|
||||
|
||||
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( artistInfo );
|
||||
@@ -276,7 +298,11 @@ Artist::id() const
|
||||
m_waitingForFuture = false;
|
||||
|
||||
if ( m_id > 0 )
|
||||
{
|
||||
QMutexLocker lock( &s_mutex );
|
||||
s_artistsById[ m_id ] = m_ownRef.toStrongRef();
|
||||
}
|
||||
|
||||
s_idMutex.unlock();
|
||||
}
|
||||
|
||||
@@ -290,7 +316,7 @@ Artist::biography() const
|
||||
if ( !m_biographyLoaded )
|
||||
{
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData;
|
||||
requestData.caller = infoid();
|
||||
requestData.caller = uniqueId();
|
||||
requestData.customData = QVariantMap();
|
||||
|
||||
requestData.input = name();
|
||||
@@ -378,7 +404,7 @@ Artist::onAlbumsFound( const QList< album_ptr >& albums, const QVariant& data )
|
||||
void
|
||||
Artist::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output )
|
||||
{
|
||||
if ( requestData.caller != infoid() )
|
||||
if ( requestData.caller != uniqueId() )
|
||||
return;
|
||||
|
||||
QVariantMap returnedData = output.value< QVariantMap >();
|
||||
@@ -419,7 +445,13 @@ Artist::infoSystemInfo( Tomahawk::InfoSystem::InfoRequestData requestData, QVari
|
||||
m_coverBuffer = ba;
|
||||
}
|
||||
|
||||
m_coverLoaded = true;
|
||||
{
|
||||
QMutexLocker lock( &s_mutex );
|
||||
m_coverLoaded = true;
|
||||
s_artistsByCoverId.remove( coverId() );
|
||||
m_coverId = uuid();
|
||||
s_artistsByCoverId[ m_coverId ] = m_ownRef.toStrongRef();
|
||||
}
|
||||
emit coverChanged();
|
||||
}
|
||||
|
||||
@@ -467,7 +499,7 @@ Artist::infoSystemFinished( QString target )
|
||||
{
|
||||
Q_UNUSED( target );
|
||||
|
||||
if ( target != infoid() )
|
||||
if ( target != uniqueId() )
|
||||
return;
|
||||
|
||||
if ( --m_infoJobs == 0 )
|
||||
@@ -498,7 +530,7 @@ Artist::cover( const QSize& size, bool forceLoad ) const
|
||||
trackInfo["artist"] = name();
|
||||
|
||||
Tomahawk::InfoSystem::InfoRequestData requestData;
|
||||
requestData.caller = infoid();
|
||||
requestData.caller = uniqueId();
|
||||
requestData.type = Tomahawk::InfoSystem::InfoArtistImages;
|
||||
requestData.input = QVariant::fromValue< Tomahawk::InfoSystem::InfoStringHash >( trackInfo );
|
||||
requestData.customData = QVariantMap();
|
||||
@@ -571,10 +603,20 @@ Artist::tracks( ModelMode mode, const Tomahawk::collection_ptr& collection )
|
||||
|
||||
|
||||
QString
|
||||
Artist::infoid() const
|
||||
Artist::uniqueId() const
|
||||
{
|
||||
if ( m_uuid.isEmpty() )
|
||||
m_uuid = uuid();
|
||||
|
||||
return m_uuid;
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
Artist::coverId() const
|
||||
{
|
||||
if ( m_coverId.isEmpty() )
|
||||
m_coverId = uuid();
|
||||
|
||||
return m_coverId;
|
||||
}
|
||||
|
@@ -46,6 +46,7 @@ Q_OBJECT
|
||||
public:
|
||||
static artist_ptr get( const QString& name, bool autoCreate = false );
|
||||
static artist_ptr get( unsigned int id, const QString& name );
|
||||
static artist_ptr getByCoverId( const QString& uuid );
|
||||
|
||||
Artist( unsigned int id, const QString& name );
|
||||
explicit Artist( const QString& name );
|
||||
@@ -54,6 +55,8 @@ public:
|
||||
unsigned int id() const;
|
||||
QString name() const { return m_name; }
|
||||
QString sortname() const { return m_sortname; }
|
||||
QString uniqueId() const;
|
||||
QString coverId() const;
|
||||
|
||||
QList<Tomahawk::album_ptr> albums( ModelMode mode = Mixed, const Tomahawk::collection_ptr& collection = Tomahawk::collection_ptr() ) const;
|
||||
QList<Tomahawk::artist_ptr> similarArtists() const;
|
||||
@@ -65,7 +68,7 @@ public:
|
||||
QList< Tomahawk::PlaybackLog > playbackHistory( const Tomahawk::source_ptr& source = Tomahawk::source_ptr() ) const;
|
||||
void setPlaybackHistory( const QList< Tomahawk::PlaybackLog >& playbackData );
|
||||
unsigned int playbackCount( const Tomahawk::source_ptr& source = Tomahawk::source_ptr() );
|
||||
|
||||
|
||||
QString biography() const;
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
@@ -98,7 +101,6 @@ private slots:
|
||||
|
||||
private:
|
||||
Artist();
|
||||
QString infoid() const;
|
||||
|
||||
void setIdFuture( QFuture<unsigned int> idFuture );
|
||||
|
||||
@@ -116,6 +118,7 @@ private:
|
||||
bool m_biographyLoaded;
|
||||
|
||||
mutable QString m_uuid;
|
||||
mutable QString m_coverId;
|
||||
mutable int m_infoJobs;
|
||||
|
||||
QList<Tomahawk::album_ptr> m_databaseAlbums;
|
||||
@@ -133,11 +136,12 @@ private:
|
||||
#endif
|
||||
|
||||
QHash< Tomahawk::ModelMode, QHash< Tomahawk::collection_ptr, Tomahawk::playlistinterface_ptr > > m_playlistInterface;
|
||||
|
||||
|
||||
QWeakPointer< Tomahawk::Artist > m_ownRef;
|
||||
|
||||
static QHash< QString, artist_ptr > s_artistsByName;
|
||||
static QHash< unsigned int, artist_ptr > s_artistsById;
|
||||
static QHash< QString, artist_ptr > s_artistsByCoverId;
|
||||
|
||||
friend class ::IdThreadWorker;
|
||||
};
|
||||
|
@@ -82,7 +82,9 @@ set( libGuiSources
|
||||
playlist/dynamic/echonest/EchonestGenerator.cpp
|
||||
playlist/dynamic/echonest/EchonestControl.cpp
|
||||
playlist/dynamic/echonest/EchonestSteerer.cpp
|
||||
playlist/dynamic/echonest/EchonestStation.cpp
|
||||
playlist/dynamic/widgets/DynamicWidget.cpp
|
||||
playlist/dynamic/widgets/DynamicQmlWidget.cpp
|
||||
playlist/dynamic/widgets/DynamicControlWrapper.cpp
|
||||
playlist/dynamic/widgets/DynamicControlList.cpp
|
||||
playlist/dynamic/widgets/ReadOrWriteWidget.cpp
|
||||
@@ -140,11 +142,13 @@ set( libGuiSources
|
||||
widgets/ToggleButton.cpp
|
||||
widgets/FadingPixmap.cpp
|
||||
widgets/SocialPlaylistWidget.cpp
|
||||
widgets/DeclarativeCoverArtProvider.cpp
|
||||
widgets/SourceTreePopupDialog.cpp
|
||||
widgets/infowidgets/SourceInfoWidget.cpp
|
||||
widgets/infowidgets/ArtistInfoWidget.cpp
|
||||
widgets/infowidgets/AlbumInfoWidget.cpp
|
||||
widgets/infowidgets/TrackInfoWidget.cpp
|
||||
widgets/infowidgets/AlbumArtImageProvider.cpp
|
||||
widgets/searchlineedit/ClearButton.cpp
|
||||
widgets/searchlineedit/LineEdit.cpp
|
||||
widgets/searchlineedit/SearchButton.cpp
|
||||
@@ -456,6 +460,7 @@ TARGET_LINK_LIBRARIES( tomahawklib
|
||||
${QT_QTNETWORK_LIBRARY}
|
||||
${QT_QTXML_LIBRARY}
|
||||
${QT_QTCORE_LIBRARY}
|
||||
${QT_QTDECLARATIVE_LIBRARY}
|
||||
${OS_SPECIFIC_LINK_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${LINK_LIBRARIES}
|
||||
|
@@ -82,8 +82,11 @@ PlaybackLog::PlaybackLog( const PlaybackLog& other )
|
||||
query_ptr
|
||||
Query::get( const QString& artist, const QString& track, const QString& album, const QID& qid, bool autoResolve )
|
||||
{
|
||||
if ( artist.trimmed().isEmpty() || track.trimmed().isEmpty() )
|
||||
if ( artist.trimmed().isEmpty() || track.trimmed().isEmpty() )
|
||||
{
|
||||
Q_ASSERT( false );
|
||||
return query_ptr();
|
||||
}
|
||||
|
||||
if ( qid.isEmpty() )
|
||||
autoResolve = false;
|
||||
@@ -150,6 +153,7 @@ Query::Query( const QString& query, const QID& qid )
|
||||
Query::~Query()
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_ownRef.clear();
|
||||
m_results.clear();
|
||||
}
|
||||
@@ -349,6 +353,22 @@ Query::id() const
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
Query::coverId() const
|
||||
{
|
||||
if ( m_albumPtr && m_albumPtr->coverLoaded() && !m_albumPtr->cover( QSize( 0, 0 ) ).isNull() )
|
||||
{
|
||||
return m_albumPtr->coverId();
|
||||
}
|
||||
else if ( m_artistPtr )
|
||||
{
|
||||
return m_artistPtr->coverId();
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Query::setPlayedBy( const Tomahawk::source_ptr& source, unsigned int playtime )
|
||||
{
|
||||
|
@@ -95,6 +95,7 @@ public:
|
||||
unsigned int numResults() const;
|
||||
|
||||
QID id() const;
|
||||
QString coverId() const;
|
||||
|
||||
/// sorter for list of results
|
||||
static bool resultSorter( const result_ptr& left, const result_ptr& right );
|
||||
|
@@ -42,6 +42,7 @@
|
||||
#include "PlaylistLargeItemDelegate.h"
|
||||
#include "RecentlyPlayedModel.h"
|
||||
#include "dynamic/widgets/DynamicWidget.h"
|
||||
#include "dynamic/widgets/DynamicQmlWidget.h"
|
||||
|
||||
#include "widgets/NewReleasesWidget.h"
|
||||
#include "widgets/WelcomeWidget.h"
|
||||
@@ -190,7 +191,7 @@ ViewManager::show( const Tomahawk::dynplaylist_ptr& playlist )
|
||||
{
|
||||
if ( !m_dynamicWidgets.contains( playlist ) || m_dynamicWidgets.value( playlist ).isNull() )
|
||||
{
|
||||
m_dynamicWidgets[ playlist ] = new Tomahawk::DynamicWidget( playlist, m_stack );
|
||||
m_dynamicWidgets[ playlist ] = new Tomahawk::DynamicQmlWidget( playlist, m_stack );
|
||||
|
||||
playlist->resolve();
|
||||
}
|
||||
@@ -832,7 +833,7 @@ ViewManager::playlistForInterface( Tomahawk::playlistinterface_ptr interface ) c
|
||||
Tomahawk::dynplaylist_ptr
|
||||
ViewManager::dynamicPlaylistForInterface( Tomahawk::playlistinterface_ptr interface ) const
|
||||
{
|
||||
foreach ( QWeakPointer<DynamicWidget> view, m_dynamicWidgets.values() )
|
||||
foreach ( QWeakPointer<DynamicQmlWidget> view, m_dynamicWidgets.values() )
|
||||
{
|
||||
if ( !view.isNull() && view.data()->playlistInterface() == interface )
|
||||
{
|
||||
|
@@ -59,6 +59,7 @@ class QPushButton;
|
||||
namespace Tomahawk
|
||||
{
|
||||
class DynamicWidget;
|
||||
class DynamicQmlWidget;
|
||||
}
|
||||
|
||||
class DLLEXPORT ViewManager : public QObject
|
||||
@@ -196,7 +197,7 @@ private:
|
||||
|
||||
QList< Tomahawk::collection_ptr > m_superCollections;
|
||||
|
||||
QHash< Tomahawk::dynplaylist_ptr, QWeakPointer<Tomahawk::DynamicWidget> > m_dynamicWidgets;
|
||||
QHash< Tomahawk::dynplaylist_ptr, QWeakPointer<Tomahawk::DynamicQmlWidget> > m_dynamicWidgets;
|
||||
QHash< Tomahawk::collection_ptr, QWeakPointer<TreeView> > m_treeViews;
|
||||
QHash< Tomahawk::artist_ptr, QWeakPointer<ArtistInfoWidget> > m_artistViews;
|
||||
QHash< Tomahawk::album_ptr, QWeakPointer<AlbumInfoWidget> > m_albumViews;
|
||||
|
@@ -520,19 +520,12 @@ LastFmInfoPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::In
|
||||
QString artistName = criteria["artist"];
|
||||
QString albumName = criteria["album"];
|
||||
|
||||
QUrl imgurl( "http://ws.audioscrobbler.com/2.0/" );
|
||||
imgurl.addQueryItem( "method", "album.imageredirect" );
|
||||
imgurl.addEncodedQueryItem( "artist", QUrl::toPercentEncoding( artistName, "", "+" ) );
|
||||
imgurl.addEncodedQueryItem( "album", QUrl::toPercentEncoding( albumName, "", "+" ) );
|
||||
imgurl.addQueryItem( "autocorrect", QString::number( 1 ) );
|
||||
imgurl.addQueryItem( "size", "large" );
|
||||
imgurl.addQueryItem( "api_key", "7a90f6672a04b809ee309af169f34b8b" );
|
||||
lastfm::Artist lfmArtist( artistName );
|
||||
lastfm::Album lfmAlbum( lfmArtist, albumName );
|
||||
|
||||
QNetworkRequest req( imgurl );
|
||||
QNetworkReply* reply = TomahawkUtils::nam()->get( req );
|
||||
QNetworkReply* reply = lfmAlbum.getInfo();
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
|
||||
connect( reply, SIGNAL( finished() ), SLOT( coverArtReturned() ) );
|
||||
connect( reply, SIGNAL( finished() ), SLOT( albumInfoReturned() ) );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -726,6 +719,40 @@ LastFmInfoPlugin::topTracksReturned()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmInfoPlugin::albumInfoReturned()
|
||||
{
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
|
||||
QHash< QString, QString > covers;
|
||||
QString url;
|
||||
|
||||
lastfm::XmlQuery lfm;
|
||||
lfm.parse( reply->readAll() );
|
||||
|
||||
foreach ( lastfm::XmlQuery xq, lfm.children( "album" ) )
|
||||
{
|
||||
foreach ( lastfm::XmlQuery xxq, xq.children( "image" ) )
|
||||
{
|
||||
covers[ xxq.attribute( "size" ).toLower() ] = xxq.text();
|
||||
}
|
||||
}
|
||||
|
||||
if ( covers.contains( "mega" ) )
|
||||
url = covers[ "mega" ];
|
||||
else if ( covers.contains( "extralarge" ) )
|
||||
url = covers[ "extralarge" ];
|
||||
else if ( covers.contains( "large" ) )
|
||||
url = covers[ "large" ];
|
||||
else if ( covers.contains( "medium" ) )
|
||||
url = covers[ "medium" ];
|
||||
|
||||
QNetworkRequest req( url );
|
||||
QNetworkReply* newReply = TomahawkUtils::nam()->get( req );
|
||||
newReply->setProperty( "requestData", reply->property( "requestData" ) );
|
||||
connect( newReply, SIGNAL( finished() ), SLOT( coverArtReturned() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmInfoPlugin::coverArtReturned()
|
||||
{
|
||||
|
@@ -61,6 +61,7 @@ public slots:
|
||||
void topTracksReturned();
|
||||
void chartReturned();
|
||||
void similarTracksReturned();
|
||||
void albumInfoReturned();
|
||||
|
||||
protected slots:
|
||||
virtual void init();
|
||||
|
@@ -53,9 +53,11 @@ PlayableItem::PlayableItem( const Tomahawk::album_ptr& album, PlayableItem* pare
|
||||
: QObject( parent )
|
||||
, m_album( album )
|
||||
{
|
||||
Q_ASSERT( !m_album.isNull() );
|
||||
init( parent, row );
|
||||
|
||||
connect( album.data(), SIGNAL( updated() ), SIGNAL( dataChanged() ) );
|
||||
connect( album.data(), SIGNAL( coverChanged() ), SIGNAL( coverChanged() ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -63,9 +65,11 @@ PlayableItem::PlayableItem( const Tomahawk::artist_ptr& artist, PlayableItem* pa
|
||||
: QObject( parent )
|
||||
, m_artist( artist )
|
||||
{
|
||||
Q_ASSERT( !m_artist.isNull() );
|
||||
init( parent, row );
|
||||
|
||||
connect( artist.data(), SIGNAL( updated() ), SIGNAL( dataChanged() ) );
|
||||
connect( artist.data(), SIGNAL( coverChanged() ), SIGNAL( coverChanged() ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -73,6 +77,7 @@ PlayableItem::PlayableItem( const Tomahawk::result_ptr& result, PlayableItem* pa
|
||||
: QObject( parent )
|
||||
, m_result( result )
|
||||
{
|
||||
Q_ASSERT( !m_result.isNull() );
|
||||
init( parent, row );
|
||||
}
|
||||
|
||||
@@ -81,6 +86,7 @@ PlayableItem::PlayableItem( const Tomahawk::query_ptr& query, PlayableItem* pare
|
||||
: QObject( parent )
|
||||
, m_query( query )
|
||||
{
|
||||
Q_ASSERT( !m_query.isNull() );
|
||||
init( parent, row );
|
||||
|
||||
connect( query.data(), SIGNAL( socialActionsLoaded() ),
|
||||
@@ -91,6 +97,9 @@ PlayableItem::PlayableItem( const Tomahawk::query_ptr& query, PlayableItem* pare
|
||||
|
||||
connect( query.data(), SIGNAL( resultsChanged() ),
|
||||
SLOT( onResultsChanged() ) );
|
||||
|
||||
connect( query->displayQuery().data(), SIGNAL( coverChanged() ), SIGNAL( coverChanged() ) );
|
||||
connect( query->displayQuery().data(), SIGNAL( coverChanged() ), SIGNAL( dataChanged() ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -99,6 +108,7 @@ PlayableItem::PlayableItem( const Tomahawk::plentry_ptr& entry, PlayableItem* pa
|
||||
, m_entry( entry )
|
||||
{
|
||||
m_query = entry->query();
|
||||
Q_ASSERT( !m_query.isNull() );
|
||||
init( parent, row );
|
||||
|
||||
connect( m_query.data(), SIGNAL( socialActionsLoaded() ),
|
||||
@@ -109,6 +119,9 @@ PlayableItem::PlayableItem( const Tomahawk::plentry_ptr& entry, PlayableItem* pa
|
||||
|
||||
connect( m_query.data(), SIGNAL( resultsChanged() ),
|
||||
SLOT( onResultsChanged() ) );
|
||||
|
||||
connect( m_query->displayQuery().data(), SIGNAL( coverChanged() ), SIGNAL( coverChanged() ) );
|
||||
connect( m_query->displayQuery().data(), SIGNAL( coverChanged() ), SIGNAL( dataChanged() ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -145,7 +158,16 @@ void
|
||||
PlayableItem::onResultsChanged()
|
||||
{
|
||||
if ( !m_query->results().isEmpty() )
|
||||
{
|
||||
m_result = m_query->results().first();
|
||||
if ( m_query->displayQuery()->coverLoaded() )
|
||||
{
|
||||
emit coverChanged();
|
||||
}
|
||||
|
||||
connect( m_query->displayQuery().data(), SIGNAL( coverChanged() ), SIGNAL( dataChanged() ) );
|
||||
connect( m_query->displayQuery().data(), SIGNAL( coverChanged() ), SIGNAL( coverChanged() ) );
|
||||
}
|
||||
else
|
||||
m_result = result_ptr();
|
||||
|
||||
|
@@ -30,7 +30,9 @@
|
||||
class DLLEXPORT PlayableItem : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QString name READ name NOTIFY dataChanged)
|
||||
Q_PROPERTY(QString artistName READ artistName NOTIFY dataChanged)
|
||||
Q_PROPERTY(QString albumName READ albumName NOTIFY dataChanged)
|
||||
public:
|
||||
~PlayableItem();
|
||||
|
||||
@@ -65,6 +67,7 @@ public:
|
||||
|
||||
signals:
|
||||
void dataChanged();
|
||||
void coverChanged();
|
||||
|
||||
private slots:
|
||||
void onResultsChanged();
|
||||
|
@@ -43,6 +43,12 @@ PlayableModel::PlayableModel( QObject* parent, bool loading )
|
||||
, m_readOnly( true )
|
||||
, m_loading( loading )
|
||||
{
|
||||
QHash<int, QByteArray> roleNames;
|
||||
roleNames.insert( ArtistRole, "artistName" );
|
||||
roleNames.insert( TrackRole, "trackName" );
|
||||
roleNames.insert( CoverIDRole, "coverID" );
|
||||
setRoleNames( roleNames );
|
||||
|
||||
connect( AudioEngine::instance(), SIGNAL( started( Tomahawk::result_ptr ) ), SLOT( onPlaybackStarted( Tomahawk::result_ptr ) ), Qt::DirectConnection );
|
||||
connect( AudioEngine::instance(), SIGNAL( stopped() ), SLOT( onPlaybackStopped() ), Qt::DirectConnection );
|
||||
|
||||
@@ -160,6 +166,12 @@ PlayableModel::queryData( const query_ptr& query, int column, int role ) const
|
||||
if ( role == Qt::SizeHintRole )
|
||||
return QSize( 0, 18 );
|
||||
|
||||
if ( role == CoverIDRole )
|
||||
{
|
||||
query->cover( QSize( 0, 0 ) );
|
||||
return query->coverId();
|
||||
}
|
||||
|
||||
if ( role != Qt::DisplayRole ) // && role != Qt::ToolTipRole )
|
||||
return QVariant();
|
||||
|
||||
@@ -192,7 +204,7 @@ PlayableModel::queryData( const query_ptr& query, int column, int role ) const
|
||||
if ( query->albumpos() != 0 )
|
||||
{
|
||||
tPos = QString::number( query->albumpos() );
|
||||
if( query->discnumber() == 0 )
|
||||
if ( query->discnumber() == 0 )
|
||||
return tPos;
|
||||
else
|
||||
return QString( "%1.%2" ).arg( QString::number( query->discnumber() ) )
|
||||
@@ -254,15 +266,22 @@ PlayableModel::data( const QModelIndex& index, int role ) const
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
if ( role == Qt::TextAlignmentRole )
|
||||
else if ( role == Qt::TextAlignmentRole )
|
||||
{
|
||||
return QVariant( columnAlignment( index.column() ) );
|
||||
}
|
||||
|
||||
int column = index.column();
|
||||
if ( role < CoverIDRole && role >= Qt::UserRole )
|
||||
{
|
||||
// Map user-role to column
|
||||
column = role - Qt::UserRole;
|
||||
role = Qt::DisplayRole;
|
||||
}
|
||||
|
||||
if ( !entry->query().isNull() )
|
||||
{
|
||||
return queryData( entry->query()->displayQuery(), index.column(), role );
|
||||
return queryData( entry->query()->displayQuery(), column, role );
|
||||
}
|
||||
else if ( !entry->artist().isNull() )
|
||||
{
|
||||
@@ -320,6 +339,7 @@ PlayableModel::setCurrentItem( const QModelIndex& index )
|
||||
m_currentIndex = QModelIndex();
|
||||
m_currentUuid = QString();
|
||||
}
|
||||
emit currentItemChanged( m_currentIndex );
|
||||
}
|
||||
|
||||
|
||||
@@ -719,6 +739,18 @@ PlayableModel::itemFromIndex( const QModelIndex& index ) const
|
||||
}
|
||||
}
|
||||
|
||||
PlayableItem *PlayableModel::itemFromIndex(int itemIndex) const
|
||||
{
|
||||
QModelIndex modelIndex = index( itemIndex, 0, QModelIndex() );
|
||||
if ( modelIndex.isValid() )
|
||||
{
|
||||
return static_cast<PlayableItem*>( modelIndex.internalPointer() );
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_rootItem;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PlayableModel::appendArtist( const Tomahawk::artist_ptr& artist )
|
||||
|
@@ -38,7 +38,8 @@ class DLLEXPORT PlayableModel : public QAbstractItemModel
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Columns {
|
||||
enum Columns
|
||||
{
|
||||
Artist = 0,
|
||||
Track = 1,
|
||||
Composer = 2,
|
||||
@@ -54,6 +55,25 @@ public:
|
||||
Name = 12
|
||||
};
|
||||
|
||||
enum PlayableRoles
|
||||
{
|
||||
ArtistRole = Qt::UserRole,
|
||||
TrackRole,
|
||||
ComposerRole,
|
||||
AlbumRole,
|
||||
AlbumPosRole,
|
||||
DurationRole,
|
||||
BitrateRole,
|
||||
AgeRole,
|
||||
YearRole,
|
||||
FilesizeRole,
|
||||
OriginRole,
|
||||
ScoreRole,
|
||||
NameRole,
|
||||
CoverIDRole
|
||||
};
|
||||
|
||||
|
||||
explicit PlayableModel( QObject* parent = 0, bool loading = true );
|
||||
virtual ~PlayableModel();
|
||||
|
||||
@@ -99,6 +119,8 @@ public:
|
||||
virtual void ensureResolved();
|
||||
|
||||
PlayableItem* itemFromIndex( const QModelIndex& index ) const;
|
||||
Q_INVOKABLE PlayableItem* itemFromIndex( int itemIndex ) const;
|
||||
|
||||
/// Returns a flat list of all tracks in this model
|
||||
QList< Tomahawk::query_ptr > queries() const;
|
||||
|
||||
@@ -115,6 +137,8 @@ signals:
|
||||
void loadingStarted();
|
||||
void loadingFinished();
|
||||
|
||||
void currentItemChanged( const QPersistentModelIndex ¤tIndex );
|
||||
|
||||
public slots:
|
||||
virtual void setCurrentItem( const QModelIndex& index );
|
||||
|
||||
|
@@ -583,3 +583,11 @@ PlayableProxyModel::setFilter( const QString& pattern )
|
||||
emit filterChanged( pattern );
|
||||
}
|
||||
}
|
||||
|
||||
PlayableItem*
|
||||
PlayableProxyModel::itemFromIndex(int itemIndex) const
|
||||
{
|
||||
// qDebug() << "returning item" << sourceModel()->itemFromIndex( itemIndex )->name();
|
||||
QModelIndex modelIndex = index( itemIndex, 0 );
|
||||
return sourceModel()->itemFromIndex( mapToSource( modelIndex ) );
|
||||
}
|
||||
|
@@ -36,7 +36,7 @@ public:
|
||||
{ Detailed = 0, Short = 1, ShortWithAvatars = 2, Large = 3, Collection = 4 };
|
||||
|
||||
enum PlayableProxyModelRole
|
||||
{ StyleRole = Qt::UserRole + 1 };
|
||||
{ StyleRole = Qt::UserRole + 100 };
|
||||
|
||||
explicit PlayableProxyModel ( QObject* parent = 0 );
|
||||
virtual ~PlayableProxyModel() {}
|
||||
@@ -67,6 +67,7 @@ public:
|
||||
virtual void setMaxVisibleItems( int items );
|
||||
|
||||
virtual PlayableItem* itemFromIndex( const QModelIndex& index ) const { return sourceModel()->itemFromIndex( index ); }
|
||||
Q_INVOKABLE virtual PlayableItem* itemFromIndex( int itemIndex ) const;
|
||||
|
||||
virtual Tomahawk::playlistinterface_ptr playlistInterface();
|
||||
|
||||
|
@@ -56,6 +56,7 @@ void
|
||||
Tomahawk::GeneratorInterface::addControl( const Tomahawk::dyncontrol_ptr& control )
|
||||
{
|
||||
m_controls << control;
|
||||
emit controlAdded( control );
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +78,7 @@ void
|
||||
Tomahawk::GeneratorInterface::removeControl( const Tomahawk::dyncontrol_ptr& control )
|
||||
{
|
||||
m_controls.removeAll( control );
|
||||
controlRemoved( control );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -59,7 +59,7 @@ public:
|
||||
// empty QString means use default
|
||||
/// The generator will keep track of all the controls it creates. No need to tell it about controls
|
||||
/// you ask it to create
|
||||
virtual dyncontrol_ptr createControl( const QString& type = QString() );
|
||||
Q_INVOKABLE virtual dyncontrol_ptr createControl( const QString& type = QString() );
|
||||
|
||||
/// A logo to display for this generator, if it has one
|
||||
virtual QPixmap logo();
|
||||
@@ -127,6 +127,8 @@ signals:
|
||||
void error( const QString& title, const QString& body);
|
||||
void generated( const QList< Tomahawk::query_ptr>& queries );
|
||||
void nextTrackGenerated( const Tomahawk::query_ptr& track );
|
||||
void controlAdded(const dyncontrol_ptr& control);
|
||||
void controlRemoved(const dyncontrol_ptr& control);
|
||||
|
||||
protected:
|
||||
QString m_type;
|
||||
|
@@ -156,6 +156,7 @@ dyncontrol_ptr
|
||||
EchonestGenerator::createControl( const QString& type )
|
||||
{
|
||||
m_controls << dyncontrol_ptr( new EchonestControl( type, GeneratorFactory::typeSelectors( m_type ) ) );
|
||||
emit controlAdded( m_controls.last() );
|
||||
return m_controls.last();
|
||||
}
|
||||
|
||||
@@ -336,6 +337,8 @@ EchonestGenerator::getParams() throw( std::runtime_error )
|
||||
} else {
|
||||
emit paramsGenerated( params );
|
||||
}
|
||||
|
||||
qDebug() << "ParamsGenerated" << params;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -71,7 +71,7 @@ public:
|
||||
explicit EchonestGenerator( QObject* parent = 0 );
|
||||
virtual ~EchonestGenerator();
|
||||
|
||||
virtual dyncontrol_ptr createControl( const QString& type = QString() );
|
||||
Q_INVOKABLE virtual dyncontrol_ptr createControl( const QString& type = QString() );
|
||||
virtual QPixmap logo();
|
||||
virtual void generate ( int number = -1 );
|
||||
virtual void startOnDemand();
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
virtual bool onDemandSteerable() const { return false; }
|
||||
virtual QWidget* steeringWidget() { return 0; }
|
||||
|
||||
static QStringList styles();
|
||||
Q_INVOKABLE static QStringList styles();
|
||||
static QStringList moods();
|
||||
static QStringList userCatalogs();
|
||||
static QByteArray catalogId( const QString& collectionId );
|
||||
|
129
src/libtomahawk/playlist/dynamic/echonest/EchonestStation.cpp
Normal file
129
src/libtomahawk/playlist/dynamic/echonest/EchonestStation.cpp
Normal file
@@ -0,0 +1,129 @@
|
||||
#include "EchonestStation.h"
|
||||
#include "dynamic/DynamicPlaylist.h"
|
||||
|
||||
#include "PlayableItem.h"
|
||||
#include "audio/AudioEngine.h"
|
||||
|
||||
#include <echonest/Playlist.h>
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
EchonestStation::EchonestStation( PlayableProxyModel *model, dynplaylist_ptr playlist, QObject *parent )
|
||||
: QObject( parent )
|
||||
, m_name( model->sourceModel()->title() )
|
||||
, m_model( model )
|
||||
, m_playlist( playlist )
|
||||
{
|
||||
connect(m_playlist->generator().data(), SIGNAL(controlAdded(const dyncontrol_ptr&)), SLOT(controlsChanged()));
|
||||
}
|
||||
|
||||
QString EchonestStation::name() const
|
||||
{
|
||||
return m_playlist->title();
|
||||
}
|
||||
|
||||
void EchonestStation::setName(const QString &name)
|
||||
{
|
||||
m_playlist->setTitle( name );
|
||||
emit nameChanged();
|
||||
}
|
||||
|
||||
Tomahawk::DynamicControl* EchonestStation::mainControl() {
|
||||
foreach(dyncontrol_ptr control, m_playlist->generator()->controls()) {
|
||||
qDebug() << "got control" << control->selectedType();
|
||||
if(control->selectedType() == "Artist" || control->selectedType() == "Style") {
|
||||
return control.data();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool EchonestStation::configured()
|
||||
{
|
||||
return mainControl() != 0;
|
||||
}
|
||||
|
||||
int EchonestStation::minTempo() const
|
||||
{
|
||||
dyncontrol_ptr minTempoControl = findControl( "Tempo", "min_tempo" );
|
||||
return minTempoControl.isNull() ? 0 : minTempoControl->input().toInt();
|
||||
}
|
||||
|
||||
int EchonestStation::maxTempo() const
|
||||
{
|
||||
dyncontrol_ptr maxTempoControl = findControl( "Tempo", "max_tempo" );
|
||||
return maxTempoControl.isNull() ? 500 : maxTempoControl->input().toInt();
|
||||
}
|
||||
|
||||
void EchonestStation::playItem(int row)
|
||||
{
|
||||
QModelIndex index( m_model->index( row, 0) );
|
||||
if( index.isValid() ) {
|
||||
PlayableItem* item = m_model->itemFromIndex( index );
|
||||
if ( item && !item->query().isNull() )
|
||||
{
|
||||
m_model->setCurrentIndex( index );
|
||||
AudioEngine::instance()->playItem( m_model->playlistInterface(), item->query() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EchonestStation::setMainControl( StationType type, const QString &value )
|
||||
{
|
||||
dyncontrol_ptr control = m_playlist->generator()->createControl( "echonest" );
|
||||
if ( type == StationTypeStyle ) {
|
||||
control->setSelectedType( "Style" );
|
||||
} else if ( type == StationTypeArtist ) {
|
||||
control->setSelectedType( "Artist" );
|
||||
}
|
||||
control->setMatch( "1" );
|
||||
control->setInput( value );
|
||||
qDebug() << "created control" << control->type() << control->selectedType() << control->match();
|
||||
m_playlist->generator()->generate( 20 );
|
||||
|
||||
emit configurationChanged();
|
||||
}
|
||||
|
||||
void EchonestStation::setTempo(int min, int max)
|
||||
{
|
||||
dyncontrol_ptr tempoMinControl = findControl("Tempo", "min_tempo");
|
||||
dyncontrol_ptr tempoMaxControl = findControl("Tempo", "max_tempo");
|
||||
|
||||
if ( tempoMinControl.isNull() ) {
|
||||
tempoMinControl = m_playlist->generator()->createControl( "echonest" );
|
||||
tempoMinControl->setSelectedType( "Tempo" );
|
||||
tempoMinControl->setMatch( "min_tempo" );
|
||||
}
|
||||
|
||||
if ( tempoMaxControl.isNull() ) {
|
||||
tempoMaxControl = m_playlist->generator()->createControl( "echonest" );
|
||||
tempoMaxControl->setSelectedType( "Tempo" );
|
||||
tempoMaxControl->setMatch( "max_tempo" );
|
||||
}
|
||||
|
||||
tempoMinControl->setInput( QString::number( min ) );
|
||||
tempoMaxControl->setInput( QString::number( max ) );
|
||||
|
||||
m_playlist->generator()->generate(20);
|
||||
|
||||
emit configurationChanged();
|
||||
}
|
||||
|
||||
dyncontrol_ptr EchonestStation::findControl(const QString &selectedType, const QString &match) const
|
||||
{
|
||||
foreach ( dyncontrol_ptr control, m_playlist->generator()->controls() ) {
|
||||
if ( control->selectedType() == selectedType && control->match() == match ) {
|
||||
return control;
|
||||
}
|
||||
}
|
||||
return dyncontrol_ptr();
|
||||
}
|
||||
|
||||
void EchonestStation::controlsChanged()
|
||||
{
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
59
src/libtomahawk/playlist/dynamic/echonest/EchonestStation.h
Normal file
59
src/libtomahawk/playlist/dynamic/echonest/EchonestStation.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#ifndef ECHONESTSTATION_H
|
||||
#define ECHONESTSTATION_H
|
||||
|
||||
#include "PlayableProxyModel.h"
|
||||
#include "dynamic/GeneratorInterface.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
class EchonestStation: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_ENUMS(StationType)
|
||||
Q_PROPERTY( QString name READ name WRITE setName NOTIFY nameChanged )
|
||||
Q_PROPERTY( bool configured READ configured NOTIFY configurationChanged )
|
||||
Q_PROPERTY( Tomahawk::DynamicControl* mainControl READ mainControl )
|
||||
Q_PROPERTY( int minTempo READ minTempo NOTIFY configurationChanged )
|
||||
Q_PROPERTY( int maxTempo READ maxTempo NOTIFY configurationChanged )
|
||||
|
||||
public:
|
||||
enum StationType {
|
||||
StationTypeStyle,
|
||||
StationTypeArtist
|
||||
};
|
||||
|
||||
EchonestStation( PlayableProxyModel *model, dynplaylist_ptr playlist, QObject *parent = 0);
|
||||
|
||||
QString name() const;
|
||||
void setName( const QString &name );
|
||||
|
||||
Tomahawk::DynamicControl* mainControl();
|
||||
bool configured();
|
||||
|
||||
int minTempo() const;
|
||||
int maxTempo() const;
|
||||
|
||||
public slots:
|
||||
void playItem( int row );
|
||||
|
||||
void setMainControl(StationType type, const QString &value);
|
||||
void setTempo( int min, int max );
|
||||
|
||||
signals:
|
||||
void nameChanged();
|
||||
void configurationChanged();
|
||||
|
||||
private:
|
||||
dyncontrol_ptr findControl( const QString &selectedType, const QString &match ) const;
|
||||
|
||||
private slots:
|
||||
void controlsChanged();
|
||||
|
||||
private:
|
||||
QString m_name;
|
||||
PlayableProxyModel *m_model;
|
||||
dynplaylist_ptr m_playlist;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
205
src/libtomahawk/playlist/dynamic/widgets/DynamicQmlWidget.cpp
Normal file
205
src/libtomahawk/playlist/dynamic/widgets/DynamicQmlWidget.cpp
Normal file
@@ -0,0 +1,205 @@
|
||||
#include "DynamicQmlWidget.h"
|
||||
|
||||
#include "dynamic/echonest/EchonestStation.h"
|
||||
#include "playlist/dynamic/DynamicModel.h"
|
||||
#include "playlist/PlayableProxyModel.h"
|
||||
#include "utils/TomahawkUtilsGui.h"
|
||||
#include "dynamic/DynamicModel.h"
|
||||
#include "dynamic/echonest/EchonestControl.h"
|
||||
#include "dynamic/GeneratorInterface.h"
|
||||
#include "PlayableItem.h"
|
||||
#include "Source.h"
|
||||
#include "widgets/DeclarativeCoverArtProvider.h"
|
||||
#include "audio/AudioEngine.h"
|
||||
|
||||
#include <QUrl>
|
||||
#include <qdeclarative.h>
|
||||
#include <QDeclarativeContext>
|
||||
#include <QDeclarativeEngine>
|
||||
#include <QSize>
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
DynamicQmlWidget::DynamicQmlWidget( const dynplaylist_ptr& playlist, QWidget* parent )
|
||||
: QDeclarativeView( parent )
|
||||
, m_playlist( playlist )
|
||||
, m_runningOnDemand( false )
|
||||
, m_activePlaylist( false )
|
||||
{
|
||||
|
||||
|
||||
|
||||
setResizeMode( QDeclarativeView::SizeRootObjectToView );
|
||||
|
||||
m_model = new DynamicModel( this );
|
||||
|
||||
m_proxyModel = new PlayableProxyModel( this );
|
||||
m_proxyModel->setSourcePlayableModel( m_model );
|
||||
m_proxyModel->setShowOfflineResults( false );
|
||||
|
||||
// QML image providers will be deleted by the view
|
||||
engine()->addImageProvider( "albumart", new DeclarativeCoverArtProvider( m_proxyModel ) );
|
||||
|
||||
m_model->loadPlaylist( m_playlist );
|
||||
|
||||
// Initially seed the playlist
|
||||
m_playlist->generator()->generate( 20 );
|
||||
|
||||
qDebug() << "###got" << m_playlist->generator()->controls().size() << "controls";
|
||||
|
||||
qmlRegisterUncreatableType<EchonestStation>("tomahawk", 1, 0, "EchonestStation", "bla");
|
||||
|
||||
// TODO: In case QML is used in more places, this should probably be moved to some generic place
|
||||
qmlRegisterType<PlayableItem>("tomahawk", 1, 0, "PlayableItem");
|
||||
qmlRegisterUncreatableType<GeneratorInterface>("tomahawk", 1, 0, "Generator", "you cannot create it on your own - should be set in context");
|
||||
qmlRegisterUncreatableType<PlayableItem>("tomahawk", 1, 0, "PlayableItem", "you cannot create it on your own - they will appear in the model");
|
||||
|
||||
|
||||
EchonestStation *station = new EchonestStation( m_proxyModel, m_playlist, this);
|
||||
rootContext()->setContextProperty( "echonestStation", station);
|
||||
rootContext()->setContextProperty( "dynamicModel", m_proxyModel );
|
||||
rootContext()->setContextProperty( "generator", m_playlist->generator().data() );
|
||||
|
||||
setSource( QUrl( "qrc" RESPATH "qml/StationScene.qml" ) );
|
||||
|
||||
connect( m_model, SIGNAL( currentItemChanged( QPersistentModelIndex ) ), SLOT( currentItemChanged( QPersistentModelIndex ) ) );
|
||||
connect( m_playlist->generator().data(), SIGNAL( generated( QList<Tomahawk::query_ptr> ) ), this, SLOT( tracksGenerated( QList<Tomahawk::query_ptr> ) ) );
|
||||
connect( m_playlist->generator().data(), SIGNAL( nextTrackGenerated( Tomahawk::query_ptr ) ), this, SLOT( nextTrackGenerated( Tomahawk::query_ptr ) ) );
|
||||
connect( m_playlist.data(), SIGNAL( dynamicRevisionLoaded( Tomahawk::DynamicPlaylistRevision ) ), this, SLOT( onRevisionLoaded( Tomahawk::DynamicPlaylistRevision ) ) );
|
||||
connect( m_playlist->generator().data(), SIGNAL( error( QString, QString )), SLOT( error(QString,QString) ) );
|
||||
|
||||
connect( AudioEngine::instance(), SIGNAL( started( Tomahawk::result_ptr ) ), this, SLOT( trackStarted() ) );
|
||||
connect( AudioEngine::instance(), SIGNAL( playlistChanged( Tomahawk::playlistinterface_ptr ) ), this, SLOT( playlistChanged( Tomahawk::playlistinterface_ptr ) ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
DynamicQmlWidget::~DynamicQmlWidget()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Tomahawk::playlistinterface_ptr
|
||||
DynamicQmlWidget::playlistInterface() const
|
||||
{
|
||||
return m_proxyModel->playlistInterface();
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
DynamicQmlWidget::title() const
|
||||
{
|
||||
return m_model->title();
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
DynamicQmlWidget::description() const
|
||||
{
|
||||
return m_model->description();
|
||||
}
|
||||
|
||||
|
||||
QPixmap
|
||||
DynamicQmlWidget::pixmap() const
|
||||
{
|
||||
return QPixmap( RESPATH "images/station.png" );
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DynamicQmlWidget::jumpToCurrentTrack()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void DynamicQmlWidget::currentItemChanged( const QPersistentModelIndex ¤tIndex )
|
||||
{
|
||||
rootContext()->setContextProperty( "currentlyPlayedIndex", m_proxyModel->mapFromSource( currentIndex ).row() );
|
||||
}
|
||||
|
||||
void
|
||||
DynamicQmlWidget::tracksGenerated( const QList< query_ptr >& queries )
|
||||
{
|
||||
qDebug() << queries.count() << "tracks generated";
|
||||
m_model->tracksGenerated( queries, queries.count() );
|
||||
m_playlist->resolve();
|
||||
}
|
||||
|
||||
void DynamicQmlWidget::nextTrackGenerated(const query_ptr &track)
|
||||
{
|
||||
m_model->tracksGenerated( QList<query_ptr>() << track );
|
||||
m_playlist->resolve();
|
||||
|
||||
connect( track.data(), SIGNAL( resolvingFinished( bool )), SLOT( resolvingFinished( bool ) ) );
|
||||
|
||||
}
|
||||
|
||||
void DynamicQmlWidget::error(const QString &title, const QString &body)
|
||||
{
|
||||
qDebug() << "got a generator error:" << title << body;
|
||||
|
||||
// m_playlist->generator()->fetchNext();
|
||||
|
||||
}
|
||||
|
||||
void DynamicQmlWidget::onRevisionLoaded(DynamicPlaylistRevision)
|
||||
{
|
||||
m_playlist->resolve();
|
||||
}
|
||||
|
||||
void DynamicQmlWidget::resolvingFinished(bool hasResults)
|
||||
{
|
||||
Q_UNUSED(hasResults)
|
||||
qDebug() << "next track generated" << m_proxyModel->rowCount() << m_proxyModel->currentIndex().row();
|
||||
if( m_proxyModel->rowCount() <= m_proxyModel->currentIndex().row() + 8 ) {
|
||||
qDebug() << "fetching next one";
|
||||
m_playlist->generator()->fetchNext();
|
||||
}
|
||||
}
|
||||
|
||||
void DynamicQmlWidget::trackStarted()
|
||||
{
|
||||
if ( m_activePlaylist && !m_playlist.isNull() &&
|
||||
m_playlist->mode() == OnDemand && !m_runningOnDemand )
|
||||
{
|
||||
|
||||
startStation();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DynamicQmlWidget::playlistChanged( Tomahawk::playlistinterface_ptr pl )
|
||||
{
|
||||
if ( pl == m_proxyModel->playlistInterface() ) // same playlist
|
||||
m_activePlaylist = true;
|
||||
else
|
||||
{
|
||||
m_activePlaylist = false;
|
||||
|
||||
// user started playing something somewhere else, so give it a rest
|
||||
if ( m_runningOnDemand )
|
||||
{
|
||||
stopStation( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DynamicQmlWidget::stopStation( bool stopPlaying )
|
||||
{
|
||||
m_model->stopOnDemand( stopPlaying );
|
||||
m_runningOnDemand = false;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
DynamicQmlWidget::startStation()
|
||||
{
|
||||
m_runningOnDemand = true;
|
||||
m_model->startOnDemand();
|
||||
}
|
||||
|
||||
|
||||
}
|
111
src/libtomahawk/playlist/dynamic/widgets/DynamicQmlWidget.h
Normal file
111
src/libtomahawk/playlist/dynamic/widgets/DynamicQmlWidget.h
Normal file
@@ -0,0 +1,111 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2012, Michael Zanetti <mzanetti@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 DYNAMIC_QML_WIDGET_H
|
||||
#define DYNAMIC_QML_WIDGET_H
|
||||
|
||||
#include "ViewPage.h"
|
||||
#include "Typedefs.h"
|
||||
|
||||
#include <QDeclarativeView>
|
||||
#include <QDeclarativeImageProvider>
|
||||
|
||||
class PlayableProxyModel;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class DynamicModel;
|
||||
|
||||
class DynamicQmlWidget : public QDeclarativeView, public Tomahawk::ViewPage
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DynamicQmlWidget( const dynplaylist_ptr& playlist, QWidget* parent = 0 );
|
||||
virtual ~DynamicQmlWidget();
|
||||
|
||||
virtual QWidget* widget() { return this; }
|
||||
virtual Tomahawk::playlistinterface_ptr playlistInterface() const;
|
||||
|
||||
virtual QString title() const;
|
||||
virtual QString description() const;
|
||||
virtual QPixmap pixmap() const;
|
||||
|
||||
virtual bool showInfoBar() const { return false; }
|
||||
virtual bool showModes() const { return false; }
|
||||
virtual bool showFilter() const { return false; }
|
||||
|
||||
virtual bool jumpToCurrentTrack();
|
||||
|
||||
private slots:
|
||||
void currentItemChanged( const QPersistentModelIndex ¤tIndex );
|
||||
void tracksGenerated( const QList< Tomahawk::query_ptr>& queries );
|
||||
void nextTrackGenerated( const Tomahawk::query_ptr& track );
|
||||
void error( const QString& title, const QString& body);
|
||||
|
||||
void onRevisionLoaded( Tomahawk::DynamicPlaylistRevision );
|
||||
void playlistChanged( Tomahawk::playlistinterface_ptr pl );
|
||||
|
||||
void resolvingFinished( bool hasResults );
|
||||
|
||||
void trackStarted();
|
||||
void startStation();
|
||||
void stopStation( bool stopPlaying );
|
||||
private:
|
||||
DynamicModel* m_model;
|
||||
PlayableProxyModel* m_proxyModel;
|
||||
|
||||
dynplaylist_ptr m_playlist;
|
||||
|
||||
bool m_runningOnDemand;
|
||||
bool m_activePlaylist;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#include "dynamic/GeneratorInterface.h"
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class ControlModel: public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ControlModel(geninterface_ptr generator, QObject *parent = 0): QAbstractListModel(parent), m_generator(generator) {
|
||||
connect(generator.data(), SIGNAL(controlAdded(const dyncontrol_ptr&)), SLOT(controlAdded()));
|
||||
}
|
||||
|
||||
int rowCount(const QModelIndex &parent) const { return m_generator->controls().size(); }
|
||||
QVariant data(const QModelIndex &index, int role) const {
|
||||
return "blabla";
|
||||
}
|
||||
Q_INVOKABLE Tomahawk::DynamicControl *controlAt( int index ) { qDebug() << "returning" << m_generator->controls().at(index).data(); return m_generator->controls().at(index).data(); }
|
||||
|
||||
private slots:
|
||||
void controlAdded() {
|
||||
qDebug() << "control added";
|
||||
beginInsertRows(QModelIndex(), m_generator->controls().size() - 1, m_generator->controls().size() - 1);
|
||||
endInsertRows();
|
||||
}
|
||||
private:
|
||||
geninterface_ptr m_generator;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif // DYNAMIC_QML_WIDGET_H
|
69
src/libtomahawk/widgets/DeclarativeCoverArtProvider.cpp
Normal file
69
src/libtomahawk/widgets/DeclarativeCoverArtProvider.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include "DeclarativeCoverArtProvider.h"
|
||||
#include "PlayableItem.h"
|
||||
#include "playlist/PlayableProxyModel.h"
|
||||
#include "Query.h"
|
||||
#include "Album.h"
|
||||
#include "Artist.h"
|
||||
|
||||
#include <QDeclarativeImageProvider>
|
||||
#include <QModelIndex>
|
||||
#include <QDebug>
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
DeclarativeCoverArtProvider::DeclarativeCoverArtProvider( PlayableProxyModel *model )
|
||||
: QDeclarativeImageProvider( QDeclarativeImageProvider::Pixmap )
|
||||
, m_model( model )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
DeclarativeCoverArtProvider::~DeclarativeCoverArtProvider()
|
||||
{
|
||||
}
|
||||
|
||||
QPixmap DeclarativeCoverArtProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
|
||||
{
|
||||
// We always can generate it in the requested size
|
||||
int width = requestedSize.width() > 0 ? requestedSize.width() : 230;
|
||||
int height = requestedSize.height() > 0 ? requestedSize.height() : 230;
|
||||
|
||||
if( size )
|
||||
*size = QSize( width, height );
|
||||
|
||||
// PlayableItem *item = m_model->itemFromIndex( id.toInt() );
|
||||
// if( item ) {
|
||||
// qDebug() << "item:" << item;
|
||||
// qDebug() << "item2:" << item->artistName() << item->name();
|
||||
// if ( !item->query().isNull() ) {
|
||||
// return item->query()->displayQuery()->cover( *size );
|
||||
// }
|
||||
// }
|
||||
|
||||
tDebug() << "Getting by id:" << id;
|
||||
album_ptr album = Album::getByCoverId( id );
|
||||
if ( !album.isNull() )
|
||||
{
|
||||
tDebug() << "Returning album cover:" << album->cover( requestedSize ).isNull();
|
||||
return album->cover( requestedSize );
|
||||
}
|
||||
artist_ptr artist = Artist::getByCoverId( id );
|
||||
if ( !artist.isNull() )
|
||||
{
|
||||
tDebug() << "Returning artist cover:" << artist->cover( requestedSize ).isNull();
|
||||
return artist->cover( requestedSize );
|
||||
}
|
||||
/* query_ptr query = Query::getByCoverId( id );
|
||||
if ( !query.isNull() ) {
|
||||
return query->cover( requestedSize );
|
||||
}*/
|
||||
|
||||
// TODO: create default cover art image
|
||||
QPixmap pixmap( *size );
|
||||
pixmap.fill();
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
}
|
26
src/libtomahawk/widgets/DeclarativeCoverArtProvider.h
Normal file
26
src/libtomahawk/widgets/DeclarativeCoverArtProvider.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef DECLARATIVECOVERARTPROVIDER_H
|
||||
#define DECLARATIVECOVERARTPROVIDER_H
|
||||
|
||||
|
||||
#include "playlist/PlayableProxyModel.h"
|
||||
|
||||
#include <QDeclarativeImageProvider>
|
||||
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class DeclarativeCoverArtProvider: public QDeclarativeImageProvider
|
||||
{
|
||||
public:
|
||||
DeclarativeCoverArtProvider( PlayableProxyModel *model );
|
||||
~DeclarativeCoverArtProvider();
|
||||
|
||||
QPixmap requestPixmap( const QString &id, QSize *size, const QSize &requestedSize );
|
||||
|
||||
private:
|
||||
PlayableProxyModel *m_model;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // DECLARATIVECOVERARTPROVIDER_H
|
@@ -0,0 +1,18 @@
|
||||
#include "AlbumArtImageProvider.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
QPixmap AlbumArtImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
|
||||
{
|
||||
qDebug() << "*!*!*!*!*!*!*!*!*!* image requested";
|
||||
int width = 100;
|
||||
int height = 50;
|
||||
|
||||
if (size)
|
||||
*size = QSize(width, height);
|
||||
QPixmap pixmap(requestedSize.width() > 0 ? requestedSize.width() : width,
|
||||
requestedSize.height() > 0 ? requestedSize.height() : height);
|
||||
pixmap.fill(QColor(id).rgba());
|
||||
|
||||
return pixmap;
|
||||
}
|
12
src/libtomahawk/widgets/infowidgets/AlbumArtImageProvider.h
Normal file
12
src/libtomahawk/widgets/infowidgets/AlbumArtImageProvider.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#include <QDeclarativeImageProvider>
|
||||
|
||||
class AlbumArtImageProvider : public QDeclarativeImageProvider
|
||||
{
|
||||
public:
|
||||
AlbumArtImageProvider()
|
||||
: QDeclarativeImageProvider(QDeclarativeImageProvider::Pixmap)
|
||||
{
|
||||
}
|
||||
|
||||
QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize);
|
||||
};
|
@@ -23,6 +23,9 @@
|
||||
|
||||
#include <QScrollArea>
|
||||
#include <QScrollBar>
|
||||
#include <QDeclarativeContext>
|
||||
#include <QDeclarativeEngine>
|
||||
#include "AlbumArtImageProvider.h"
|
||||
|
||||
#include "audio/AudioEngine.h"
|
||||
#include "playlist/GridItemDelegate.h"
|
||||
@@ -44,7 +47,7 @@ using namespace Tomahawk;
|
||||
|
||||
|
||||
ArtistInfoWidget::ArtistInfoWidget( const Tomahawk::artist_ptr& artist, QWidget* parent )
|
||||
: QWidget( parent )
|
||||
: QDeclarativeView( parent )
|
||||
, ui( new Ui::ArtistInfoWidget )
|
||||
, m_artist( artist )
|
||||
{
|
||||
@@ -159,7 +162,7 @@ ArtistInfoWidget::ArtistInfoWidget( const Tomahawk::artist_ptr& artist, QWidget*
|
||||
|
||||
ArtistInfoWidget::~ArtistInfoWidget()
|
||||
{
|
||||
delete ui;
|
||||
// delete ui;
|
||||
}
|
||||
|
||||
|
||||
@@ -239,9 +242,9 @@ ArtistInfoWidget::load( const artist_ptr& artist )
|
||||
connect( m_artist.data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr>, Tomahawk::ModelMode, Tomahawk::collection_ptr ) ),
|
||||
SLOT( onTracksFound( QList<Tomahawk::query_ptr>, Tomahawk::ModelMode ) ) );
|
||||
|
||||
ui->artistLabel->setText( artist->name() );
|
||||
// ui->artistLabel->setText( artist->name() );
|
||||
|
||||
m_topHitsModel->startLoading();
|
||||
// m_topHitsModel->startLoading();
|
||||
|
||||
if ( !m_artist->albums( Mixed ).isEmpty() )
|
||||
onAlbumsFound( m_artist->albums( Mixed ), Mixed );
|
||||
@@ -273,38 +276,38 @@ ArtistInfoWidget::onTracksFound( const QList<Tomahawk::query_ptr>& queries, Mode
|
||||
{
|
||||
Q_UNUSED( mode );
|
||||
|
||||
m_topHitsModel->finishLoading();
|
||||
m_topHitsModel->appendQueries( queries );
|
||||
// m_topHitsModel->finishLoading();
|
||||
// m_topHitsModel->appendQueries( queries );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ArtistInfoWidget::onSimilarArtistsLoaded()
|
||||
{
|
||||
m_relatedModel->appendArtists( m_artist->similarArtists() );
|
||||
// m_relatedModel->appendArtists( m_artist->similarArtists() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ArtistInfoWidget::onBiographyLoaded()
|
||||
{
|
||||
m_longDescription = m_artist->biography();
|
||||
emit longDescriptionChanged( m_longDescription );
|
||||
// m_longDescription = m_artist->biography();
|
||||
// emit longDescriptionChanged( m_longDescription );
|
||||
|
||||
ui->biography->setHtml( m_artist->biography() );
|
||||
// ui->biography->setHtml( m_artist->biography() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ArtistInfoWidget::onArtistImageUpdated()
|
||||
{
|
||||
if ( m_artist->cover( QSize( 0, 0 ) ).isNull() )
|
||||
return;
|
||||
// if ( m_artist->cover( QSize( 0, 0 ) ).isNull() )
|
||||
// return;
|
||||
|
||||
m_pixmap = m_artist->cover( QSize( 0, 0 ) );
|
||||
emit pixmapChanged( m_pixmap );
|
||||
// m_pixmap = m_artist->cover( QSize( 0, 0 ) );
|
||||
// emit pixmapChanged( m_pixmap );
|
||||
|
||||
ui->cover->setPixmap( m_artist->cover( ui->cover->sizeHint() ) );
|
||||
// ui->cover->setPixmap( m_artist->cover( ui->cover->sizeHint() ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -315,7 +318,7 @@ ArtistInfoWidget::changeEvent( QEvent* e )
|
||||
switch ( e->type() )
|
||||
{
|
||||
case QEvent::LanguageChange:
|
||||
ui->retranslateUi( this );
|
||||
// ui->retranslateUi( this );
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@@ -31,11 +31,13 @@
|
||||
#define ARTISTINFOWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QDeclarativeView>
|
||||
|
||||
#include "Typedefs.h"
|
||||
#include "PlaylistInterface.h"
|
||||
#include "ViewPage.h"
|
||||
|
||||
|
||||
#include "DllMacro.h"
|
||||
|
||||
class PlayableModel;
|
||||
@@ -48,7 +50,7 @@ namespace Ui
|
||||
|
||||
class MetaArtistInfoInterface;
|
||||
|
||||
class DLLEXPORT ArtistInfoWidget : public QWidget, public Tomahawk::ViewPage
|
||||
class DLLEXPORT ArtistInfoWidget : public QDeclarativeView, public Tomahawk::ViewPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
Reference in New Issue
Block a user