mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-16 11:04:01 +02:00
more work on the new station view
This commit is contained in:
122
data/qml/CoverImage.qml
Normal file
122
data/qml/CoverImage.qml
Normal file
@@ -0,0 +1,122 @@
|
||||
import QtQuick 1.1
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
// Labels & Cover
|
||||
property string artistName
|
||||
property string trackName
|
||||
property string 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
|
||||
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: print("cover 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: 0.5
|
||||
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
|
||||
}
|
||||
Text {
|
||||
color: "white"
|
||||
text: artistName
|
||||
anchors { left: textBackground.left; right: textBackground.right; bottom: textBackground.bottom }
|
||||
anchors.margins: 2
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loader {
|
||||
sourceComponent: coverImage
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: mirroredCover
|
||||
sourceComponent: coverImage
|
||||
opacity: parent.mirrorOpacity
|
||||
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
|
||||
}
|
||||
|
||||
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 }
|
||||
}
|
||||
}
|
||||
}
|
@@ -5,171 +5,118 @@ Rectangle {
|
||||
id: scene
|
||||
color: "black"
|
||||
anchors.fill: parent
|
||||
state: echonestStation.configured ? "list" : "configure"
|
||||
|
||||
property int coverSize: 230
|
||||
|
||||
Component {
|
||||
id: coverImage
|
||||
states: [
|
||||
State {
|
||||
name: "configure" //; when: scene.state === "configure"
|
||||
PropertyChanges { target: coverView; anchors.leftMargin: scene.width + scene.coverSize + 20 }
|
||||
PropertyChanges { target: styleCloud; anchors.leftMargin: 0 }
|
||||
}
|
||||
]
|
||||
|
||||
Rectangle {
|
||||
height: scene.coverSize
|
||||
width: scene.coverSize
|
||||
color: scene.color
|
||||
border.color: scene.color
|
||||
border.width: 2
|
||||
|
||||
property string artistName
|
||||
property string trackName
|
||||
property string artworkId
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
anchors.margins: parent.border.width
|
||||
source: "image://albumart/" + parent.artworkId
|
||||
transitions: [
|
||||
Transition {
|
||||
NumberAnimation {
|
||||
target: coverView
|
||||
properties: "anchors.leftMargin"; easing.type: Easing.InOutQuad; duration: 500
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: textBackground
|
||||
anchors { left: parent.left; right: parent.right; bottom: parent.bottom }
|
||||
height: 32
|
||||
anchors.margins: 5
|
||||
color: "black"
|
||||
opacity: 0.5
|
||||
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
|
||||
}
|
||||
Text {
|
||||
color: "white"
|
||||
text: artistName
|
||||
anchors { left: textBackground.left; right: textBackground.right; bottom: textBackground.bottom }
|
||||
anchors.margins: 2
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: print("cover clicked")
|
||||
NumberAnimation {
|
||||
target: styleCloud
|
||||
properties: "anchors.leftMargin"; easing.type: Easing.InOutQuad; duration: 500
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
Component {
|
||||
id: mirroredDelegate
|
||||
|
||||
Item {
|
||||
id: mirroredItem
|
||||
height: scene.coverSize
|
||||
width: scene.coverSize
|
||||
|
||||
z: x
|
||||
scale: PathView.itemScale
|
||||
|
||||
property double itemOpacity: PathView.itemOpacity
|
||||
property double shadowOp: PathView.shadowOpacity
|
||||
|
||||
Connections {
|
||||
target: dynamicModel.itemFromIndex( index )
|
||||
onCoverChanged: {
|
||||
// We need to unset and re-set it because QML wouldn't re-query the image if it still has the same url
|
||||
normalCover.item.artworkId = ""
|
||||
mirroredCover.item.artworkId = ""
|
||||
normalCover.item.artworkId = index
|
||||
mirroredCover.item.artworkId = index
|
||||
}
|
||||
}
|
||||
//Component.onCompleted: print("created delegate for", dynamicModel.itemFromIndex( index ) )
|
||||
|
||||
Loader {
|
||||
id: normalCover
|
||||
sourceComponent: coverImage
|
||||
opacity: parent.itemOpacity
|
||||
onLoaded: {
|
||||
item.trackName = trackName
|
||||
item.artistName = artistName
|
||||
item.artworkId = index
|
||||
}
|
||||
}
|
||||
Loader {
|
||||
id: mirroredCover
|
||||
sourceComponent: coverImage
|
||||
opacity: parent.itemOpacity
|
||||
onLoaded: {
|
||||
item.trackName = trackName
|
||||
item.artistName = artistName
|
||||
item.artworkId = index
|
||||
}
|
||||
transform : [
|
||||
Rotation {
|
||||
angle: 180; origin.y: scene.coverSize
|
||||
axis.x: 1; axis.y: 0; axis.z: 0
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: scene.color
|
||||
anchors.fill: parent
|
||||
opacity: mirroredItem.shadowOp
|
||||
}
|
||||
Rectangle {
|
||||
color: scene.color
|
||||
height: scene.coverSize
|
||||
width: scene.coverSize
|
||||
anchors.centerIn: parent
|
||||
anchors.verticalCenterOffset: scene.coverSize
|
||||
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 scene.color
|
||||
GradientStop { position: 0.0; color: Qt.rgba(0, 0, 0, mirroredItem.shadowOp + ( (1 - mirroredItem.shadowOp) * .4)) }
|
||||
GradientStop { position: 0.5; color: scene.color }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PathView {
|
||||
id: view
|
||||
id: coverView
|
||||
anchors.fill: parent
|
||||
highlight: appHighlight
|
||||
|
||||
preferredHighlightBegin: 0.07
|
||||
preferredHighlightEnd: 0.07
|
||||
|
||||
preferredHighlightBegin: 0.07 // scene.width / 11000
|
||||
preferredHighlightEnd: preferredHighlightBegin
|
||||
pathItemCount: 4
|
||||
highlightMoveDuration: 500
|
||||
|
||||
model: dynamicModel
|
||||
currentIndex: currentlyPlayedIndex
|
||||
|
||||
delegate: mirroredDelegate
|
||||
delegate: CoverImage {
|
||||
height: scene.coverSize
|
||||
width: scene.coverSize
|
||||
|
||||
scale: PathView.itemScale
|
||||
|
||||
artistName: model.artistName
|
||||
trackName: model.trackName
|
||||
artworkId: index
|
||||
|
||||
itemBrightness: PathView.itemBrightness
|
||||
z: x
|
||||
}
|
||||
|
||||
path: Path {
|
||||
startX: scene.width / 2 + 20
|
||||
startX: coverView.width / 2 + 20
|
||||
startY: 155
|
||||
|
||||
PathAttribute { name: "itemOpacity"; value: 0 }
|
||||
PathAttribute { name: "shadowOpacity"; value: 0 }
|
||||
PathAttribute { name: "itemBrightness"; value: 0 }
|
||||
PathAttribute { name: "itemScale"; value: 1.5 }
|
||||
PathLine { x: scene.width / 2; y: 150 }
|
||||
PathLine { x: coverView.width / 2; y: 150 }
|
||||
PathAttribute { name: "itemOpacity"; value: 1 }
|
||||
PathAttribute { name: "shadowOpacity"; value: 0 }
|
||||
PathAttribute { name: "itemBrightness"; value: 1 }
|
||||
PathAttribute { name: "itemScale"; value: 1.0 }
|
||||
PathLine { x: scene.width / 2 - 100; y: 180;}
|
||||
PathLine { x: coverView.width / 2 - 100; y: 180;}
|
||||
PathAttribute { name: "itemOpacity"; value: 1 }
|
||||
PathAttribute { name: "shadowOpacity"; value: 0 }
|
||||
PathAttribute { name: "itemBrightness"; value: 1 }
|
||||
PathAttribute { name: "itemScale"; value: 0.6 }
|
||||
PathLine { x: 100; y: 100;}
|
||||
PathAttribute { name: "itemOpacity"; value: 1 }
|
||||
PathAttribute { name: "shadowOpacity"; value: 1 }
|
||||
PathAttribute { name: "itemBrighness"; value: 0.4 }
|
||||
PathAttribute { name: "itemScale"; value: 0.4 }
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: styleCloud
|
||||
anchors { left: parent.left; top: parent.top; bottom: parent.bottom }
|
||||
anchors.leftMargin: scene.width
|
||||
width: scene.width
|
||||
|
||||
function randomNumber(min, max) {
|
||||
var date = new Date();
|
||||
return Math.floor((max - min) * Math.random(date.getSeconds())) + min
|
||||
}
|
||||
|
||||
Flow {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width - 100
|
||||
//model: controlModel
|
||||
spacing: 3
|
||||
Repeater {
|
||||
model: generator.styles()
|
||||
|
||||
delegate: Item {
|
||||
width: delegateText.width
|
||||
height: 28
|
||||
Text {
|
||||
id: delegateText
|
||||
color: "white"
|
||||
//text: controlModel.controlAt( index ).summary
|
||||
text: modelData
|
||||
font.pixelSize: styleCloud.randomNumber(11, 28)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.verticalCenterOffset: styleCloud.randomNumber(0, 15)
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: echonestStation.setMainControl(modelData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user