mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-12 00:54:20 +02:00
some more work on the station qml
This commit is contained in:
@@ -20,12 +20,17 @@ Item {
|
|||||||
property double itemBrightness: 1
|
property double itemBrightness: 1
|
||||||
property double mirrorBrightness: .5
|
property double mirrorBrightness: .5
|
||||||
|
|
||||||
|
// will be emitted when the on hower play button is clicked
|
||||||
|
signal playClicked()
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
id: mouseArea
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: print("cover clicked")
|
hoverEnabled: true
|
||||||
}
|
|
||||||
|
|
||||||
|
onClicked: print("cover clicked")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: coverImage
|
id: coverImage
|
||||||
@@ -80,7 +85,6 @@ Item {
|
|||||||
Loader {
|
Loader {
|
||||||
id: mirroredCover
|
id: mirroredCover
|
||||||
sourceComponent: coverImage
|
sourceComponent: coverImage
|
||||||
opacity: parent.mirrorOpacity
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
transform : [
|
transform : [
|
||||||
Rotation {
|
Rotation {
|
||||||
@@ -101,7 +105,11 @@ Item {
|
|||||||
anchors.rightMargin: -2
|
anchors.rightMargin: -2
|
||||||
anchors.topMargin: -2
|
anchors.topMargin: -2
|
||||||
|
|
||||||
opacity: 1 - itemBrightness
|
opacity: 1 - itemBrightness + (mouseArea.containsMouse ? .2 : 0)
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
NumberAnimation { easing: Easing.Linear; duration: 300 }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -119,4 +127,18 @@ Item {
|
|||||||
GradientStop { position: 0.5; color: backgroundColor }
|
GradientStop { position: 0.5; color: backgroundColor }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: playButton
|
||||||
|
source: "../images/play-rest.png"
|
||||||
|
anchors.centerIn: parent
|
||||||
|
// width:
|
||||||
|
// height: 32
|
||||||
|
visible: mouseArea.containsMouse
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: root.playClicked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -9,23 +9,37 @@ Rectangle {
|
|||||||
|
|
||||||
property int coverSize: 230
|
property int coverSize: 230
|
||||||
|
|
||||||
|
onWidthChanged: {
|
||||||
|
print("width changed to", width)
|
||||||
|
coverView.model = dynamicModel
|
||||||
|
}
|
||||||
|
|
||||||
states: [
|
states: [
|
||||||
State {
|
State {
|
||||||
name: "configure" //; when: scene.state === "configure"
|
name: "configure"
|
||||||
PropertyChanges { target: coverView; anchors.leftMargin: scene.width + scene.coverSize + 20 }
|
|
||||||
PropertyChanges { target: styleCloud; anchors.leftMargin: 0 }
|
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: [
|
transitions: [
|
||||||
Transition {
|
Transition {
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
target: coverView
|
target: styleCloud
|
||||||
properties: "anchors.leftMargin"; easing.type: Easing.InOutQuad; duration: 500
|
properties: "anchors.leftMargin"; easing.type: Easing.InOutQuad; duration: 500
|
||||||
}
|
}
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
target: styleCloud
|
target: fineTuneView
|
||||||
properties: "anchors.leftMargin"; easing.type: Easing.InOutQuad; duration: 500
|
properties: "anchors.rightMargin"; easing.type: Easing.InOutQuad; duration: 500
|
||||||
|
}
|
||||||
|
NumberAnimation {
|
||||||
|
target: configureButton
|
||||||
|
properties: "opacity"; easing.type: Easing.InOutQuad; duration: 500
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -35,51 +49,88 @@ Rectangle {
|
|||||||
id: coverView
|
id: coverView
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
print("pathview created:", scene.width)
|
||||||
|
}
|
||||||
|
|
||||||
preferredHighlightBegin: 0.07 // scene.width / 11000
|
preferredHighlightBegin: 0.1 // scene.width / 11000
|
||||||
preferredHighlightEnd: preferredHighlightBegin
|
preferredHighlightEnd: preferredHighlightBegin
|
||||||
pathItemCount: 4
|
pathItemCount: 5
|
||||||
highlightMoveDuration: 500
|
//highlightMoveDuration: 500
|
||||||
|
|
||||||
model: dynamicModel
|
model: dynamicModel
|
||||||
currentIndex: currentlyPlayedIndex
|
currentIndex: currentlyPlayedIndex
|
||||||
|
|
||||||
|
property int pathStartX: width - scene.coverSize
|
||||||
|
property int pathStartY: height / 2
|
||||||
|
|
||||||
delegate: CoverImage {
|
delegate: CoverImage {
|
||||||
height: scene.coverSize
|
height: scene.coverSize
|
||||||
width: scene.coverSize
|
width: scene.coverSize
|
||||||
|
|
||||||
scale: PathView.itemScale
|
|
||||||
|
|
||||||
artistName: model.artistName
|
artistName: model.artistName
|
||||||
trackName: model.trackName
|
trackName: model.trackName
|
||||||
artworkId: index
|
artworkId: index
|
||||||
|
|
||||||
|
scale: PathView.itemScale
|
||||||
itemBrightness: PathView.itemBrightness
|
itemBrightness: PathView.itemBrightness
|
||||||
|
opacity: PathView.itemOpacity
|
||||||
z: x
|
z: x
|
||||||
|
|
||||||
|
onPlayClicked: echonestStation.playItem( index )
|
||||||
}
|
}
|
||||||
|
|
||||||
path: Path {
|
path: Path {
|
||||||
startX: coverView.width / 2 + 20
|
startX: coverView.pathStartX
|
||||||
startY: 155
|
startY: coverView.pathStartY
|
||||||
|
|
||||||
PathAttribute { name: "itemOpacity"; value: 0 }
|
PathAttribute { name: "itemOpacity"; value: 0 }
|
||||||
PathAttribute { name: "itemBrightness"; value: 0 }
|
PathAttribute { name: "itemBrightness"; value: 0 }
|
||||||
PathAttribute { name: "itemScale"; value: 1.5 }
|
PathAttribute { name: "itemScale"; value: 1.5 }
|
||||||
PathLine { x: coverView.width / 2; y: 150 }
|
PathLine { x: coverView.pathStartX * 9/10 ; y: coverView.pathStartY * 9/10 }
|
||||||
|
PathPercent { value: .1 }
|
||||||
PathAttribute { name: "itemOpacity"; value: 1 }
|
PathAttribute { name: "itemOpacity"; value: 1 }
|
||||||
PathAttribute { name: "itemBrightness"; value: 1 }
|
PathAttribute { name: "itemBrightness"; value: 1 }
|
||||||
PathAttribute { name: "itemScale"; value: 1.0 }
|
PathAttribute { name: "itemScale"; value: 1.0 }
|
||||||
PathLine { x: coverView.width / 2 - 100; y: 180;}
|
PathLine { x: coverView.pathStartX * .5; y: coverView.pathStartY * .7}
|
||||||
|
PathPercent { value: .4 }
|
||||||
PathAttribute { name: "itemOpacity"; value: 1 }
|
PathAttribute { name: "itemOpacity"; value: 1 }
|
||||||
PathAttribute { name: "itemBrightness"; value: 1 }
|
PathAttribute { name: "itemBrightness"; value: 1 }
|
||||||
PathAttribute { name: "itemScale"; value: 0.6 }
|
PathAttribute { name: "itemScale"; value: 0.6 }
|
||||||
PathLine { x: 100; y: 100;}
|
PathLine { x: coverView.pathStartX * .25 ; y: coverView.pathStartY * .25 }
|
||||||
|
PathPercent { value: .75 }
|
||||||
PathAttribute { name: "itemOpacity"; value: 1 }
|
PathAttribute { name: "itemOpacity"; value: 1 }
|
||||||
PathAttribute { name: "itemBrighness"; value: 0.4 }
|
PathAttribute { name: "itemBrightness"; value: .5 }
|
||||||
PathAttribute { name: "itemScale"; value: 0.4 }
|
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 {
|
Item {
|
||||||
id: styleCloud
|
id: styleCloud
|
||||||
anchors { left: parent.left; top: parent.top; bottom: parent.bottom }
|
anchors { left: parent.left; top: parent.top; bottom: parent.bottom }
|
||||||
@@ -88,7 +139,7 @@ Rectangle {
|
|||||||
|
|
||||||
function randomNumber(min, max) {
|
function randomNumber(min, max) {
|
||||||
var date = new Date();
|
var date = new Date();
|
||||||
return Math.floor((max - min) * Math.random(date.getSeconds())) + min
|
return (max - min) * Math.random(date.getSeconds()) + min
|
||||||
}
|
}
|
||||||
|
|
||||||
Flow {
|
Flow {
|
||||||
@@ -96,27 +147,126 @@ Rectangle {
|
|||||||
width: parent.width - 100
|
width: parent.width - 100
|
||||||
//model: controlModel
|
//model: controlModel
|
||||||
spacing: 3
|
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 {
|
Repeater {
|
||||||
|
id: cloudRepeater
|
||||||
model: generator.styles()
|
model: generator.styles()
|
||||||
|
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
width: delegateText.width
|
id: cloudItem
|
||||||
|
width: delegateText.width * scale
|
||||||
height: 28
|
height: 28
|
||||||
|
property double itemScale: Math.random()
|
||||||
|
scale: itemScale
|
||||||
Text {
|
Text {
|
||||||
id: delegateText
|
id: delegateText
|
||||||
color: "white"
|
color: "white"
|
||||||
//text: controlModel.controlAt( index ).summary
|
//text: controlModel.controlAt( index ).summary
|
||||||
text: modelData
|
text: modelData
|
||||||
font.pixelSize: styleCloud.randomNumber(11, 28)
|
font.pixelSize: 28
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.verticalCenterOffset: styleCloud.randomNumber(0, 15)
|
anchors.verticalCenterOffset: styleCloud.randomNumber(0, 15)
|
||||||
MouseArea {
|
}
|
||||||
anchors.fill: parent
|
MouseArea {
|
||||||
onClicked: echonestStation.setMainControl(modelData);
|
hoverEnabled: true
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: echonestStation.setMainControl(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 }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -80,6 +80,7 @@ set( libGuiSources
|
|||||||
playlist/dynamic/echonest/EchonestGenerator.cpp
|
playlist/dynamic/echonest/EchonestGenerator.cpp
|
||||||
playlist/dynamic/echonest/EchonestControl.cpp
|
playlist/dynamic/echonest/EchonestControl.cpp
|
||||||
playlist/dynamic/echonest/EchonestSteerer.cpp
|
playlist/dynamic/echonest/EchonestSteerer.cpp
|
||||||
|
playlist/dynamic/echonest/EchonestStation.cpp
|
||||||
playlist/dynamic/widgets/DynamicWidget.cpp
|
playlist/dynamic/widgets/DynamicWidget.cpp
|
||||||
playlist/dynamic/widgets/DynamicQmlWidget.cpp
|
playlist/dynamic/widgets/DynamicQmlWidget.cpp
|
||||||
playlist/dynamic/widgets/DynamicControlWrapper.cpp
|
playlist/dynamic/widgets/DynamicControlWrapper.cpp
|
||||||
@@ -141,6 +142,7 @@ set( libGuiSources
|
|||||||
widgets/ToggleButton.cpp
|
widgets/ToggleButton.cpp
|
||||||
widgets/FadingPixmap.cpp
|
widgets/FadingPixmap.cpp
|
||||||
widgets/SocialPlaylistWidget.cpp
|
widgets/SocialPlaylistWidget.cpp
|
||||||
|
widgets/DeclarativeCoverArtProvider.cpp
|
||||||
widgets/infowidgets/SourceInfoWidget.cpp
|
widgets/infowidgets/SourceInfoWidget.cpp
|
||||||
widgets/infowidgets/ArtistInfoWidget.cpp
|
widgets/infowidgets/ArtistInfoWidget.cpp
|
||||||
widgets/infowidgets/AlbumInfoWidget.cpp
|
widgets/infowidgets/AlbumInfoWidget.cpp
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
#include "DynamicQmlWidget.h"
|
#include "DynamicQmlWidget.h"
|
||||||
|
|
||||||
|
#include "dynamic/echonest/EchonestStation.h"
|
||||||
#include "playlist/dynamic/DynamicModel.h"
|
#include "playlist/dynamic/DynamicModel.h"
|
||||||
#include "playlist/PlayableProxyModel.h"
|
#include "playlist/PlayableProxyModel.h"
|
||||||
#include "utils/TomahawkUtilsGui.h"
|
#include "utils/TomahawkUtilsGui.h"
|
||||||
@@ -8,6 +9,7 @@
|
|||||||
#include "dynamic/GeneratorInterface.h"
|
#include "dynamic/GeneratorInterface.h"
|
||||||
#include "PlayableItem.h"
|
#include "PlayableItem.h"
|
||||||
#include "Source.h"
|
#include "Source.h"
|
||||||
|
#include "widgets/DeclarativeCoverArtProvider.h"
|
||||||
|
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <qdeclarative.h>
|
#include <qdeclarative.h>
|
||||||
@@ -20,23 +22,28 @@ namespace Tomahawk
|
|||||||
|
|
||||||
DynamicQmlWidget::DynamicQmlWidget( const dynplaylist_ptr& playlist, QWidget* parent )
|
DynamicQmlWidget::DynamicQmlWidget( const dynplaylist_ptr& playlist, QWidget* parent )
|
||||||
: QDeclarativeView( parent )
|
: QDeclarativeView( parent )
|
||||||
, QDeclarativeImageProvider( QDeclarativeImageProvider::Pixmap )
|
|
||||||
, m_playlist( playlist )
|
, m_playlist( playlist )
|
||||||
{
|
{
|
||||||
|
|
||||||
engine()->addImageProvider( "albumart", this );
|
|
||||||
|
|
||||||
setResizeMode( QDeclarativeView::SizeRootObjectToView );
|
setResizeMode( QDeclarativeView::SizeRootObjectToView );
|
||||||
|
|
||||||
m_model = new DynamicModel( this );
|
m_model = new DynamicModel( this );
|
||||||
|
|
||||||
m_proxyModel = new PlayableProxyModel( this );
|
m_proxyModel = new PlayableProxyModel( this );
|
||||||
m_proxyModel->setSourcePlayableModel( m_model );
|
m_proxyModel->setSourcePlayableModel( m_model );
|
||||||
m_proxyModel->setShowOfflineResults( true );
|
m_proxyModel->setShowOfflineResults( false );
|
||||||
|
|
||||||
|
// QML image providers will be deleted by the view
|
||||||
|
engine()->addImageProvider( "albumart", new DeclarativeCoverArtProvider( m_proxyModel ) );
|
||||||
|
|
||||||
m_model->loadPlaylist( m_playlist );
|
m_model->loadPlaylist( m_playlist );
|
||||||
|
m_model->startOnDemand();
|
||||||
|
|
||||||
// Initially seed the playlist
|
// Initially seed the playlist
|
||||||
m_playlist->generator()->generate( 20 );
|
playlist->generator()->fetchNext();
|
||||||
|
// m_playlist->generator()->generate( 20 );
|
||||||
|
|
||||||
qDebug() << "###got" << m_playlist->generator()->controls().size() << "controls";
|
qDebug() << "###got" << m_playlist->generator()->controls().size() << "controls";
|
||||||
|
|
||||||
@@ -59,7 +66,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_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 );
|
||||||
@@ -70,7 +77,9 @@ DynamicQmlWidget::DynamicQmlWidget( const dynplaylist_ptr& playlist, QWidget* pa
|
|||||||
|
|
||||||
connect( m_model, SIGNAL( currentItemChanged( QPersistentModelIndex ) ), SLOT( currentItemChanged( QPersistentModelIndex ) ) );
|
connect( m_model, SIGNAL( currentItemChanged( QPersistentModelIndex ) ), SLOT( currentItemChanged( QPersistentModelIndex ) ) );
|
||||||
connect( m_playlist->generator().data(), SIGNAL( generated( QList<Tomahawk::query_ptr> ) ), this, SLOT( tracksGenerated( QList<Tomahawk::query_ptr> ) ) );
|
connect( m_playlist->generator().data(), SIGNAL( generated( QList<Tomahawk::query_ptr> ) ), this, SLOT( tracksGenerated( QList<Tomahawk::query_ptr> ) ) );
|
||||||
|
connect( m_playlist->generator().data(), SIGNAL( nextTrackGenerated( Tomahawk::query_ptr ) ), this, SLOT( nextTrackGenerated( Tomahawk::query_ptr ) ) );
|
||||||
connect( m_playlist.data(), SIGNAL( dynamicRevisionLoaded( Tomahawk::DynamicPlaylistRevision ) ), this, SLOT( onRevisionLoaded( Tomahawk::DynamicPlaylistRevision ) ) );
|
connect( m_playlist.data(), SIGNAL( dynamicRevisionLoaded( Tomahawk::DynamicPlaylistRevision ) ), this, SLOT( onRevisionLoaded( Tomahawk::DynamicPlaylistRevision ) ) );
|
||||||
|
connect( m_playlist->generator().data(), SIGNAL( error( QString, QString )), SLOT( error(QString,QString) ) );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,39 +120,13 @@ DynamicQmlWidget::pixmap() const
|
|||||||
bool
|
bool
|
||||||
DynamicQmlWidget::jumpToCurrentTrack()
|
DynamicQmlWidget::jumpToCurrentTrack()
|
||||||
{
|
{
|
||||||
return false;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
QPixmap DynamicQmlWidget::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
|
|
||||||
{
|
|
||||||
// We always can generate it in the requested size
|
|
||||||
int width = requestedSize.width() > 0 ? requestedSize.width() : 230;
|
|
||||||
int height = requestedSize.height() > 0 ? requestedSize.height() : 230;
|
|
||||||
|
|
||||||
if( size )
|
|
||||||
*size = QSize( width, height );
|
|
||||||
|
|
||||||
QModelIndex index = m_proxyModel->mapToSource( m_proxyModel->index( id.toInt(), 0, QModelIndex() ) );
|
|
||||||
qDebug() << "!*!*!*! got index" << index << id;
|
|
||||||
if( index.isValid() ) {
|
|
||||||
PlayableItem *item = m_model->itemFromIndex( index );
|
|
||||||
qDebug() << "item:" << item;
|
|
||||||
qDebug() << "item2:" << item->artistName() << item->name();
|
|
||||||
if ( !item->query().isNull() ) {
|
|
||||||
return item->query()->displayQuery()->cover( *size );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: create default cover art image
|
|
||||||
QPixmap pixmap( *size );
|
|
||||||
pixmap.fill();
|
|
||||||
|
|
||||||
return pixmap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DynamicQmlWidget::currentItemChanged( const QPersistentModelIndex ¤tIndex )
|
void DynamicQmlWidget::currentItemChanged( const QPersistentModelIndex ¤tIndex )
|
||||||
{
|
{
|
||||||
rootContext()->setContextProperty( "currentlyPlayedIndex", m_proxyModel->mapFromSource( currentIndex ).row() );
|
rootContext()->setContextProperty( "currentlyPlayedIndex", m_proxyModel->mapFromSource( currentIndex ).row() );
|
||||||
|
m_playlist->generator()->fetchNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -157,6 +140,26 @@ DynamicQmlWidget::tracksGenerated( const QList< query_ptr >& queries )
|
|||||||
//m_model->startOnDemand();
|
//m_model->startOnDemand();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DynamicQmlWidget::nextTrackGenerated(const query_ptr &track)
|
||||||
|
{
|
||||||
|
m_model->tracksGenerated( QList<query_ptr>() << track );
|
||||||
|
m_playlist->resolve();
|
||||||
|
|
||||||
|
qDebug() << "next track generated" << m_proxyModel->rowCount() << m_proxyModel->currentIndex().row();
|
||||||
|
if( m_proxyModel->rowCount() <= m_proxyModel->currentIndex().row() + 8 ) {
|
||||||
|
qDebug() << "fetching next one";
|
||||||
|
m_playlist->generator()->fetchNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicQmlWidget::error(const QString &title, const QString &body)
|
||||||
|
{
|
||||||
|
qDebug() << "got a generator error:" << title << body;
|
||||||
|
|
||||||
|
m_playlist->generator()->fetchNext();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void DynamicQmlWidget::onRevisionLoaded(DynamicPlaylistRevision)
|
void DynamicQmlWidget::onRevisionLoaded(DynamicPlaylistRevision)
|
||||||
{
|
{
|
||||||
m_playlist->resolve();
|
m_playlist->resolve();
|
||||||
|
@@ -32,7 +32,7 @@ namespace Tomahawk
|
|||||||
|
|
||||||
class DynamicModel;
|
class DynamicModel;
|
||||||
|
|
||||||
class DynamicQmlWidget : public QDeclarativeView, public Tomahawk::ViewPage, public QDeclarativeImageProvider
|
class DynamicQmlWidget : public QDeclarativeView, public Tomahawk::ViewPage
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -51,12 +51,12 @@ public:
|
|||||||
|
|
||||||
virtual bool jumpToCurrentTrack();
|
virtual bool jumpToCurrentTrack();
|
||||||
|
|
||||||
QPixmap requestPixmap( const QString &id, QSize *size, const QSize &requestedSize );
|
|
||||||
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void currentItemChanged( const QPersistentModelIndex ¤tIndex );
|
void currentItemChanged( const QPersistentModelIndex ¤tIndex );
|
||||||
void tracksGenerated( const QList< Tomahawk::query_ptr>& queries );
|
void tracksGenerated( const QList< Tomahawk::query_ptr>& queries );
|
||||||
|
void nextTrackGenerated( const Tomahawk::query_ptr& track );
|
||||||
|
void error( const QString& title, const QString& body);
|
||||||
|
|
||||||
void onRevisionLoaded( Tomahawk::DynamicPlaylistRevision );
|
void onRevisionLoaded( Tomahawk::DynamicPlaylistRevision );
|
||||||
private:
|
private:
|
||||||
DynamicModel* m_model;
|
DynamicModel* m_model;
|
||||||
@@ -68,49 +68,6 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#include "dynamic/GeneratorInterface.h"
|
#include "dynamic/GeneratorInterface.h"
|
||||||
|
|
||||||
namespace Tomahawk
|
|
||||||
{
|
|
||||||
class EchonestStation: public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
Q_PROPERTY(bool configured READ configured NOTIFY configuredChanged)
|
|
||||||
Q_PROPERTY(Tomahawk::DynamicControl* mainControl READ mainControl)
|
|
||||||
|
|
||||||
public:
|
|
||||||
EchonestStation(geninterface_ptr generator, QObject *parent = 0) : QObject(parent), m_generator(generator) {}
|
|
||||||
|
|
||||||
Tomahawk::DynamicControl* mainControl() {
|
|
||||||
foreach(dyncontrol_ptr control, m_generator->controls()) {
|
|
||||||
qDebug() << "got control" << control->selectedType();
|
|
||||||
if(control->selectedType() == "Artist" || control->selectedType() == "Style") {
|
|
||||||
return control.data();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool configured() { return mainControl() != 0; }
|
|
||||||
|
|
||||||
Q_INVOKABLE void setMainControl(const QString &type) {
|
|
||||||
dyncontrol_ptr control = m_generator->createControl("echonest");
|
|
||||||
control->setSelectedType("Style");
|
|
||||||
control->setMatch("1");
|
|
||||||
control->setInput(type);
|
|
||||||
qDebug() << "created control" << control->type() << control->selectedType() << control->match();
|
|
||||||
m_generator->generate(20);
|
|
||||||
|
|
||||||
emit configuredChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void configuredChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
geninterface_ptr m_generator;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Tomahawk
|
namespace Tomahawk
|
||||||
{
|
{
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user