diff --git a/data/images/inputfield-border.svg b/data/images/inputfield-border.svg
new file mode 100644
index 000000000..3f3ff841c
--- /dev/null
+++ b/data/images/inputfield-border.svg
@@ -0,0 +1,145 @@
+
+
diff --git a/data/images/station-artist.svg b/data/images/station-artist.svg
new file mode 100644
index 000000000..43ed51948
--- /dev/null
+++ b/data/images/station-artist.svg
@@ -0,0 +1,14 @@
+
+
\ No newline at end of file
diff --git a/data/images/station-genre.svg b/data/images/station-genre.svg
new file mode 100644
index 000000000..ba5c1157f
--- /dev/null
+++ b/data/images/station-genre.svg
@@ -0,0 +1,18 @@
+
+
\ No newline at end of file
diff --git a/data/images/station-year.svg b/data/images/station-year.svg
new file mode 100644
index 000000000..a18fb23d3
--- /dev/null
+++ b/data/images/station-year.svg
@@ -0,0 +1,19 @@
+
+
\ No newline at end of file
diff --git a/data/qml/DeclarativeHeader.qml b/data/qml/DeclarativeHeader.qml
new file mode 100644
index 000000000..5863a9d27
--- /dev/null
+++ b/data/qml/DeclarativeHeader.qml
@@ -0,0 +1,21 @@
+import QtQuick 1.1
+import tomahawk 1.0
+import "tomahawkimports"
+
+// Only to be used together with DeclarativeHeader C++ class
+// If you want to use the header in QML, use FlexibleHeader
+
+Item {
+ anchors.fill: parent
+
+ FlexibleHeader {
+ anchors.fill: parent
+ icon: iconSource
+ title: caption
+ subtitle: description
+ buttonModel: buttonList
+
+ onSearchTextChanged: mainView.setFilterText(searchText)
+ onCurrentButtonIndexChanged: mainView.viewModeSelected(currentButtonIndex)
+ }
+}
diff --git a/data/qml/QmlGridView.qml b/data/qml/QmlGridView.qml
new file mode 100644
index 000000000..1d27a2d5e
--- /dev/null
+++ b/data/qml/QmlGridView.qml
@@ -0,0 +1,65 @@
+import QtQuick 1.1
+//import tomahawk 1.0
+import "tomahawkimports"
+
+Rectangle {
+ anchors.fill: parent
+ color: "black"
+
+ Text {
+ id: fontMetrics
+ text: "Here's some sample text"
+ opacity: 0
+ }
+
+ GridView {
+ id: gridView
+ anchors.fill: parent
+ //anchors.rightMargin: scrollBar.width
+
+ cellHeight: cellWidth
+ cellWidth: calculateCoverSize(gridView.width - 3)
+
+ cacheBuffer: cellHeight * 5
+
+ function calculateCoverSize(rectWidth) {
+ var itemWidth = fontMetrics.width;
+ var itemsPerRow = Math.max( 1, Math.floor( rectWidth / itemWidth ) );
+
+ var remSpace = rectWidth - ( itemsPerRow * itemWidth );
+ var extraSpace = remSpace / itemsPerRow;
+ return itemWidth + extraSpace;
+
+ }
+
+ model: mainModel
+
+ delegate: CoverImage {
+ height: gridView.cellHeight// * 0.95
+ width: gridView.cellWidth// * 0.95
+
+ showLabels: true
+ showMirror: false
+ artistName: model.artistName
+ trackName: model.trackName
+ artworkId: model.coverID
+ showPlayButton: true
+ currentlyPlaying: isPlaying
+ smooth: !gridView.moving
+
+ onClicked: {
+ rootView.onItemClicked(index)
+ }
+ onPlayClicked: {
+ rootView.onItemPlayClicked(index)
+ }
+ }
+ }
+
+ ScrollBar {
+ id: scrollBar
+ listView: gridView
+ orientation: Qt.Vertical
+ margin: -width
+ }
+}
diff --git a/data/qml/SpinnerTest.qml b/data/qml/SpinnerTest.qml
new file mode 100644
index 000000000..217b4dbcf
--- /dev/null
+++ b/data/qml/SpinnerTest.qml
@@ -0,0 +1,34 @@
+import QtQuick 1.1
+import "tomahawkimports"
+
+Rectangle {
+width: 1400
+height: 900
+color: "black"
+
+BusyIndicator {
+ anchors.centerIn: parent
+ anchors.horizontalCenterOffset: 200
+ height: 200
+ width: 200
+}
+
+Image {
+ id: svgSpinner
+ source: "../images/loading-animation.svg"
+ smooth: true
+ height: 200
+ width: 200
+ anchors.centerIn: parent
+ anchors.horizontalCenterOffset: -200
+
+ Timer {
+ running: true
+ repeat: true
+ interval: 200
+ onTriggered: svgSpinner.rotation += 360 / 12
+ }
+}
+
+
+}
diff --git a/data/qml/StationView.qml b/data/qml/StationView.qml
new file mode 100644
index 000000000..7bb79e1b4
--- /dev/null
+++ b/data/qml/StationView.qml
@@ -0,0 +1,162 @@
+import QtQuick 1.1
+import tomahawk 1.0
+import "tomahawkimports"
+import "stations"
+Rectangle {
+ id: scene
+ color: "black"
+ anchors.fill: parent
+ state: "list"
+
+ FlexibleHeader {
+ id: header
+ anchors {
+ left: parent.left
+ top: parent.top
+ right: parent.right
+ }
+ height: defaultFontHeight * 4
+ width: parent.width
+ icon: "../images/station.svg"
+ title: mainView.title
+ subtitle: generator.summary
+ showSearchField: false
+ showBackButton: stationListView.currentIndex > 0
+ showNextButton: stationListView.currentIndex == 2
+ nextButtonText: "Save"
+
+ z: 1 //cover albumcovers that may leave their area
+
+ onBackPressed: stationListView.decrementCurrentIndex()
+ onNextPressed: stationListView.incrementCurrentIndex()
+ }
+
+ ListModel {
+ id: modeModel
+ ListElement { label: "By Artist"; image: "../../images/station-artist.svg"; creatorContent: "stations/CreateByArtist.qml" }
+ ListElement { label: "By Genre"; image: "../../images/station-genre.svg"; creatorContent: "stations/CreateByGenre.qml" }
+ ListElement { label: "By Year"; image: "../../images/station-year.svg"; creatorContent: "year" }
+ }
+
+ VisualItemModel {
+ id: stationVisualModel
+
+ StationCreatorPage1 {
+ height: scene.height - header.height
+ width: scene.width
+ model: modeModel
+
+ onItemClicked: {
+ stationCreator.content = modeModel.get(index).creatorContent
+ stationListView.incrementCurrentIndex()
+ }
+ }
+
+ StationCreatorPage2 {
+ id: stationCreator
+ height: stationListView.height
+ width: stationListView.width
+
+ onNext: stationListView.incrementCurrentIndex()
+ }
+
+ Item {
+ id: stationItem
+ height: stationListView.height
+ width: stationListView.width
+
+ CoverFlip {
+ id: coverView
+ anchors.right: parent.right
+ anchors.top: parent.top
+ height: parent.height
+ width: parent.width
+ interactive: false
+
+ backgroundColor: scene.color
+
+ model: dynamicModel
+ currentIndex: currentlyPlayedIndex
+
+ onItemPlayPauseClicked: {
+ mainView.playItem(index)
+ }
+
+ onItemClicked: {
+ mainView.playItem(index)
+ }
+
+ states: [
+ State {
+ name: "empty"; when: mainView.loading
+ PropertyChanges {
+ target: coverView
+ anchors.rightMargin: -coverView.width
+ anchors.topMargin: - coverView.height
+ scale: 0
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ from: "empty"
+ to: "*"
+ NumberAnimation {
+ properties: "anchors.topMargin,anchors.rightMargin,scale"
+ duration: 1000
+ easing.type: Easing.OutQuad
+ }
+ }
+
+ ]
+// Behavior on anchors.topMargin {
+// NumberAnimation { duration: 500 }
+// }
+// Behavior on anchors.rightMargin {
+// NumberAnimation { duration: 500 }
+// }
+// Behavior on scale {
+// NumberAnimation { duration: 500 }
+// }
+
+ }
+ BusyIndicator {
+ id: busyIndicator
+ anchors.centerIn: parent
+ height: defaultFontHeight * 4
+ width: height
+
+ opacity: mainView.loading ? 1 : 0
+ running: mainView.loading
+ }
+
+ }
+
+ }
+
+
+ ListView {
+ id: stationListView
+ anchors {
+ left: parent.left
+ top: header.bottom
+ right: parent.right
+ bottom: parent.bottom
+ }
+
+ contentHeight: height
+ contentWidth: width
+ orientation: ListView.Horizontal
+ model: stationVisualModel
+ interactive: false
+ highlightMoveDuration: 300
+
+ onHeightChanged: {
+ contentHeight = scene.height
+ }
+ onWidthChanged: {
+ contentWidth = scene.width
+ }
+ }
+
+}
diff --git a/data/qml/stations/CreateByArtist.qml b/data/qml/stations/CreateByArtist.qml
new file mode 100644
index 000000000..f3f2f4ceb
--- /dev/null
+++ b/data/qml/stations/CreateByArtist.qml
@@ -0,0 +1,69 @@
+import QtQuick 1.1
+import tomahawk 1.0
+import "../tomahawkimports"
+
+Item {
+ id: root
+ anchors.fill: parent
+
+ signal done()
+
+ function createStation(artist) {
+ mainView.startStationFromArtist(artist)
+ root.done()
+ }
+
+ Column {
+ id: upperColumn
+ anchors.horizontalCenter: parent.horizontalCenter
+ height: parent.height
+ width: defaultFontHeight * 30
+ anchors.bottomMargin: defaultFontHeight
+ spacing: defaultFontHeight
+
+ HeaderLabel {
+ id: headerText
+ text: "Create station by artist..."
+ }
+
+ Row {
+ height: artistInputField.height
+ width: parent.width
+ spacing: defaultFontHeight * 0.5
+
+ InputField {
+ id: artistInputField
+ width: parent.width - createFromInputButton.width - parent.spacing
+
+ onAccepted: createStation(text)
+ }
+
+ PushButton {
+ id: createFromInputButton
+ text: "Go!"
+ enabled: artistInputField.text.length > 2
+ onClicked: createStation(artistInputField.text)
+ }
+ }
+
+ Item {
+ height: parent.height - headerText.height - artistInputField.height - parent.spacing * 3
+ width: parent.width
+ ArtistView {
+ id: artistView
+ height: parent.height
+ width: parent.width
+ model: artistChartsModel
+ clip: true
+ delegateHeight: defaultFontHeight * 6
+
+ onItemClicked: {
+ createStation(artistChartsModel.itemFromIndex(index).artistName);
+ }
+ }
+ ScrollBar {
+ listView: artistView
+ }
+ }
+ }
+}
diff --git a/data/qml/stations/CreateByGenre.qml b/data/qml/stations/CreateByGenre.qml
new file mode 100644
index 000000000..9d2fb1b9b
--- /dev/null
+++ b/data/qml/stations/CreateByGenre.qml
@@ -0,0 +1,88 @@
+import QtQuick 1.1
+import tomahawk 1.0
+import "../tomahawkimports"
+
+Item {
+ id: root
+ anchors.fill: parent
+
+ signal done()
+
+ function createStation(genre) {
+ mainView.startStationFromGenre(genre)
+ root.done()
+ }
+
+ 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" }
+ }
+
+ Column {
+ id: upperColumn
+ anchors.fill: parent
+ anchors.bottomMargin: defaultFontHeight
+ spacing: defaultFontHeight
+
+ HeaderLabel {
+ id: headerText
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: "Create station by genre..."
+ }
+
+ Row {
+ width: defaultFontHeight * 30
+ height: genreInputField.height
+ spacing: defaultFontHeight * 0.5
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ InputField {
+ id: genreInputField
+ width: parent.width - createFromInputButton.width - parent.spacing
+
+ onAccepted: createStation(text);
+ }
+
+ PushButton {
+ id: createFromInputButton
+ text: "Go!"
+ height: genreInputField.height
+ enabled: genreInputField.text.length > 2
+ onClicked: createStation(genreInputField.text)
+ }
+ }
+
+ Item {
+ height: parent.height - headerText.height - genreInputField.height
+ width: parent.width
+ TagCloud {
+ anchors.fill: parent
+ anchors.margins: parent.width / 6
+ model: styleModel
+
+ onTagClicked: {
+ root.createStation(tag);
+ }
+ }
+ }
+ }
+}
diff --git a/data/qml/stations/StationConfig.qml b/data/qml/stations/StationConfig.qml
new file mode 100644
index 000000000..d6f0ce11d
--- /dev/null
+++ b/data/qml/stations/StationConfig.qml
@@ -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
+ }
+
+}
diff --git a/data/qml/stations/StationCreatorPage1.qml b/data/qml/stations/StationCreatorPage1.qml
new file mode 100644
index 000000000..826d69d69
--- /dev/null
+++ b/data/qml/stations/StationCreatorPage1.qml
@@ -0,0 +1,64 @@
+import QtQuick 1.1
+import tomahawk 1.0
+import "../tomahawkimports"
+
+
+Item {
+ id: root
+ property alias model: gridView.model
+ property int spacing: 10
+
+ signal itemClicked(int index)
+
+ GridView {
+ id: gridView
+ anchors.centerIn: parent
+ width: root.width * 9 / 10
+ height: cellHeight
+
+ cellWidth: (width - 1) / 3
+ cellHeight: cellWidth //* 10 / 16
+
+ delegate: Image {
+ width: gridView.cellWidth - root.spacing
+ height: gridView.cellHeight - root.spacing
+ source: image
+ smooth: true
+
+ Rectangle {
+ id: textBackground
+ anchors {
+ left: parent.left
+ bottom: parent.bottom
+ right: parent.right
+ }
+ height: parent.height / 5
+ color: "black"
+ opacity: .5
+
+ }
+ Text {
+ anchors.centerIn: textBackground
+ text: label
+ color: "white"
+ font.bold: true
+ }
+ Rectangle {
+ id: hoverShade
+ anchors.fill: parent
+ color: "white"
+ opacity: mouseArea.containsMouse ? .2 : 0
+
+ Behavior on opacity {
+ NumberAnimation { easing.type: Easing.Linear; duration: 300 }
+ }
+ }
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ onClicked: root.itemClicked(index)
+ }
+ }
+ }
+}
diff --git a/data/qml/stations/StationCreatorPage2.qml b/data/qml/stations/StationCreatorPage2.qml
new file mode 100644
index 000000000..34f4b65cd
--- /dev/null
+++ b/data/qml/stations/StationCreatorPage2.qml
@@ -0,0 +1,25 @@
+import QtQuick 1.1
+import tomahawk 1.0
+import "../tomahawkimports"
+
+Item {
+ id: root
+
+ property int margins: defaultFontHeight * 2
+ property alias content: contentLoader.source
+
+ signal next()
+
+ Loader {
+ id: contentLoader
+ anchors.fill: parent
+ anchors.margins: root.margins
+ }
+
+ Connections {
+ target: contentLoader.item
+
+ onDone: root.next()
+ }
+
+}
diff --git a/data/qml/tomahawkimports/ArtistView.qml b/data/qml/tomahawkimports/ArtistView.qml
new file mode 100644
index 000000000..a35c9b428
--- /dev/null
+++ b/data/qml/tomahawkimports/ArtistView.qml
@@ -0,0 +1,71 @@
+import QtQuick 1.1
+import tomahawk 1.0
+
+ListView {
+ id: root
+
+ property int delegateHeight: defaultFontHeight * 3
+
+ signal itemClicked(int index)
+
+ delegate: Item {
+ width: parent.width
+ height: root.delegateHeight
+
+ Rectangle {
+ id: background
+ anchors.fill: parent
+ radius: defaultFontHeight / 2
+ opacity: 0.5
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#00FFFFFF" }
+ GradientStop { position: 1.0; color: "#AAFFFFFF" }
+ }
+
+ states: [
+ State {
+ name: "hovered"; when: mouseArea.containsMouse
+ PropertyChanges { target: background; opacity: 1 }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ from: "*"; to: "hovered"
+ NumberAnimation { properties: "opacity"; duration: 100 }
+ },
+ Transition {
+ from: "hovered"; to: "*"
+ NumberAnimation { properties: "opacity"; duration: 600 }
+ }
+ ]
+ }
+
+ Row {
+ anchors.fill: parent
+ spacing: defaultFontHeight
+
+ CoverImage {
+ id: coverImage
+ height: parent.height
+ width: height
+ showLabels: false
+ artworkId: model.coverID
+ }
+ Text {
+ text: model.artistName
+ color: "white"
+ anchors.verticalCenter: parent.verticalCenter
+ width: parent.width - coverImage.width - parent.spacing
+ elide: Text.ElideRight
+ }
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ onClicked: root.itemClicked(index)
+ hoverEnabled: true
+ }
+ }
+}
diff --git a/data/qml/tomahawkimports/BusyIndicator.qml b/data/qml/tomahawkimports/BusyIndicator.qml
new file mode 100644
index 000000000..52b6e0fba
--- /dev/null
+++ b/data/qml/tomahawkimports/BusyIndicator.qml
@@ -0,0 +1,52 @@
+import QtQuick 1.1
+
+Item {
+ id: busyIndicator
+ width: 100
+ height: width
+ property int barWidth: width / 10
+ property int barHeight: height / 4
+ property int count: 12
+ property color color: "white"
+ property int currentHighlight: 0
+ property bool running: true
+ property int interval: 200
+
+ Behavior on opacity {
+ NumberAnimation { duration: 500 }
+ }
+
+ Repeater {
+ model: busyIndicator.count
+
+
+ Item {
+ height: parent.height
+ width: busyIndicator.barWidth
+ anchors.centerIn: parent
+ Rectangle {
+ anchors {
+ top: parent.top
+ left: parent.left
+ right: parent.right
+ }
+ height: busyIndicator.barHeight
+ radius: width / 2
+
+ color: busyIndicator.color
+ }
+ rotation: 360 / busyIndicator.count * index
+ opacity: 1 - ((index > busyIndicator.currentHighlight ? busyIndicator.currentHighlight + busyIndicator.count : busyIndicator.currentHighlight) - index) / busyIndicator.count
+ Behavior on opacity {
+ NumberAnimation { duration: busyIndicator.interval }
+ }
+ }
+ }
+
+ Timer {
+ interval: busyIndicator.interval
+ running: busyIndicator.running
+ repeat: true
+ onTriggered: parent.currentHighlight = (parent.currentHighlight + 1) % busyIndicator.count
+ }
+}
diff --git a/data/qml/tomahawkimports/Button.qml b/data/qml/tomahawkimports/Button.qml
new file mode 100644
index 000000000..1c73d7c8c
--- /dev/null
+++ b/data/qml/tomahawkimports/Button.qml
@@ -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();
+ }
+}
diff --git a/data/qml/tomahawkimports/CoverFlip.qml b/data/qml/tomahawkimports/CoverFlip.qml
new file mode 100644
index 000000000..58e85824c
--- /dev/null
+++ b/data/qml/tomahawkimports/CoverFlip.qml
@@ -0,0 +1,137 @@
+import QtQuick 1.1
+import tomahawk 1.0
+
+PathView {
+ id: coverView
+
+ // The start coordinates for the covers
+ // Default is left, centered in height
+ property int pathStartX: 0
+ property int pathStartY: height
+
+ // The size of the covers in the path
+ property int coverSize: height
+
+ property color backgroundColor: "black"
+
+ // emitted when a cover is clicked
+ signal itemClicked(int index)
+
+ // emitted when a cover is clicked
+ signal itemPlayPauseClicked(int index)
+
+ preferredHighlightBegin: 0.2 // scene.width / 11000
+ preferredHighlightEnd: preferredHighlightBegin
+ pathItemCount: 5
+ //highlightMoveDuration: 500
+
+ property bool itemHovered: false
+
+ delegate: Item {
+ id: delegateItem
+ height: coverView.coverSize
+ width: coverView.coverSize
+
+ scale: PathView.itemScale
+ // itemBrightness: PathView.itemBrightness - ((coverView.itemHovered && !coverDelegate.containsMouse) ? .4 : 0)
+ property double itemBrightness: PathView.itemBrightness
+ property double itemOpacity: PathView.itemOpacity
+ property int _origZ
+
+ z: coverView.width - x
+
+ CoverImage {
+ id: coverDelegate
+ height: coverView.coverSize
+ width: coverView.coverSize
+ anchors {
+ top: parent.top
+ right: parent.right
+ }
+
+ backgroundColor: coverView.backgroundColor
+
+ showLabels: true
+ showMirror: true
+ artistName: model.artistName
+ trackName: model.trackName
+ artworkId: model.coverID
+ showPlayButton: true
+ currentlyPlaying: isPlaying
+ smooth: true
+
+ // itemBrightness: PathView.itemBrightness - ((coverView.itemHovered && !coverDelegate.containsMouse) ? .4 : 0)
+ itemBrightness: coverDelegate.containsMouse ? 1 : parent.itemBrightness * (coverView.itemHovered ? .5 : 1)
+ opacity: parent.itemOpacity
+ z: coverView.width - x
+
+ onPlayClicked: {
+ console.log("***************")
+ coverView.itemPlayPauseClicked(index)
+ }
+
+ onClicked: {
+ coverView.itemClicked(index)
+ }
+
+ onContainsMouseChanged: {
+ if (containsMouse) {
+ delegateItem._origZ = delegateItem.z;
+ coverView.itemHovered = true
+ } else {
+ coverView.itemHovered = false
+ }
+ }
+
+
+ }
+ states: [
+ State {
+ name: "hovered"; when: coverDelegate.containsMouse && !coverView.moving && index !== currentIndex
+ PropertyChanges {
+ target: delegateItem
+ width: coverView.coverSize * 2
+ z: delegateItem._origZ
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ NumberAnimation {
+ properties: "width"
+ duration: 300
+ easing.type: Easing.InOutSine
+ }
+
+ }
+ ]
+ }
+
+ path: Path {
+ startX: coverView.pathStartX
+ startY: coverView.pathStartY
+
+ PathAttribute { name: "itemOpacity"; value: 0 }
+ PathAttribute { name: "itemBrightness"; value: 0 }
+ PathAttribute { name: "itemScale"; value: 1.3 }
+
+ PathLine { x: coverView.width / 4; y: coverView.height / 4 * 3}
+ PathPercent { value: 0.1 }
+ PathAttribute { name: "itemOpacity"; value: 0 }
+ PathAttribute { name: "itemBrightness"; value: 1 }
+ PathAttribute { name: "itemScale"; value: 1.0 }
+
+ PathLine { x: coverView.width / 2; y: coverView.height / 2}
+ PathPercent { value: 0.2 }
+ PathAttribute { name: "itemOpacity"; value: 1 }
+ PathAttribute { name: "itemBrightness"; value: 1 }
+ PathAttribute { name: "itemScale"; value: 0.5 }
+
+ PathLine { x: coverView.width; y: 0 }
+ PathPercent { value: 1 }
+ PathAttribute { name: "itemOpacity"; value: 1 }
+ PathAttribute { name: "itemBrightness"; value: 0 }
+ PathAttribute { name: "itemScale"; value: 0.1 }
+ }
+
+}
diff --git a/data/qml/tomahawkimports/CoverImage.qml b/data/qml/tomahawkimports/CoverImage.qml
new file mode 100644
index 000000000..518137aac
--- /dev/null
+++ b/data/qml/tomahawkimports/CoverImage.qml
@@ -0,0 +1,197 @@
+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
+
+ // if this is true, the play button will be swapped by a pause button
+ property bool currentlyPlaying: false
+
+ // Should the mirror be painted?
+ property bool showMirror: false
+
+ // 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
+
+ // set this to true if you want to smoothly scale the cover (be aware of performance impacts)
+ property bool smooth: false
+
+ // will be emitted when the on hower play button is clicked
+ signal playClicked()
+ // will be emitted when the cover is clicked
+ signal clicked()
+ // will be emitted when the cover is hovered by the mouse
+ property alias containsMouse: mouseArea.containsMouse
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+
+ onClicked: {
+ print("Cover clicked");
+ root.clicked();
+ }
+ }
+
+ Rectangle {
+ id: itemShadow
+ color: backgroundColor
+ anchors.fill: parent
+
+ //opacity: 1 - itemBrightness
+
+ Behavior on opacity {
+ NumberAnimation { easing.type: Easing.Linear; duration: 300 }
+ }
+ }
+
+ Component {
+ id: coverImage
+
+ Item {
+ property bool isMirror: false
+
+ Image {
+ anchors.fill: parent
+ source: "image://albumart/" + artworkId + (isMirror ? "-mirror" : "") + (showLabels ? "-labels" : "")
+ smooth: root.smooth
+ opacity: itemBrightness
+ Behavior on opacity {
+ NumberAnimation { duration: 300 }
+ }
+ }
+
+ Rectangle {
+ id: itemGlow
+ anchors.fill: parent
+ anchors.topMargin: isMirror ? parent.height / 2 : 0
+
+ opacity: (mouseArea.containsMouse ? .2 : 0)
+
+ Gradient {
+ id: glowGradient
+ GradientStop { position: 0.0; color: "white" }
+ GradientStop { position: 0.7; color: "white" }
+ GradientStop { position: 0.8; color: "#00000000" }
+ GradientStop { position: 1.0; color: "#00000000" }
+ }
+ Gradient {
+ id: mirrorGlowGradient
+ GradientStop { position: 0.0; color: "#00000000" }
+ GradientStop { position: 0.5; color: "#00000000" }
+ GradientStop { position: 1.0; color: "#44FFFFFF" }
+ }
+
+ states: [
+ State {
+ name: "mirrored"; when: isMirror
+ PropertyChanges {
+ target: itemGlow
+ gradient: mirrorGlowGradient
+ }
+ },
+ State {
+ name: "normal"; when: !isMirror
+ PropertyChanges {
+ target: itemGlow
+ gradient: glowGradient
+ }
+ }
+ ]
+
+ Behavior on opacity {
+ NumberAnimation { easing.type: Easing.Linear; duration: 300 }
+ }
+ }
+
+ Text {
+ id: trackText
+ color: "white"
+ font.bold: true
+ text: trackName
+ anchors { left: parent.left; right: parent.right; bottom: artistText.top }
+ anchors.margins: 2
+ horizontalAlignment: Text.AlignHCenter
+ elide: Text.ElideRight
+ opacity: showLabels ? itemBrightness * (isMirror ? 0.5 : 1): 0
+ font.pixelSize: root.height / 15
+ Behavior on opacity {
+ NumberAnimation { duration: 300 }
+ }
+ }
+ Text {
+ id: artistText
+ color: "white"
+ font.bold: trackText.text.length == 0
+ text: artistName
+ anchors { left: parent.left; right: parent.right; bottom: parent.bottom }
+ anchors.margins: root.height / 20
+ horizontalAlignment: Text.AlignHCenter
+ elide: Text.ElideRight
+ opacity: showLabels ? itemBrightness * (isMirror ? 0.5 : 1) : 0
+ font.pixelSize: trackText.text.length == 0 ? root.height / 10 : root.height / 15
+ Behavior on opacity {
+ NumberAnimation { duration: 300 }
+ }
+ }
+ }
+
+ }
+ Loader {
+ sourceComponent: coverImage
+ anchors.fill: parent
+ }
+
+ Loader {
+ id: mirroredCover
+ sourceComponent: parent.showMirror ? coverImage : undefined
+ anchors.fill: parent
+ onLoaded: {
+ item.isMirror = true
+ }
+ transform : [
+ Rotation {
+ angle: 180; origin.y: root.height
+ axis.x: 1; axis.y: 0; axis.z: 0
+ }
+ ]
+ }
+
+ Image {
+ id: playButton
+ visible: showPlayButton ? (mouseArea.containsMouse || currentlyPlaying) : false
+ source: currentlyPlaying ? "../../images/pause-rest.svg" : "../../images/play-rest.svg"
+ anchors.centerIn: parent
+ height: mirroredCover.height / 5
+ width: height
+ smooth: root.smooth
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ print("Play button clicked");
+ root.playClicked();
+ }
+ }
+ }
+
+}
diff --git a/data/qml/tomahawkimports/DoubleSlider.qml b/data/qml/tomahawkimports/DoubleSlider.qml
new file mode 100644
index 000000000..b1dc522cc
--- /dev/null
+++ b/data/qml/tomahawkimports/DoubleSlider.qml
@@ -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"
+ }
+ }
+}
diff --git a/data/qml/tomahawkimports/FlexibleHeader.qml b/data/qml/tomahawkimports/FlexibleHeader.qml
new file mode 100644
index 000000000..04c5e2566
--- /dev/null
+++ b/data/qml/tomahawkimports/FlexibleHeader.qml
@@ -0,0 +1,199 @@
+import QtQuick 1.1
+import tomahawk 1.0
+
+Rectangle {
+ id: root
+
+ // The icon
+ property alias icon: iconImage.source
+
+ // The title
+ property alias title: titleItem.titleText
+
+ // The subtitle/description
+ property alias subtitle: subtitleText.text
+
+ // The model for the ToggleViewButtons.
+ // "modelData" role name holds the iconSource
+ // => You can use a QStringList or StandardListModel here
+ property alias buttonModel: toggleViewButtons.model
+
+ // The index of the currently selected item
+ property alias currentButtonIndex: toggleViewButtons.currentIndex
+
+ // Should we show the searchfield?
+ property bool showSearchField: true
+
+ // The SearchFields text
+ property alias searchText: searchField.text
+
+ property bool showBackButton: false
+ property bool showNextButton: false
+
+ property string backButtonText: "Back"
+ property string nextButtonText: "Next"
+
+ // Layout spacing
+ property int spacing: defaultFontHeight * 0.5
+
+ signal backPressed()
+ signal nextPressed()
+ signal savePressed()
+
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#615858" }
+ GradientStop { position: 1.0; color: "#231F1F" }
+ }
+
+ Row {
+ id: leftRow
+ anchors {
+ left: parent.left
+ top: parent.top
+ bottom: parent.bottom
+ right: rightRow.left
+ }
+
+ anchors.margins: root.spacing
+ spacing: root.spacing
+
+ Image {
+ id: iconImage
+ height: parent.height * 0.8
+ width: height
+ anchors.verticalCenter: parent.verticalCenter
+ smooth: true
+ }
+
+ Column {
+ height: parent.height
+ width: parent.width - iconImage.width - parent.spacing
+
+ Item {
+ id: titleItem
+ height: captionText1.height
+ width: parent.width
+ clip: true
+
+ property string titleText
+
+ onTitleTextChanged: {
+ if(captionText1.text.length > 0) {
+ captionText2.text = titleText;
+ renewTitleAnimation.start();
+ } else {
+ captionText1.text = titleText;
+ }
+ }
+
+ ParallelAnimation {
+ id: renewTitleAnimation
+ property int duration: 500
+ property variant easingType: Easing.OutBounce;
+
+ NumberAnimation { target: captionText2; property: "anchors.topMargin"; to: 0; duration: renewTitleAnimation.duration; easing.type: renewTitleAnimation.easingType }
+ NumberAnimation { target: captionText1; property: "anchors.topMargin"; to: captionText1.height * 2; duration: renewTitleAnimation.duration; easing.type: renewTitleAnimation.easingType }
+
+ onCompleted: {
+ captionText1.text = titleItem.titleText
+ captionText2.anchors.topMargin = -captionText2.height * 2
+ captionText1.anchors.topMargin = 0
+ }
+ }
+
+ Text {
+ id: captionText1
+ color: "white"
+ anchors.left: parent.left
+ anchors.top: parent.top
+
+ font.pointSize: defaultFontSize * 1.5
+ font.bold: true
+ width: parent.width
+ elide: Text.ElideRight
+ }
+ Text {
+ id: captionText2
+ color: "white"
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.topMargin: -height * 2
+ font.pointSize: defaultFontSize * 1.5
+ font.bold: true
+ width: parent.width
+ elide: Text.ElideRight
+ }
+
+ }
+ Text {
+ id: subtitleText
+ color: "white"
+ font.pointSize: defaultFontSize * 1.2
+ width: parent.width
+ elide: Text.ElideRight
+ }
+ }
+
+ }
+
+ Row {
+ id: rightRow
+ anchors {
+ top: parent.top
+ right: parent.right
+ rightMargin: -backButton.width - root.spacing - nextButton.width
+ bottom: parent.bottom
+ margins: root.spacing
+ }
+ width: childrenRect.width
+ spacing: root.spacing
+ layoutDirection: Qt.RightToLeft
+
+ states: [
+ State {
+ name: "oneVisible"; when: root.showBackButton && !root.showNextButton
+ PropertyChanges {
+ target: rightRow
+ anchors.rightMargin: -nextButton.width
+ }
+ },
+ State {
+ name: "bothVisible"; when: root.showBackButton && root.showNextButton
+ PropertyChanges {
+ target: rightRow
+ anchors.rightMargin: root.spacing
+ }
+ }
+
+ ]
+
+ Behavior on anchors.rightMargin {
+ NumberAnimation { duration: 200 }
+ }
+
+ PushButton {
+ id: nextButton
+ anchors.verticalCenter: parent.verticalCenter
+ text: root.nextButtonText
+ onClicked: root.nextPressed();
+ }
+ PushButton {
+ id: backButton
+ anchors.verticalCenter: parent.verticalCenter
+ text: root.backButtonText
+ onClicked: root.backPressed();
+ }
+ InputField {
+ id: searchField
+ visible: root.showSearchField
+ anchors.verticalCenter: parent.verticalCenter
+ placeholderText: "Search..."
+ showSearchIcon: true
+ }
+ ToggleViewButtons {
+ id: toggleViewButtons
+ anchors.verticalCenter: parent.verticalCenter
+ height: defaultFontHeight * 1.5
+ }
+ }
+}
diff --git a/data/qml/tomahawkimports/HeaderLabel.qml b/data/qml/tomahawkimports/HeaderLabel.qml
new file mode 100644
index 000000000..ebffedbd4
--- /dev/null
+++ b/data/qml/tomahawkimports/HeaderLabel.qml
@@ -0,0 +1,7 @@
+import QtQuick 1.1
+
+Text {
+ color: "white"
+ font.pointSize: defaultFontSize + 5
+ font.bold: true
+}
diff --git a/data/qml/tomahawkimports/InputField.qml b/data/qml/tomahawkimports/InputField.qml
new file mode 100644
index 000000000..9f052124d
--- /dev/null
+++ b/data/qml/tomahawkimports/InputField.qml
@@ -0,0 +1,90 @@
+import QtQuick 1.1
+
+Rectangle {
+ id: root
+ color: "white"
+ border.color: "black"
+ border.width: defaultFontHeight * 0.1
+ radius: defaultFontHeight * 0.25
+
+ height: textInput.height * 1.4
+ width: 300
+
+ property bool showSearchIcon: false
+ property string text: ""
+ property string placeholderText: ""
+
+ property int spacing: defaultFontHeight * 0.2
+ signal accepted( string text )
+
+ Image {
+ id: searchIcon
+ anchors {
+ left: parent.left
+ leftMargin: root.spacing
+ verticalCenter: parent.verticalCenter
+ }
+ height: parent.height * 0.6
+ width: root.showSearchIcon ? height : 1
+ opacity: root.showSearchIcon ? 1 : 0
+ smooth: true
+ source: "../../images/search-icon.svg"
+ }
+
+ Item {
+ id: textItem
+ anchors.left: searchIcon.right
+ anchors.leftMargin: root.spacing
+ anchors.right: clearIcon.right
+ anchors.rightMargin: root.spacing
+ height: textInput.height
+ anchors.verticalCenter: parent.verticalCenter
+
+ TextInput {
+ id: textInput
+ width: parent.width
+ anchors.centerIn: parent
+ text: root.text
+ font.pointSize: defaultFontSize
+
+ onAccepted: root.accepted( text );
+ onTextChanged: root.text = text;
+ }
+ Text {
+ width: parent.width
+ anchors.centerIn: parent
+ text: root.text.length === 0 ? root.placeholderText : ""
+ color: "lightgray"
+ font.pointSize: defaultFontSize
+ }
+ }
+
+ Image {
+ id: clearIcon
+ anchors {
+ right: parent.right
+ rightMargin: root.spacing
+ verticalCenter: parent.verticalCenter
+ }
+ height: parent.height * 0.8
+ width: (root.showSearchIcon && root.text.length > 0) ? height : 1
+ opacity: (root.showSearchIcon && root.text.length > 0) ? 1 : 0
+ smooth: true
+ source: "../../images/search-box-dismiss-x.svg"
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: textInput.text = ""
+ }
+ }
+
+
+ BorderImage {
+ source: "../../images/inputfield-border.svg"
+ anchors.fill: parent
+ anchors.margins: root.radius * 0.1
+ clip: true
+ border.left: defaultFontHeight/4; border.top: defaultFontHeight/4
+ border.right: defaultFontHeight/4; border.bottom: defaultFontHeight/4
+ }
+}
diff --git a/data/qml/tomahawkimports/PushButton.qml b/data/qml/tomahawkimports/PushButton.qml
new file mode 100644
index 000000000..b2c4b2503
--- /dev/null
+++ b/data/qml/tomahawkimports/PushButton.qml
@@ -0,0 +1,34 @@
+import QtQuick 1.1
+//import tomahawk 1.0
+
+Rectangle {
+ id: root
+ height: buttonText.height * 1.4
+ width: buttonText.width + (spacing * 2)
+ radius: defaultFontHeight * 0.25
+ border.width: defaultFontHeight * 0.05
+ border.color: "#a7a7a7"
+
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: mouseArea.pressed ? "#040404" : "#fbfbfb" }
+ GradientStop { position: 1.0; color: mouseArea.pressed ? "#8e8f8e" : "#787878" }
+ }
+
+ property int spacing: defaultFontHeight * 0.5
+ property alias text: buttonText.text
+
+ signal clicked()
+
+ Text {
+ id: buttonText
+ anchors.centerIn: root
+ font.pointSize: defaultFontSize
+ color: mouseArea.pressed ? "white" : "black"
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ onClicked: root.clicked()
+ }
+}
diff --git a/data/qml/tomahawkimports/RoundedButton.qml b/data/qml/tomahawkimports/RoundedButton.qml
new file mode 100644
index 000000000..790afe227
--- /dev/null
+++ b/data/qml/tomahawkimports/RoundedButton.qml
@@ -0,0 +1,43 @@
+import QtQuick 1.1
+import tomahawk 1.0
+
+Rectangle {
+ id: root
+ border.width: 4
+ border.color: enabled ? "white" : "grey"
+ radius: height / 2
+ color: (buttonMouseArea.containsMouse && enabled) ? "#22ffffff" : "black"
+ opacity: hidden ? 0 : 1
+
+ height: defaultFontHeight * 2
+ width: height
+
+ property string text
+ property bool enabled: true
+ property bool hidden: false
+
+ signal clicked()
+
+ Behavior on opacity {
+ NumberAnimation { duration: 200 }
+ }
+
+ Behavior on color {
+ ColorAnimation { duration: 200 }
+ }
+
+ Text {
+ anchors.centerIn: parent
+ text: parent.text
+ color: root.border.color
+ font.pixelSize: parent.height * .75
+ font.bold: true
+ }
+ MouseArea {
+ id: buttonMouseArea
+ anchors.fill: parent
+ hoverEnabled: true
+ enabled: root.enabled
+ onClicked: parent.clicked()
+ }
+}
diff --git a/data/qml/tomahawkimports/ScrollBar.qml b/data/qml/tomahawkimports/ScrollBar.qml
new file mode 100644
index 000000000..351e37803
--- /dev/null
+++ b/data/qml/tomahawkimports/ScrollBar.qml
@@ -0,0 +1,69 @@
+import QtQuick 1.1
+
+Item {
+ id: scrollBar
+ width: defaultFontHeight / 2
+
+ // the ListView where to attach this scrollbar
+ property variant listView
+ // the orientation of the scrollbar
+ property variant orientation : Qt.Vertical
+
+ property int margin: defaultFontHeight * 0.25
+
+ states: [
+ State {
+ name: "hidden"; when: !listView.moving
+ PropertyChanges { target: scrollBar; opacity: 0 }
+ },
+ State {
+ name: "visible"; when: listView.moving
+ PropertyChanges { target: scrollBar; opacity: 1 }
+ }
+ ]
+ transitions: [
+ Transition {
+ from: "hidden"
+ to: "visible"
+ NumberAnimation { properties: "opacity"; duration: 200 }
+ },
+ Transition {
+ from: "visible"
+ to: "hidden"
+ NumberAnimation { properties: "opacity"; duration: 2000 }
+ }
+ ]
+
+ anchors {
+ left: orientation == Qt.Vertical ? listView.right : listView.left
+ leftMargin: orientation == Qt.Vertical ? scrollBar.margin : 0
+ top: orientation == Qt.Vertical ? listView.top : listView.bottom
+ topMargin: orientation == Qt.Vertical ? 0 : scrollBar.margin
+ bottom: orientation == Qt.Vertical ? listView.bottom : undefined
+ right: orientation == Qt.Vertical ? undefined : listView.right
+ }
+
+ // A light, semi-transparent background
+ Rectangle {
+ id: background
+ anchors.fill: parent
+ radius: orientation == Qt.Vertical ? (width/2 - 1) : (height/2 - 1)
+ color: "white"
+ opacity: 0.2
+ clip: true
+ // Size the bar to the required size, depending upon the orientation.
+ Rectangle {
+ property real position: orientation == Qt.Vertical ? (listView.contentY / listView.contentHeight) : (listView.contentX / listView.contentWidth)
+ property real pageSize: orientation == Qt.Vertical ? (listView.height / listView.contentHeight) : (listView.width / listView.contentWidth)
+
+ x: orientation == Qt.Vertical ? 1 : (position * (scrollBar.width-2) + 1)
+ y: orientation == Qt.Vertical ? (position * (scrollBar.height-2) + 1) : 1
+ width: orientation == Qt.Vertical ? (parent.width-2) : (pageSize * (scrollBar.width-2))
+ height: orientation == Qt.Vertical ? (pageSize * (scrollBar.height-2)) : (parent.height-2)
+ radius: orientation == Qt.Vertical ? (width/2 - 1) : (height/2 - 1)
+ color: "white"
+ opacity: 1
+ }
+ }
+
+}
diff --git a/data/qml/tomahawkimports/TagCloud.qml b/data/qml/tomahawkimports/TagCloud.qml
new file mode 100644
index 000000000..ba3de03aa
--- /dev/null
+++ b/data/qml/tomahawkimports/TagCloud.qml
@@ -0,0 +1,80 @@
+import QtQuick 1.1
+import tomahawk 1.0
+
+Item {
+ id: tagCloud
+
+ property variant model: 10
+
+ signal tagClicked( string tag )
+
+ 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: "gray"
+ //text: controlModel.controlAt( index ).summary
+ text: modelData
+ font.pointSize: 16
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.verticalCenterOffset: tagCloud.randomNumber(0, 15)
+
+ states: [
+ State {
+ name: "hovered"; when: cloudItemMouseArea.containsMouse
+ PropertyChanges {
+ target: delegateText
+ color: "white"
+ }
+ }
+ ]
+ transitions: [
+ Transition {
+ from: "*"
+ to: "hovered"
+ ColorAnimation {
+ duration: 200
+ }
+ },
+ Transition {
+ from: "hovered"
+ to: "*"
+ ColorAnimation {
+ duration: 1000
+ }
+ }
+ ]
+
+ }
+ MouseArea {
+ id: cloudItemMouseArea
+ hoverEnabled: true
+ anchors.fill: parent
+ onClicked: tagCloud.tagClicked( modelData )
+ }
+
+ Behavior on scale {
+ NumberAnimation { easing: Easing.Linear; duration: 1000 }
+ }
+ }
+ }
+ }
+}
diff --git a/data/qml/tomahawkimports/ToggleViewButtons.qml b/data/qml/tomahawkimports/ToggleViewButtons.qml
new file mode 100644
index 000000000..066d5f4c9
--- /dev/null
+++ b/data/qml/tomahawkimports/ToggleViewButtons.qml
@@ -0,0 +1,34 @@
+import QtQuick 1.1
+import tomahawk 1.0
+
+Row {
+ id: root
+ width: repeater.width
+
+ property alias model: repeater.model
+ property int currentIndex: 0
+
+ Repeater {
+ id: repeater
+ height: root.height
+ width: count * height
+
+
+ delegate: Image {
+ height: repeater.height
+ width: height
+
+ source: "../../images/view-toggle-" + (index === root.currentIndex ? "active-" : "inactive-" ) + (index === 0 ? "left" : ( index === repeater.count - 1 ? "right" : "centre" )) + ".svg"
+ smooth: true
+ Image {
+ anchors.fill: parent
+ source: "../../images/" + modelData + (index === root.currentIndex ? "-active.svg" : "-inactive.svg")
+ }
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ onClicked: root.currentIndex = index
+ }
+ }
+ }
+}