mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-13 17:43:59 +02:00
restructured QML
This commit is contained in:
@@ -3,6 +3,11 @@ import QtQuick 1.1
|
|||||||
Item {
|
Item {
|
||||||
id: root
|
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
|
||||||
|
|
||||||
// Labels & Cover
|
// Labels & Cover
|
||||||
property string artistName
|
property string artistName
|
||||||
property string trackName
|
property string trackName
|
||||||
@@ -22,13 +27,15 @@ Item {
|
|||||||
|
|
||||||
// will be emitted when the on hower play button is clicked
|
// will be emitted when the on hower play button is clicked
|
||||||
signal playClicked()
|
signal playClicked()
|
||||||
|
// will be emitted when the cover is clicked
|
||||||
|
signal clicked()
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: mouseArea
|
id: mouseArea
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
|
|
||||||
onClicked: print("cover clicked")
|
onClicked: root.clicked();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,10 +60,10 @@ Item {
|
|||||||
height: 32
|
height: 32
|
||||||
anchors.margins: 5
|
anchors.margins: 5
|
||||||
color: "black"
|
color: "black"
|
||||||
opacity: 0.5
|
opacity: showLabels ? 0.5 : 0
|
||||||
radius: 3
|
radius: 3
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
color: "white"
|
color: "white"
|
||||||
font.bold: true
|
font.bold: true
|
||||||
@@ -65,6 +72,7 @@ Item {
|
|||||||
anchors.margins: 2
|
anchors.margins: 2
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
|
opacity: showLabels ? 1 : 0
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
color: "white"
|
color: "white"
|
||||||
@@ -73,6 +81,7 @@ Item {
|
|||||||
anchors.margins: 2
|
anchors.margins: 2
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
elide: Text.ElideRight
|
elide: Text.ElideRight
|
||||||
|
opacity: showLabels ? 1 : 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,11 +139,9 @@ Item {
|
|||||||
|
|
||||||
Image {
|
Image {
|
||||||
id: playButton
|
id: playButton
|
||||||
|
visible: showPlayButton ? mouseArea.containsMouse : false
|
||||||
source: "../images/play-rest.png"
|
source: "../images/play-rest.png"
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
// width:
|
|
||||||
// height: 32
|
|
||||||
visible: mouseArea.containsMouse
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: root.playClicked();
|
onClicked: root.playClicked();
|
||||||
|
53
data/qml/StationConfig.qml
Normal file
53
data/qml/StationConfig.qml
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import QtQuick 1.1
|
||||||
|
import tomahawk 1.0
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: fineTuneView
|
||||||
|
|
||||||
|
property color textColor: "white"
|
||||||
|
|
||||||
|
signal done();
|
||||||
|
|
||||||
|
Grid {
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.margins: 50
|
||||||
|
Text {
|
||||||
|
color: fineTuneView.textColor
|
||||||
|
text: "Name"
|
||||||
|
|
||||||
|
}
|
||||||
|
TextInput {
|
||||||
|
id: stationName
|
||||||
|
width: 200
|
||||||
|
text: echonestStation.name
|
||||||
|
//onTextChanged: echonestStation.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: configureButton
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.bottomMargin: 20
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
color: "gray"
|
||||||
|
height: 20
|
||||||
|
width: 150
|
||||||
|
radius: 10
|
||||||
|
//opacity: 0
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "configure"
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
fineTuneView.done();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -7,265 +7,56 @@ Rectangle {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
state: echonestStation.configured ? "list" : "configure"
|
state: echonestStation.configured ? "list" : "configure"
|
||||||
|
|
||||||
property int coverSize: 230
|
|
||||||
|
|
||||||
onWidthChanged: {
|
VisualItemModel {
|
||||||
print("width changed to", width)
|
id: stationVisualModel
|
||||||
coverView.model = dynamicModel
|
|
||||||
|
TagCloud {
|
||||||
|
height: scene.height
|
||||||
|
width: scene.width
|
||||||
|
model: generator.styles()
|
||||||
|
opacity: echonestStation.configured ? 0 : 1
|
||||||
|
|
||||||
|
onTagClicked: {
|
||||||
|
echonestStation.setMainControl( item );
|
||||||
|
stationListView.incrementCurrentIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
states: [
|
Behavior on opacity {
|
||||||
State {
|
NumberAnimation { duration: 300 }
|
||||||
name: "configure"
|
|
||||||
PropertyChanges { target: styleCloud; anchors.leftMargin: 0 }
|
|
||||||
PropertyChanges { target: configureButton; opacity: 1 }
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
name: "finetune"
|
|
||||||
PropertyChanges { target: fineTuneView; anchors.rightMargin: 0 }
|
|
||||||
PropertyChanges { target: configureButton; opacity: 1 }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
transitions: [
|
|
||||||
Transition {
|
|
||||||
NumberAnimation {
|
|
||||||
target: styleCloud
|
|
||||||
properties: "anchors.leftMargin"; easing.type: Easing.InOutQuad; duration: 500
|
|
||||||
}
|
|
||||||
NumberAnimation {
|
|
||||||
target: fineTuneView
|
|
||||||
properties: "anchors.rightMargin"; easing.type: Easing.InOutQuad; duration: 500
|
|
||||||
}
|
|
||||||
NumberAnimation {
|
|
||||||
target: configureButton
|
|
||||||
properties: "opacity"; easing.type: Easing.InOutQuad; duration: 500
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
|
||||||
|
|
||||||
|
StationView {
|
||||||
PathView {
|
coverSize: 250
|
||||||
id: coverView
|
height: scene.height
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
print("pathview created:", scene.width)
|
|
||||||
}
|
|
||||||
|
|
||||||
preferredHighlightBegin: 0.1 // scene.width / 11000
|
|
||||||
preferredHighlightEnd: preferredHighlightBegin
|
|
||||||
pathItemCount: 5
|
|
||||||
//highlightMoveDuration: 500
|
|
||||||
|
|
||||||
model: dynamicModel
|
|
||||||
currentIndex: currentlyPlayedIndex
|
|
||||||
|
|
||||||
property int pathStartX: width - scene.coverSize
|
|
||||||
property int pathStartY: height / 2
|
|
||||||
|
|
||||||
delegate: CoverImage {
|
|
||||||
height: scene.coverSize
|
|
||||||
width: scene.coverSize
|
|
||||||
|
|
||||||
artistName: model.artistName
|
|
||||||
trackName: model.trackName
|
|
||||||
artworkId: index
|
|
||||||
|
|
||||||
scale: PathView.itemScale
|
|
||||||
itemBrightness: PathView.itemBrightness
|
|
||||||
opacity: PathView.itemOpacity
|
|
||||||
z: x
|
|
||||||
|
|
||||||
onPlayClicked: 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 * 9/10 ; y: coverView.pathStartY * 9/10 }
|
|
||||||
PathPercent { value: .1 }
|
|
||||||
PathAttribute { name: "itemOpacity"; value: 1 }
|
|
||||||
PathAttribute { name: "itemBrightness"; value: 1 }
|
|
||||||
PathAttribute { name: "itemScale"; value: 1.0 }
|
|
||||||
PathLine { x: coverView.pathStartX * .5; y: coverView.pathStartY * .7}
|
|
||||||
PathPercent { value: .4 }
|
|
||||||
PathAttribute { name: "itemOpacity"; value: 1 }
|
|
||||||
PathAttribute { name: "itemBrightness"; value: 1 }
|
|
||||||
PathAttribute { name: "itemScale"; value: 0.6 }
|
|
||||||
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.2 }
|
|
||||||
}
|
|
||||||
|
|
||||||
states: [
|
|
||||||
State {
|
|
||||||
name: "normal"
|
|
||||||
PropertyChanges { target: coverView; anchors.rightMargin: 0 }
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
name: "shrinked"
|
|
||||||
PropertyChanges { target: coverView; anchors.rightMargin: scene.width / 3 }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
transitions: [
|
|
||||||
Transition {
|
|
||||||
NumberAnimation {
|
|
||||||
target: coverView
|
|
||||||
properties: "anchors.rightMargin"; easing.type: Easing.InOutQuad; duration: 500
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: styleCloud
|
|
||||||
anchors { left: parent.left; top: parent.top; bottom: parent.bottom }
|
|
||||||
anchors.leftMargin: scene.width
|
|
||||||
width: scene.width
|
width: scene.width
|
||||||
|
|
||||||
function randomNumber(min, max) {
|
onConfigure: stationListView.incrementCurrentIndex();
|
||||||
var date = new Date();
|
|
||||||
return (max - min) * Math.random(date.getSeconds()) + min
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Flow {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
width: parent.width - 100
|
|
||||||
//model: controlModel
|
|
||||||
spacing: 3
|
|
||||||
|
|
||||||
Timer {
|
StationConfig {
|
||||||
interval: 5000
|
height: scene.height
|
||||||
running: false
|
width: scene.width
|
||||||
repeat: true
|
|
||||||
|
|
||||||
onTriggered: {
|
onDone: stationListView.decrementCurrentIndex();
|
||||||
for(var i = 0; i < cloudRepeater.count; i++) {
|
|
||||||
var item = cloudRepeater.itemAt(i);
|
|
||||||
if(item.itemScale > 0.6) {
|
|
||||||
item.itemScale = Math.random();
|
|
||||||
} else {
|
|
||||||
item.itemScale = Math.random();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Repeater {
|
ListView {
|
||||||
id: cloudRepeater
|
id: stationListView
|
||||||
model: generator.styles()
|
|
||||||
|
|
||||||
delegate: Item {
|
|
||||||
id: cloudItem
|
|
||||||
width: delegateText.width * scale
|
|
||||||
height: 28
|
|
||||||
property double itemScale: Math.random()
|
|
||||||
scale: itemScale
|
|
||||||
Text {
|
|
||||||
id: delegateText
|
|
||||||
color: "white"
|
|
||||||
//text: controlModel.controlAt( index ).summary
|
|
||||||
text: modelData
|
|
||||||
font.pixelSize: 28
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.verticalCenterOffset: styleCloud.randomNumber(0, 15)
|
|
||||||
}
|
|
||||||
MouseArea {
|
|
||||||
hoverEnabled: true
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: echonestStation.setMainControl(modelData);
|
contentHeight: scene.height
|
||||||
|
contentWidth: scene.width
|
||||||
|
orientation: ListView.Horizontal
|
||||||
|
model: stationVisualModel
|
||||||
|
interactive: false
|
||||||
|
highlightMoveDuration: 400
|
||||||
|
|
||||||
onMousePositionChanged: {
|
Component.onCompleted: {
|
||||||
cloudItem.scale = 1;
|
if ( echonestStation.configured ) {
|
||||||
delegateTimer.restart();
|
currentIndex = 1
|
||||||
}
|
|
||||||
}
|
|
||||||
Timer {
|
|
||||||
id: delegateTimer
|
|
||||||
interval: 3000
|
|
||||||
repeat: false
|
|
||||||
onTriggered: cloudItem.scale = cloudItem.itemScale
|
|
||||||
}
|
|
||||||
|
|
||||||
Behavior on scale {
|
|
||||||
NumberAnimation { easing: Easing.Linear; duration: 1000 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
id: fineTuneView
|
|
||||||
anchors { right: parent.right; top: parent.top; bottom: parent.bottom }
|
|
||||||
anchors.rightMargin: -width
|
|
||||||
width: scene.width / 2
|
|
||||||
|
|
||||||
property color textColor: "white"
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: 30
|
|
||||||
color: "gray"
|
|
||||||
border.width: 2
|
|
||||||
border.color: "white"
|
|
||||||
radius: 20
|
|
||||||
}
|
|
||||||
|
|
||||||
Grid {
|
|
||||||
Text {
|
|
||||||
color: fineTuneView.textColor
|
|
||||||
text: "Name"
|
|
||||||
|
|
||||||
}
|
|
||||||
TextInput {
|
|
||||||
id: stationName
|
|
||||||
//onTextChanged: echonestStation.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Rectangle {
|
|
||||||
id: configureButton
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.rightMargin: 20
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
color: "gray"
|
|
||||||
height: 50
|
|
||||||
width: 50
|
|
||||||
radius: 25
|
|
||||||
//opacity: 0
|
|
||||||
|
|
||||||
Text {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: "configure"
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
onClicked: {
|
|
||||||
print("changing scene state to", scene.state)
|
|
||||||
if( scene.state === "list" ) {
|
|
||||||
scene.state = "finetune";
|
|
||||||
coverView.state = "shrinked"
|
|
||||||
} else {
|
|
||||||
scene.state = "list";
|
|
||||||
coverView.state = "normal"
|
|
||||||
}
|
|
||||||
print("changed scene state to", scene.state)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
201
data/qml/StationView.qml
Normal file
201
data/qml/StationView.qml
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
import QtQuick 1.1
|
||||||
|
import tomahawk 1.0
|
||||||
|
|
||||||
|
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
|
||||||
|
//artistName: model.artistName
|
||||||
|
//trackName: model.trackName
|
||||||
|
artworkId: index
|
||||||
|
|
||||||
|
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.pixelSize: 16
|
||||||
|
width: parent.width
|
||||||
|
elide: Text.ElideRight
|
||||||
|
text: "Station:"
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
color: "white"
|
||||||
|
font.pixelSize: 24
|
||||||
|
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.pixelSize: 16
|
||||||
|
width: parent.width
|
||||||
|
elide: Text.ElideRight
|
||||||
|
text: "Now Playing:"
|
||||||
|
visible: currentlyPlayedIndex !== -1
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
height: 64
|
||||||
|
width: parent.width
|
||||||
|
radius: 32
|
||||||
|
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 {
|
||||||
|
color: "white"
|
||||||
|
font.pixelSize: 24
|
||||||
|
anchors.left: image.right
|
||||||
|
anchors.margins: 10
|
||||||
|
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.pixelSize: 24
|
||||||
|
width: parent.width
|
||||||
|
elide: Text.ElideRight
|
||||||
|
text: coverView.model.itemFromIndex( currentlyPlayedIndex ).name
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
color: "white"
|
||||||
|
font.pixelSize: 20
|
||||||
|
width: parent.width
|
||||||
|
elide: Text.ElideRight
|
||||||
|
text: coverView.model.itemFromIndex( currentlyPlayedIndex ).artistName
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
color: "white"
|
||||||
|
font.pixelSize: 20
|
||||||
|
width: parent.width
|
||||||
|
elide: Text.ElideRight
|
||||||
|
text: coverView.model.itemFromIndex( currentlyPlayedIndex ).albumName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: configureButton
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.bottomMargin: 20
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
color: "gray"
|
||||||
|
height: 20
|
||||||
|
width: 150
|
||||||
|
radius: 10
|
||||||
|
//opacity: 0
|
||||||
|
|
||||||
|
Text {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: "configure"
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
root.configure();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
81
data/qml/TagCloud.qml
Normal file
81
data/qml/TagCloud.qml
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
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 - 100
|
||||||
|
//model: controlModel
|
||||||
|
spacing: 3
|
||||||
|
|
||||||
|
Timer {
|
||||||
|
interval: 5000
|
||||||
|
running: false
|
||||||
|
repeat: true
|
||||||
|
|
||||||
|
onTriggered: {
|
||||||
|
for(var i = 0; i < cloudRepeater.count; i++) {
|
||||||
|
var item = cloudRepeater.itemAt(i);
|
||||||
|
if(item.itemScale > 0.6) {
|
||||||
|
item.itemScale = Math.random();
|
||||||
|
} else {
|
||||||
|
item.itemScale = Math.random();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
id: cloudRepeater
|
||||||
|
model: tagCloud.model
|
||||||
|
|
||||||
|
delegate: Item {
|
||||||
|
id: cloudItem
|
||||||
|
width: delegateText.width * scale
|
||||||
|
height: 28
|
||||||
|
property double itemScale: Math.random()
|
||||||
|
scale: itemScale
|
||||||
|
Text {
|
||||||
|
id: delegateText
|
||||||
|
color: "white"
|
||||||
|
//text: controlModel.controlAt( index ).summary
|
||||||
|
text: "bla" + modelData
|
||||||
|
font.pixelSize: 28
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
anchors.verticalCenterOffset: tagCloud.randomNumber(0, 15)
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
hoverEnabled: true
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: tagCloud.tagClicked( modelData )
|
||||||
|
|
||||||
|
onMousePositionChanged: {
|
||||||
|
cloudItem.scale = 1;
|
||||||
|
delegateTimer.restart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Timer {
|
||||||
|
id: delegateTimer
|
||||||
|
interval: 3000
|
||||||
|
repeat: false
|
||||||
|
onTriggered: cloudItem.scale = cloudItem.itemScale
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on scale {
|
||||||
|
NumberAnimation { easing: Easing.Linear; duration: 1000 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -149,5 +149,8 @@
|
|||||||
<file>data/qml/ArtistInfoScene.qml</file>
|
<file>data/qml/ArtistInfoScene.qml</file>
|
||||||
<file>data/qml/StationScene.qml</file>
|
<file>data/qml/StationScene.qml</file>
|
||||||
<file>data/qml/CoverImage.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>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@@ -30,7 +30,9 @@
|
|||||||
class DLLEXPORT PlayableItem : public QObject
|
class DLLEXPORT PlayableItem : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
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:
|
public:
|
||||||
~PlayableItem();
|
~PlayableItem();
|
||||||
|
|
||||||
|
@@ -583,3 +583,11 @@ PlayableProxyModel::setFilter( const QString& pattern )
|
|||||||
emit filterChanged( 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 ) );
|
||||||
|
}
|
||||||
|
@@ -67,7 +67,7 @@ public:
|
|||||||
virtual void setMaxVisibleItems( int items );
|
virtual void setMaxVisibleItems( int items );
|
||||||
|
|
||||||
virtual PlayableItem* itemFromIndex( const QModelIndex& index ) const { return sourceModel()->itemFromIndex( index ); }
|
virtual PlayableItem* itemFromIndex( const QModelIndex& index ) const { return sourceModel()->itemFromIndex( index ); }
|
||||||
Q_INVOKABLE virtual PlayableItem* itemFromIndex( int itemIndex ) const { return sourceModel()->itemFromIndex( itemIndex ); }
|
Q_INVOKABLE virtual PlayableItem* itemFromIndex( int itemIndex ) const;
|
||||||
|
|
||||||
virtual Tomahawk::playlistinterface_ptr playlistInterface();
|
virtual Tomahawk::playlistinterface_ptr playlistInterface();
|
||||||
|
|
||||||
|
@@ -7,13 +7,25 @@ namespace Tomahawk
|
|||||||
{
|
{
|
||||||
|
|
||||||
EchonestStation::EchonestStation( PlayableProxyModel *model, geninterface_ptr generator, QObject *parent )
|
EchonestStation::EchonestStation( PlayableProxyModel *model, geninterface_ptr generator, QObject *parent )
|
||||||
: QObject(parent)
|
: QObject( parent )
|
||||||
, m_model(model)
|
, m_name( model->sourceModel()->title() )
|
||||||
, m_generator(generator)
|
, m_model( model )
|
||||||
|
, m_generator( generator )
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString EchonestStation::name() const
|
||||||
|
{
|
||||||
|
return m_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EchonestStation::setName(const QString &name)
|
||||||
|
{
|
||||||
|
m_name = name;
|
||||||
|
emit nameChanged();
|
||||||
|
}
|
||||||
|
|
||||||
Tomahawk::DynamicControl* EchonestStation::mainControl() {
|
Tomahawk::DynamicControl* EchonestStation::mainControl() {
|
||||||
foreach(dyncontrol_ptr control, m_generator->controls()) {
|
foreach(dyncontrol_ptr control, m_generator->controls()) {
|
||||||
qDebug() << "got control" << control->selectedType();
|
qDebug() << "got control" << control->selectedType();
|
||||||
|
@@ -9,12 +9,16 @@ namespace Tomahawk
|
|||||||
class EchonestStation: public QObject
|
class EchonestStation: public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(bool configured READ configured NOTIFY configuredChanged)
|
Q_PROPERTY( QString name READ name WRITE setName NOTIFY nameChanged )
|
||||||
Q_PROPERTY(Tomahawk::DynamicControl* mainControl READ mainControl)
|
Q_PROPERTY( bool configured READ configured NOTIFY configuredChanged )
|
||||||
|
Q_PROPERTY( Tomahawk::DynamicControl* mainControl READ mainControl )
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EchonestStation( PlayableProxyModel *model, geninterface_ptr generator, QObject *parent = 0);
|
EchonestStation( PlayableProxyModel *model, geninterface_ptr generator, QObject *parent = 0);
|
||||||
|
|
||||||
|
QString name() const;
|
||||||
|
void setName( const QString &name );
|
||||||
|
|
||||||
Tomahawk::DynamicControl* mainControl();
|
Tomahawk::DynamicControl* mainControl();
|
||||||
bool configured();
|
bool configured();
|
||||||
|
|
||||||
@@ -24,9 +28,11 @@ public slots:
|
|||||||
void setMainControl(const QString &type);
|
void setMainControl(const QString &type);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
void nameChanged();
|
||||||
void configuredChanged();
|
void configuredChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QString m_name;
|
||||||
PlayableProxyModel *m_model;
|
PlayableProxyModel *m_model;
|
||||||
geninterface_ptr m_generator;
|
geninterface_ptr m_generator;
|
||||||
};
|
};
|
||||||
|
@@ -56,6 +56,7 @@ DynamicQmlWidget::DynamicQmlWidget( const dynplaylist_ptr& playlist, QWidget* pa
|
|||||||
qmlRegisterUncreatableType<DynamicControl>("tomahawk", 1, 0, "DynamicControl", "use generator.createControl() isntead");
|
qmlRegisterUncreatableType<DynamicControl>("tomahawk", 1, 0, "DynamicControl", "use generator.createControl() isntead");
|
||||||
qmlRegisterUncreatableType<EchonestControl>("tomahawk", 1, 0, "EchonestControl", "use Generator.createControl() instead");
|
qmlRegisterUncreatableType<EchonestControl>("tomahawk", 1, 0, "EchonestControl", "use Generator.createControl() instead");
|
||||||
qmlRegisterUncreatableType<GeneratorInterface>("tomahawk", 1, 0, "Generator", "you cannot create it on your own - should be set in context");
|
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");
|
||||||
|
|
||||||
QStringList generatorControls;
|
QStringList generatorControls;
|
||||||
|
|
||||||
@@ -66,7 +67,7 @@ DynamicQmlWidget::DynamicQmlWidget( const dynplaylist_ptr& playlist, QWidget* pa
|
|||||||
|
|
||||||
ControlModel *controls = new ControlModel(m_playlist->generator(), this);
|
ControlModel *controls = new ControlModel(m_playlist->generator(), this);
|
||||||
|
|
||||||
EchonestStation *station = new EchonestStation(m_proxyModel, m_playlist->generator(), this);
|
EchonestStation *station = new EchonestStation( m_proxyModel, m_playlist->generator(), this);
|
||||||
rootContext()->setContextProperty( "echonestStation", station);
|
rootContext()->setContextProperty( "echonestStation", station);
|
||||||
rootContext()->setContextProperty( "controlModel", controls );
|
rootContext()->setContextProperty( "controlModel", controls );
|
||||||
rootContext()->setContextProperty( "dynamicModel", m_proxyModel );
|
rootContext()->setContextProperty( "dynamicModel", m_proxyModel );
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
#include "PlayableItem.h"
|
#include "PlayableItem.h"
|
||||||
#include "playlist/PlayableProxyModel.h"
|
#include "playlist/PlayableProxyModel.h"
|
||||||
#include "Query.h"
|
#include "Query.h"
|
||||||
|
#include "Album.h"
|
||||||
|
|
||||||
#include <QDeclarativeImageProvider>
|
#include <QDeclarativeImageProvider>
|
||||||
#include <QModelIndex>
|
#include <QModelIndex>
|
||||||
@@ -30,13 +31,18 @@ QPixmap DeclarativeCoverArtProvider::requestPixmap(const QString &id, QSize *siz
|
|||||||
if( size )
|
if( size )
|
||||||
*size = QSize( width, height );
|
*size = QSize( width, height );
|
||||||
|
|
||||||
PlayableItem *item = m_model->itemFromIndex( id.toInt() );
|
// PlayableItem *item = m_model->itemFromIndex( id.toInt() );
|
||||||
if( item ) {
|
// if( item ) {
|
||||||
qDebug() << "item:" << item;
|
// qDebug() << "item:" << item;
|
||||||
qDebug() << "item2:" << item->artistName() << item->name();
|
// qDebug() << "item2:" << item->artistName() << item->name();
|
||||||
if ( !item->query().isNull() ) {
|
// if ( !item->query().isNull() ) {
|
||||||
return item->query()->displayQuery()->cover( *size );
|
// return item->query()->displayQuery()->cover( *size );
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
album_ptr album = Album::getByUniqueId(id);
|
||||||
|
if ( !album.isNull() ) {
|
||||||
|
return album->cover(requestedSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: create default cover art image
|
// TODO: create default cover art image
|
||||||
|
Reference in New Issue
Block a user