From fcc6f5c9662323bf47d1fd56d39996cd44cf9f8e Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sun, 19 May 2013 00:39:29 +0200 Subject: [PATCH] some more work on stations merged --- data/qml/SpinnerTest.qml | 1 + data/qml/StationView.qml | 183 ++++++++++-------- data/qml/stations/CreateByArtist.qml | 4 +- data/qml/stations/CreateByGenre.qml | 4 +- data/qml/stations/CreateByYear.qml | 79 ++++++++ data/qml/stations/StationCreatorPage2.qml | 4 +- data/qml/stations/StationItem.qml | 73 +++++++ data/qml/tomahawkimports/CoverFlip.qml | 2 - data/qml/tomahawkimports/CoverImage.qml | 5 +- data/qml/tomahawkimports/DoubleSlider.qml | 130 ++++++++++--- data/qml/tomahawkimports/InputField.qml | 6 + data/qml/tomahawkimports/TagCloud.qml | 6 +- resources.qrc | 2 + .../dynamic/widgets/DynamicQmlWidget.cpp | 17 +- .../dynamic/widgets/DynamicQmlWidget.h | 3 +- 15 files changed, 396 insertions(+), 123 deletions(-) create mode 100644 data/qml/stations/CreateByYear.qml create mode 100644 data/qml/stations/StationItem.qml diff --git a/data/qml/SpinnerTest.qml b/data/qml/SpinnerTest.qml index 217b4dbcf..aa11c4031 100644 --- a/data/qml/SpinnerTest.qml +++ b/data/qml/SpinnerTest.qml @@ -11,6 +11,7 @@ BusyIndicator { anchors.horizontalCenterOffset: 200 height: 200 width: 200 + count: 11 } Image { diff --git a/data/qml/StationView.qml b/data/qml/StationView.qml index 7bb79e1b4..3448c3adb 100644 --- a/data/qml/StationView.qml +++ b/data/qml/StationView.qml @@ -19,23 +19,42 @@ Rectangle { width: parent.width icon: "../images/station.svg" title: mainView.title - subtitle: generator.summary + subtitle: ""//generator.summary showSearchField: false showBackButton: stationListView.currentIndex > 0 - showNextButton: stationListView.currentIndex == 2 + showNextButton: !mainView.configured && stationListView.currentIndex == 2 nextButtonText: "Save" + backButtonText: mainView.configured ? "Configure" : "Back" z: 1 //cover albumcovers that may leave their area - onBackPressed: stationListView.decrementCurrentIndex() - onNextPressed: stationListView.incrementCurrentIndex() + onBackPressed: { + if(mainView.configured) { + return; + } + + inputBubble.opacity = 0 + stationListView.decrementCurrentIndex() + if(stationListView.currentIndex == 1) { + subtitle = modeModel.get(stationCreator.modeIndex).headerSubtitle + "..." + } + if(stationListView.currentIndex == 0) { + subtitle = "" + } + } + // In our case the next button is the save button + onNextPressed: { + inputBubble.opacity = 1 + saveNameInput.forceActiveFocus(); + } } + 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" } + ListElement { label: "By Artist"; image: "../../images/station-artist.svg"; creatorContent: "stations/CreateByArtist.qml"; headerSubtitle: "by" } + ListElement { label: "By Genre"; image: "../../images/station-genre.svg"; creatorContent: "stations/CreateByGenre.qml"; headerSubtitle: "like" } + ListElement { label: "By Year"; image: "../../images/station-year.svg"; creatorContent: "stations/CreateByYear.qml"; headerSubtitle: "from" } } VisualItemModel { @@ -47,8 +66,9 @@ Rectangle { model: modeModel onItemClicked: { - stationCreator.content = modeModel.get(index).creatorContent + stationCreator.modeIndex = index stationListView.incrementCurrentIndex() + header.subtitle = modeModel.get(index).headerSubtitle + "..." } } @@ -57,84 +77,35 @@ Rectangle { height: stationListView.height width: stationListView.width - onNext: stationListView.incrementCurrentIndex() + property int modeIndex + + content: modeModel.get(modeIndex).creatorContent + + onNext: { + stationListView.incrementCurrentIndex() + header.subtitle = modeModel.get(modeIndex).headerSubtitle + " " + text + } } - Item { + StationItem { 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 - } - } - } + VisualItemModel { + id: configuredStationVisualModel + + + StationItem { + id: cfgstationItem + height: stationListView.height + width: stationListView.width + } + } + ListView { id: stationListView anchors { @@ -147,7 +118,7 @@ Rectangle { contentHeight: height contentWidth: width orientation: ListView.Horizontal - model: stationVisualModel + //model: mainView.configured ? configuredStationVisualModel : stationVisualModel interactive: false highlightMoveDuration: 300 @@ -157,6 +128,62 @@ Rectangle { onWidthChanged: { contentWidth = scene.width } + + Component.onCompleted: { + model = mainView.configured ? configuredStationVisualModel : stationVisualModel + } + onModelChanged: print("ccccccccccccc", mainView.configured) } + Rectangle { + id: inputBubble + color: "black" + border.width: 2 + border.color: "white" + height: defaultFontHeight * 3 + width: height * 6 + radius: defaultFontHeight / 2 + anchors.top: header.bottom + anchors.right: parent.right + anchors.rightMargin: defaultFontHeight / 2 + anchors.topMargin: -defaultFontHeight / 2 + z: 2 + opacity: 0 + Behavior on opacity { + NumberAnimation { duration: 200 } + } + + Row { + anchors.centerIn: parent + width: parent.width - defaultFontHeight + spacing: defaultFontHeight / 2 + + function saveStation(name) { + mainView.title = name + inputBubble.opacity = 0 + header.showNextButton = false + header.backButtonText = "Configure" + } + + Text { + id: nameText + color: "white" + text: "Name:" + anchors.verticalCenter: parent.verticalCenter + } + InputField { + id: saveNameInput + width: parent.width - nameText.width - saveOkButton.width - parent.spacing * 2 + placeholderText: "Station" + onAccepted: parent.saveStation(text); + } + PushButton { + id: saveOkButton + text: "OK" + onClicked: parent.saveStation(saveNameInput.text) + } + } + + } + } diff --git a/data/qml/stations/CreateByArtist.qml b/data/qml/stations/CreateByArtist.qml index f3f2f4ceb..359b353f7 100644 --- a/data/qml/stations/CreateByArtist.qml +++ b/data/qml/stations/CreateByArtist.qml @@ -6,11 +6,11 @@ Item { id: root anchors.fill: parent - signal done() + signal done(string text) function createStation(artist) { mainView.startStationFromArtist(artist) - root.done() + root.done(artist) } Column { diff --git a/data/qml/stations/CreateByGenre.qml b/data/qml/stations/CreateByGenre.qml index 9d2fb1b9b..1d8964183 100644 --- a/data/qml/stations/CreateByGenre.qml +++ b/data/qml/stations/CreateByGenre.qml @@ -6,11 +6,11 @@ Item { id: root anchors.fill: parent - signal done() + signal done(string text) function createStation(genre) { mainView.startStationFromGenre(genre) - root.done() + root.done(genre) } ListModel { diff --git a/data/qml/stations/CreateByYear.qml b/data/qml/stations/CreateByYear.qml new file mode 100644 index 000000000..5e1461668 --- /dev/null +++ b/data/qml/stations/CreateByYear.qml @@ -0,0 +1,79 @@ +import QtQuick 1.1 +import tomahawk 1.0 +import "../tomahawkimports" + +Item { + id: root + anchors.fill: parent + + signal done(string text) + + function createStation(artist) { + mainView.startStationFromArtist(artist) + root.done(artist) + } + + 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 year..." + } + + 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 +// } +// } + + DoubleSlider { + width: parent.width + height: defaultFontHeight * 2 + min: 1960 + max: new Date().getFullYear() + lowerSliderPos: 1990 + upperSliderPos: 2010 + minMaxLabelsVisible: false + } + } +} diff --git a/data/qml/stations/StationCreatorPage2.qml b/data/qml/stations/StationCreatorPage2.qml index 34f4b65cd..295069aa6 100644 --- a/data/qml/stations/StationCreatorPage2.qml +++ b/data/qml/stations/StationCreatorPage2.qml @@ -8,7 +8,7 @@ Item { property int margins: defaultFontHeight * 2 property alias content: contentLoader.source - signal next() + signal next(string text) Loader { id: contentLoader @@ -19,7 +19,7 @@ Item { Connections { target: contentLoader.item - onDone: root.next() + onDone: root.next(text) } } diff --git a/data/qml/stations/StationItem.qml b/data/qml/stations/StationItem.qml new file mode 100644 index 000000000..9d7804a0a --- /dev/null +++ b/data/qml/stations/StationItem.qml @@ -0,0 +1,73 @@ +import QtQuick 1.1 +import tomahawk 1.0 +import "../tomahawkimports" + +Item { + id: stationItem + + 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 + } + +} diff --git a/data/qml/tomahawkimports/CoverFlip.qml b/data/qml/tomahawkimports/CoverFlip.qml index 58e85824c..742dcce71 100644 --- a/data/qml/tomahawkimports/CoverFlip.qml +++ b/data/qml/tomahawkimports/CoverFlip.qml @@ -49,8 +49,6 @@ PathView { right: parent.right } - backgroundColor: coverView.backgroundColor - showLabels: true showMirror: true artistName: model.artistName diff --git a/data/qml/tomahawkimports/CoverImage.qml b/data/qml/tomahawkimports/CoverImage.qml index 518137aac..e3f2c1d30 100644 --- a/data/qml/tomahawkimports/CoverImage.qml +++ b/data/qml/tomahawkimports/CoverImage.qml @@ -25,9 +25,6 @@ Item { // 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 @@ -55,7 +52,7 @@ Item { Rectangle { id: itemShadow - color: backgroundColor + color: "black" anchors.fill: parent //opacity: 1 - itemBrightness diff --git a/data/qml/tomahawkimports/DoubleSlider.qml b/data/qml/tomahawkimports/DoubleSlider.qml index b1dc522cc..08061b96e 100644 --- a/data/qml/tomahawkimports/DoubleSlider.qml +++ b/data/qml/tomahawkimports/DoubleSlider.qml @@ -2,8 +2,6 @@ import QtQuick 1.1 Item { id: root - width: 500 - height: 10 property int min: 0 property int max: 100 @@ -16,71 +14,144 @@ Item { /** Should the floating label indicating the current position be shown? */ property bool showFloatingLabel: true + property bool minMaxLabelsVisible: true property int lowerSliderPos: 25 property int upperSliderPos: 75 + onUpperSliderPosChanged: print("fooooooooo", upperSliderPos) + signal valueChanged() + QtObject { + id: priv + + property int steps: root.max - root.min + 1 + + property int sliderHeight: root.height + property int sliderWidth: root.height / 2 + } + Row { anchors.fill: parent + anchors.topMargin: defaultFontHeight * 1.2 + anchors.bottomMargin: defaultFontHeight * 1.2 spacing: 10 Text { id: minText text: root.minLabel.length > 0 ? root.minLabel : min color: "white" + visible: root.minMaxLabelsVisible } Item { id: sliderRect height: root.height - width: parent.width - minText.width - maxText.width - parent.spacing * 2 + property int maxWidth: parent.width - (minText.visible ? minText.width : 0) - (maxText.visible ? maxText.width : 0) - parent.spacing * 2 + width: maxWidth - (maxWidth % priv.steps) + anchors.horizontalCenter: parent.horizontalCenter function sliderPosToValue( sliderPos ) { - var percent = sliderPos * 100 / (sliderRect.width - lowerSlider.width); - return Math.floor(percent * (root.max - root.min) / 100) + root.min + var percent = sliderPos * 100 / (sliderRect.width - priv.sliderWidth/2); + return Math.floor(percent * (priv.steps-1) / 100) + root.min } function valueToSloderPos( value ) { - var percent = (value - root.min) * 100 / (root.max - root.min) - return percent * (sliderRect.width - lowerSlider.width) / 100 + var percent = (value - root.min) * 100 / (priv.steps-1) + return percent * (sliderRect.width - priv.sliderWidth/2) / 100 } Rectangle { id: sliderBase - height: root.height / 5 - width: parent.width + height: root.height / 1.5 + width: parent.width + defaultFontHeight * 1.5 color: "white" radius: height / 2 anchors.centerIn: parent + gradient: Gradient { + GradientStop { position: 0.0; color: "#ffffffff" } + GradientStop { position: 1.0; color: "#aaffffff" } + } + + Rectangle { + anchors.fill: sliderBase + anchors.leftMargin: lowerSlider.x + priv.sliderWidth + anchors.rightMargin: sliderBase.width - upperSlider.x - priv.sliderWidth + gradient: Gradient { + GradientStop { position: 0.0; color: "#aa962c26" } + GradientStop { position: 1.0; color: "#962c26" } + } + } + + Row { + id: stepRow + anchors.fill: parent + anchors.leftMargin: defaultFontHeight - lineWidth/2 + anchors.rightMargin: defaultFontHeight - lineWidth/2 + property int stepCount: root.max - root.min + 1 + property int lineHeight: height + property int lineWidth: lineHeight / 15 + spacing: (width - (stepCount * lineWidth)) / stepCount + + Repeater { + model: stepRow.stepCount + + Rectangle { + id: marker + height: stepRow.lineHeight * (isHighlight ? 1.2 : 1) + width: stepRow.lineWidth + color: "black" + + property bool isHighlight: index % 10 === 0 + + gradient: Gradient { + GradientStop { position: 0.0; color: marker.isHighlight ? "white" : "black" } + GradientStop { position: 1.0; color: marker.isHighlight ? "#aaffffff" : "black" } + } + + Text { + text: root.min + index + visible: marker.isHighlight + anchors.horizontalCenter: marker.horizontalCenter + anchors.top: marker.bottom + anchors.topMargin: defaultFontHeight / 2 + color: "white" + } + + } + + } + } + } + Rectangle { id: lowerSlider - height: root.height - width: height + height: priv.sliderHeight + width: priv.sliderWidth anchors.top: root.top - radius: height/2 + radius: height/4 border.color: "black" border.width: 2 - x: sliderRect.valueToSloderPos(root.lowerSliderPos) + x: sliderRect.valueToSloderPos(root.lowerSliderPos) - priv.sliderWidth/2 Rectangle { id: lowerFloatingRect color: "white" anchors.bottom: lowerSlider.top anchors.bottomMargin: 10 - visible: root.showFloatingLabel && lowerSliderMouseArea.pressed +// visible: root.showFloatingLabel && lowerSliderMouseArea.pressed width: lowerFloatingText.width * 1.2 height: lowerFloatingText.height + height * 1.2 - x: -(width - lowerSlider.width) / 2 - radius: height / 4 + x: -(width - priv.sliderWidth) / 2 + radius: height / 8 Text { id: lowerFloatingText anchors.centerIn: parent - text: sliderRect.sliderPosToValue(lowerSlider.x) + text: sliderRect.sliderPosToValue(lowerSlider.x + priv.sliderWidth/2) } } } @@ -89,10 +160,10 @@ Item { anchors.fill: lowerSlider drag.target: lowerSlider drag.axis: "XAxis" - drag.minimumX: 0 - drag.maximumX: upperSlider.x - lowerSlider.width + drag.minimumX: -priv.sliderWidth / 2 + drag.maximumX: upperSlider.x - priv.sliderWidth onReleased: { - root.lowerSliderPos = sliderRect.sliderPosToValue( lowerSlider.x ); + root.lowerSliderPos = sliderRect.sliderPosToValue( lowerSlider.x + priv.sliderWidth/2 ); root.valueChanged(); } } @@ -100,9 +171,9 @@ Item { Rectangle { id: upperSlider height: root.height - width: height + width: height / 2 anchors.top: root.top - radius: height/2 + radius: height / 4 border.color: "black" border.width: 2 x: sliderRect.valueToSloderPos(root.upperSliderPos) @@ -111,16 +182,16 @@ Item { color: "white" anchors.bottom: upperSlider.top anchors.bottomMargin: 10 - visible: root.showFloatingLabel && upperSliderMouseArea.pressed +// visible: root.showFloatingLabel && upperSliderMouseArea.pressed width: upperFloatingText.width * 1.2 height: upperFloatingText.height + height * 1.2 radius: height / 4 - x: -(width - upperSlider.width) / 2 + x: -(width - priv.sliderWidth) / 2 Text { id: upperFloatingText anchors.centerIn: parent - text: sliderRect.sliderPosToValue(upperSlider.x) + text: sliderRect.sliderPosToValue(upperSlider.x + priv.sliderWidth/2) } } @@ -131,14 +202,16 @@ Item { onClicked: print("button pressed") drag.target: upperSlider drag.axis: "XAxis" - drag.minimumX: lowerSlider.x + lowerSlider.width - drag.maximumX: parent.width - upperSlider.width + drag.minimumX: lowerSlider.x + priv.sliderWidth + drag.maximumX: parent.width - priv.sliderWidth onReleased: { - root.upperSliderPos = sliderRect.sliderPosToValue( upperSlider.x ); + root.upperSliderPos = sliderRect.sliderPosToValue( upperSlider.x + priv.sliderWidth/2 ); root.valueChanged(); } } + + } @@ -146,6 +219,7 @@ Item { id: maxText text: root.maxLabel.length > 0 ? root.maxLabel : max color: "white" + visible: root.minMaxLabelsVisible } } } diff --git a/data/qml/tomahawkimports/InputField.qml b/data/qml/tomahawkimports/InputField.qml index 9f052124d..c15d03077 100644 --- a/data/qml/tomahawkimports/InputField.qml +++ b/data/qml/tomahawkimports/InputField.qml @@ -17,6 +17,12 @@ Rectangle { property int spacing: defaultFontHeight * 0.2 signal accepted( string text ) + onFocusChanged: { + if(focus) { + textInput.forceActiveFocus(); + } + } + Image { id: searchIcon anchors { diff --git a/data/qml/tomahawkimports/TagCloud.qml b/data/qml/tomahawkimports/TagCloud.qml index ba3de03aa..ccdc82cd3 100644 --- a/data/qml/tomahawkimports/TagCloud.qml +++ b/data/qml/tomahawkimports/TagCloud.qml @@ -16,7 +16,7 @@ Item { Flow { anchors.centerIn: parent width: parent.width - spacing: 3 + spacing: defaultFontSize Repeater { id: cloudRepeater @@ -26,7 +26,7 @@ Item { id: cloudItem width: delegateText.width * 1.1 height: delegateText.height - property double itemScale: Math.random() + .3 + property double itemScale: tagCloud.randomNumber(0.5, 1.2) scale: itemScale Text { id: delegateText @@ -35,7 +35,7 @@ Item { text: modelData font.pointSize: 16 anchors.verticalCenter: parent.verticalCenter - anchors.verticalCenterOffset: tagCloud.randomNumber(0, 15) + //anchors.verticalCenterOffset: tagCloud.randomNumber(0, 15) states: [ State { diff --git a/resources.qrc b/resources.qrc index 5c0708890..100c6a0f7 100644 --- a/resources.qrc +++ b/resources.qrc @@ -103,9 +103,11 @@ data/qml/tomahawkimports/CoverFlip.qml data/qml/tomahawkimports/BusyIndicator.qml data/qml/StationView.qml + data/qml/stations/StationItem.qml data/qml/stations/StationCreatorPage1.qml data/qml/stations/StationCreatorPage2.qml data/qml/stations/CreateByArtist.qml + data/qml/stations/CreateByYear.qml data/qml/stations/StationConfig.qml data/qml/QmlGridView.qml data/qml/stations/CreateByGenre.qml diff --git a/src/libtomahawk/playlist/dynamic/widgets/DynamicQmlWidget.cpp b/src/libtomahawk/playlist/dynamic/widgets/DynamicQmlWidget.cpp index c4b149df1..0b5c1edd4 100644 --- a/src/libtomahawk/playlist/dynamic/widgets/DynamicQmlWidget.cpp +++ b/src/libtomahawk/playlist/dynamic/widgets/DynamicQmlWidget.cpp @@ -82,7 +82,22 @@ DynamicQmlWidget::playlistInterface() const QString DynamicQmlWidget::title() const { - return m_model->title(); + if ( !m_playlist->title().isEmpty() ) { + return m_playlist->title(); + } + return "Listen to radio..."; +} + + +void +DynamicQmlWidget::setTitle(const QString &title) +{ + m_model->setTitle( title ); + m_playlist->setTitle( title ); + m_model->playlist()->setTitle( title ); + m_playlist->createNewRevision( uuid(), m_playlist->currentrevision(), m_playlist->type(), m_playlist->generator()->controls() ); + m_playlist->reportCreated( m_playlist ); + emit titleChanged(); } diff --git a/src/libtomahawk/playlist/dynamic/widgets/DynamicQmlWidget.h b/src/libtomahawk/playlist/dynamic/widgets/DynamicQmlWidget.h index 382bf314a..c5a0ceac7 100644 --- a/src/libtomahawk/playlist/dynamic/widgets/DynamicQmlWidget.h +++ b/src/libtomahawk/playlist/dynamic/widgets/DynamicQmlWidget.h @@ -37,7 +37,7 @@ class DynamicQmlWidget : public DeclarativeView, public Tomahawk::ViewPage { Q_OBJECT - Q_PROPERTY(QString title READ title NOTIFY titleChanged) + Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged) Q_PROPERTY(bool loading READ loading NOTIFY loadingChanged) Q_PROPERTY(bool configured READ configured NOTIFY configuredChanged) @@ -49,6 +49,7 @@ public: virtual Tomahawk::playlistinterface_ptr playlistInterface() const; virtual QString title() const; + virtual void setTitle(const QString &title); virtual QString description() const; virtual QString iconSource() const;