1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-13 17:43:59 +02:00

restructured QML

This commit is contained in:
Michael Zanetti
2012-07-14 16:19:35 +02:00
parent 71eb1e916a
commit 710e570845
13 changed files with 445 additions and 274 deletions

View File

@@ -3,6 +3,11 @@ import QtQuick 1.1
Item { Item {
id: root id: root
// Should the artist + track labels be painted
property bool showLabels: true
// Should the play button be painted on mouse hover?
property bool showPlayButton: false
// Labels & Cover // Labels & Cover
property string artistName property string artistName
property string trackName property string trackName
@@ -22,13 +27,15 @@ Item {
// will be emitted when the on hower play button is clicked // will be emitted when the on hower play button is clicked
signal playClicked() signal playClicked()
// will be emitted when the cover is clicked
signal clicked()
MouseArea { MouseArea {
id: mouseArea id: mouseArea
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
onClicked: print("cover clicked") onClicked: root.clicked();
} }
@@ -53,10 +60,10 @@ Item {
height: 32 height: 32
anchors.margins: 5 anchors.margins: 5
color: "black" color: "black"
opacity: 0.5 opacity: showLabels ? 0.5 : 0
radius: 3 radius: 3
} }
Text { Text {
color: "white" color: "white"
font.bold: true font.bold: true
@@ -65,6 +72,7 @@ Item {
anchors.margins: 2 anchors.margins: 2
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight elide: Text.ElideRight
opacity: showLabels ? 1 : 0
} }
Text { Text {
color: "white" color: "white"
@@ -73,6 +81,7 @@ Item {
anchors.margins: 2 anchors.margins: 2
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight elide: Text.ElideRight
opacity: showLabels ? 1 : 0
} }
} }
@@ -130,11 +139,9 @@ Item {
Image { Image {
id: playButton id: playButton
visible: showPlayButton ? mouseArea.containsMouse : false
source: "../images/play-rest.png" source: "../images/play-rest.png"
anchors.centerIn: parent anchors.centerIn: parent
// width:
// height: 32
visible: mouseArea.containsMouse
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: root.playClicked(); onClicked: root.playClicked();

View File

@@ -0,0 +1,53 @@
import QtQuick 1.1
import tomahawk 1.0
Item {
id: fineTuneView
property color textColor: "white"
signal done();
Grid {
anchors.fill: parent
anchors.margins: 50
Text {
color: fineTuneView.textColor
text: "Name"
}
TextInput {
id: stationName
width: 200
text: echonestStation.name
//onTextChanged: echonestStation.
}
}
Rectangle {
id: configureButton
anchors.bottom: parent.bottom
anchors.bottomMargin: 20
anchors.horizontalCenter: parent.horizontalCenter
color: "gray"
height: 20
width: 150
radius: 10
//opacity: 0
Text {
anchors.centerIn: parent
text: "configure"
color: "white"
}
MouseArea {
anchors.fill: parent
onClicked: {
fineTuneView.done();
}
}
}
}

View File

@@ -7,265 +7,56 @@ Rectangle {
anchors.fill: parent anchors.fill: parent
state: echonestStation.configured ? "list" : "configure" state: echonestStation.configured ? "list" : "configure"
property int coverSize: 230
onWidthChanged: { VisualItemModel {
print("width changed to", width) id: stationVisualModel
coverView.model = dynamicModel
TagCloud {
height: scene.height
width: scene.width
model: generator.styles()
opacity: echonestStation.configured ? 0 : 1
onTagClicked: {
echonestStation.setMainControl( item );
stationListView.incrementCurrentIndex();
} }
states: [ Behavior on opacity {
State { NumberAnimation { duration: 300 }
name: "configure"
PropertyChanges { target: styleCloud; anchors.leftMargin: 0 }
PropertyChanges { target: configureButton; opacity: 1 }
},
State {
name: "finetune"
PropertyChanges { target: fineTuneView; anchors.rightMargin: 0 }
PropertyChanges { target: configureButton; opacity: 1 }
}
]
transitions: [
Transition {
NumberAnimation {
target: styleCloud
properties: "anchors.leftMargin"; easing.type: Easing.InOutQuad; duration: 500
}
NumberAnimation {
target: fineTuneView
properties: "anchors.rightMargin"; easing.type: Easing.InOutQuad; duration: 500
}
NumberAnimation {
target: configureButton
properties: "opacity"; easing.type: Easing.InOutQuad; duration: 500
} }
} }
]
StationView {
PathView { coverSize: 250
id: coverView height: scene.height
anchors.fill: parent
Component.onCompleted: {
print("pathview created:", scene.width)
}
preferredHighlightBegin: 0.1 // scene.width / 11000
preferredHighlightEnd: preferredHighlightBegin
pathItemCount: 5
//highlightMoveDuration: 500
model: dynamicModel
currentIndex: currentlyPlayedIndex
property int pathStartX: width - scene.coverSize
property int pathStartY: height / 2
delegate: CoverImage {
height: scene.coverSize
width: scene.coverSize
artistName: model.artistName
trackName: model.trackName
artworkId: index
scale: PathView.itemScale
itemBrightness: PathView.itemBrightness
opacity: PathView.itemOpacity
z: x
onPlayClicked: echonestStation.playItem( index )
}
path: Path {
startX: coverView.pathStartX
startY: coverView.pathStartY
PathAttribute { name: "itemOpacity"; value: 0 }
PathAttribute { name: "itemBrightness"; value: 0 }
PathAttribute { name: "itemScale"; value: 1.5 }
PathLine { x: coverView.pathStartX * 9/10 ; y: coverView.pathStartY * 9/10 }
PathPercent { value: .1 }
PathAttribute { name: "itemOpacity"; value: 1 }
PathAttribute { name: "itemBrightness"; value: 1 }
PathAttribute { name: "itemScale"; value: 1.0 }
PathLine { x: coverView.pathStartX * .5; y: coverView.pathStartY * .7}
PathPercent { value: .4 }
PathAttribute { name: "itemOpacity"; value: 1 }
PathAttribute { name: "itemBrightness"; value: 1 }
PathAttribute { name: "itemScale"; value: 0.6 }
PathLine { x: coverView.pathStartX * .25 ; y: coverView.pathStartY * .25 }
PathPercent { value: .75 }
PathAttribute { name: "itemOpacity"; value: 1 }
PathAttribute { name: "itemBrightness"; value: .5 }
PathAttribute { name: "itemScale"; value: 0.4 }
PathLine { x: 0; y: 0 }
PathPercent { value: 1 }
PathAttribute { name: "itemOpacity"; value: 1 }
PathAttribute { name: "itemBrightness"; value: 0 }
PathAttribute { name: "itemScale"; value: 0.2 }
}
states: [
State {
name: "normal"
PropertyChanges { target: coverView; anchors.rightMargin: 0 }
},
State {
name: "shrinked"
PropertyChanges { target: coverView; anchors.rightMargin: scene.width / 3 }
}
]
transitions: [
Transition {
NumberAnimation {
target: coverView
properties: "anchors.rightMargin"; easing.type: Easing.InOutQuad; duration: 500
}
}
]
}
Item {
id: styleCloud
anchors { left: parent.left; top: parent.top; bottom: parent.bottom }
anchors.leftMargin: scene.width
width: scene.width width: scene.width
function randomNumber(min, max) { onConfigure: stationListView.incrementCurrentIndex();
var date = new Date();
return (max - min) * Math.random(date.getSeconds()) + min
} }
Flow {
anchors.centerIn: parent
width: parent.width - 100
//model: controlModel
spacing: 3
Timer { StationConfig {
interval: 5000 height: scene.height
running: false width: scene.width
repeat: true
onTriggered: { onDone: stationListView.decrementCurrentIndex();
for(var i = 0; i < cloudRepeater.count; i++) {
var item = cloudRepeater.itemAt(i);
if(item.itemScale > 0.6) {
item.itemScale = Math.random();
} else {
item.itemScale = Math.random();
}
}
} }
} }
Repeater { ListView {
id: cloudRepeater id: stationListView
model: generator.styles()
delegate: Item {
id: cloudItem
width: delegateText.width * scale
height: 28
property double itemScale: Math.random()
scale: itemScale
Text {
id: delegateText
color: "white"
//text: controlModel.controlAt( index ).summary
text: modelData
font.pixelSize: 28
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: styleCloud.randomNumber(0, 15)
}
MouseArea {
hoverEnabled: true
anchors.fill: parent anchors.fill: parent
onClicked: echonestStation.setMainControl(modelData); contentHeight: scene.height
contentWidth: scene.width
orientation: ListView.Horizontal
model: stationVisualModel
interactive: false
highlightMoveDuration: 400
onMousePositionChanged: { Component.onCompleted: {
cloudItem.scale = 1; if ( echonestStation.configured ) {
delegateTimer.restart(); currentIndex = 1
}
}
Timer {
id: delegateTimer
interval: 3000
repeat: false
onTriggered: cloudItem.scale = cloudItem.itemScale
}
Behavior on scale {
NumberAnimation { easing: Easing.Linear; duration: 1000 }
}
}
}
}
}
Item {
id: fineTuneView
anchors { right: parent.right; top: parent.top; bottom: parent.bottom }
anchors.rightMargin: -width
width: scene.width / 2
property color textColor: "white"
Rectangle {
anchors.fill: parent
anchors.margins: 30
color: "gray"
border.width: 2
border.color: "white"
radius: 20
}
Grid {
Text {
color: fineTuneView.textColor
text: "Name"
}
TextInput {
id: stationName
//onTextChanged: echonestStation.
}
}
}
Rectangle {
id: configureButton
anchors.right: parent.right
anchors.rightMargin: 20
anchors.verticalCenter: parent.verticalCenter
color: "gray"
height: 50
width: 50
radius: 25
//opacity: 0
Text {
anchors.centerIn: parent
text: "configure"
}
MouseArea {
anchors.fill: parent
onClicked: {
print("changing scene state to", scene.state)
if( scene.state === "list" ) {
scene.state = "finetune";
coverView.state = "shrinked"
} else {
scene.state = "list";
coverView.state = "normal"
}
print("changed scene state to", scene.state)
} }
} }
} }

201
data/qml/StationView.qml Normal file
View File

@@ -0,0 +1,201 @@
import QtQuick 1.1
import tomahawk 1.0
Item {
id: root
property int coverSize
signal configure()
PathView {
id: coverView
anchors.fill: parent
anchors.rightMargin: parent.width / 3
preferredHighlightBegin: 0.2 // scene.width / 11000
preferredHighlightEnd: preferredHighlightBegin
pathItemCount: 5
//highlightMoveDuration: 500
model: dynamicModel
currentIndex: currentlyPlayedIndex
property int pathStartX: width / 2
property int pathStartY: height / 2
delegate: CoverImage {
height: root.coverSize
width: root.coverSize
showLabels: false
//artistName: model.artistName
//trackName: model.trackName
artworkId: index
scale: PathView.itemScale
itemBrightness: PathView.itemBrightness
opacity: PathView.itemOpacity
z: x
onClicked: {
if ( currentlyPlayedIndex !==-1 ) {
echonestStation.playItem( index )
}
}
}
path: Path {
startX: coverView.pathStartX
startY: coverView.pathStartY
PathAttribute { name: "itemOpacity"; value: 0 }
PathAttribute { name: "itemBrightness"; value: 0 }
PathAttribute { name: "itemScale"; value: 1.5 }
PathLine { x: coverView.pathStartX * 0.9 ; y: coverView.pathStartY * 0.9 }
PathPercent { value: .2 }
PathAttribute { name: "itemOpacity"; value: 1 }
PathAttribute { name: "itemBrightness"; value: 1 }
PathAttribute { name: "itemScale"; value: 1 }
PathLine { x: coverView.pathStartX * .5; y: coverView.pathStartY * .5}
PathPercent { value: .3 }
PathAttribute { name: "itemOpacity"; value: 1 }
PathAttribute { name: "itemBrightness"; value: 1 }
PathAttribute { name: "itemScale"; value: 0.5 }
// PathLine { x: coverView.pathStartX * .25 ; y: coverView.pathStartY * .25 }
// PathPercent { value: .75 }
// PathAttribute { name: "itemOpacity"; value: 1 }
// PathAttribute { name: "itemBrightness"; value: .5 }
// PathAttribute { name: "itemScale"; value: 0.4 }
PathLine { x: 0; y: 0 }
PathPercent { value: 1 }
PathAttribute { name: "itemOpacity"; value: 1 }
PathAttribute { name: "itemBrightness"; value: 0 }
PathAttribute { name: "itemScale"; value: 0.1 }
}
}
Item {
anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
anchors.margins: 50
width: scene.width / 3
Column {
anchors { left: parent.left; top: parent.top; right: parent.right }
Text {
color: "white"
font.pixelSize: 16
width: parent.width
elide: Text.ElideRight
text: "Station:"
}
Text {
color: "white"
font.pixelSize: 24
font.bold: true
width: parent.width
elide: Text.ElideRight
text: echonestStation.name
}
}
Column {
anchors.right: parent.right
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: scene.width / 3
Text {
color: "white"
font.pixelSize: 16
width: parent.width
elide: Text.ElideRight
text: "Now Playing:"
visible: currentlyPlayedIndex !== -1
}
Rectangle {
height: 64
width: parent.width
radius: 32
border.width: 2
border.color: "white"
color: startPlayingMouseArea.containsMouse ? "blue" : "gray"
visible: currentlyPlayedIndex === -1
Image {
id: image
source: "../images/play-rest.png"
anchors.left: parent.left
anchors.margins: 10
anchors.verticalCenter: parent.verticalCenter
}
Text {
color: "white"
font.pixelSize: 24
anchors.left: image.right
anchors.margins: 10
anchors.verticalCenter: parent.verticalCenter
width: parent.width - 30 - image.width
elide: Text.ElideRight
text: "Start playing"
}
MouseArea {
id: startPlayingMouseArea
anchors.fill: parent
hoverEnabled: true
onClicked: echonestStation.playItem( 0 );
}
}
Text {
color: "white"
font.pixelSize: 24
width: parent.width
elide: Text.ElideRight
text: coverView.model.itemFromIndex( currentlyPlayedIndex ).name
}
Text {
color: "white"
font.pixelSize: 20
width: parent.width
elide: Text.ElideRight
text: coverView.model.itemFromIndex( currentlyPlayedIndex ).artistName
}
Text {
color: "white"
font.pixelSize: 20
width: parent.width
elide: Text.ElideRight
text: coverView.model.itemFromIndex( currentlyPlayedIndex ).albumName
}
}
}
Rectangle {
id: configureButton
anchors.bottom: parent.bottom
anchors.bottomMargin: 20
anchors.horizontalCenter: parent.horizontalCenter
color: "gray"
height: 20
width: 150
radius: 10
//opacity: 0
Text {
anchors.centerIn: parent
text: "configure"
color: "white"
}
MouseArea {
anchors.fill: parent
onClicked: {
root.configure();
}
}
}
}

81
data/qml/TagCloud.qml Normal file
View File

@@ -0,0 +1,81 @@
import QtQuick 1.1
import tomahawk 1.0
Item {
id: tagCloud
property variant model: 10
signal tagClicked( string item )
function randomNumber(min, max) {
var date = new Date();
return (max - min) * Math.random(date.getSeconds()) + min
}
Flow {
anchors.centerIn: parent
width: parent.width - 100
//model: controlModel
spacing: 3
Timer {
interval: 5000
running: false
repeat: true
onTriggered: {
for(var i = 0; i < cloudRepeater.count; i++) {
var item = cloudRepeater.itemAt(i);
if(item.itemScale > 0.6) {
item.itemScale = Math.random();
} else {
item.itemScale = Math.random();
}
}
}
}
Repeater {
id: cloudRepeater
model: tagCloud.model
delegate: Item {
id: cloudItem
width: delegateText.width * scale
height: 28
property double itemScale: Math.random()
scale: itemScale
Text {
id: delegateText
color: "white"
//text: controlModel.controlAt( index ).summary
text: "bla" + modelData
font.pixelSize: 28
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: tagCloud.randomNumber(0, 15)
}
MouseArea {
hoverEnabled: true
anchors.fill: parent
onClicked: tagCloud.tagClicked( modelData )
onMousePositionChanged: {
cloudItem.scale = 1;
delegateTimer.restart();
}
}
Timer {
id: delegateTimer
interval: 3000
repeat: false
onTriggered: cloudItem.scale = cloudItem.itemScale
}
Behavior on scale {
NumberAnimation { easing: Easing.Linear; duration: 1000 }
}
}
}
}
}

View File

@@ -149,5 +149,8 @@
<file>data/qml/ArtistInfoScene.qml</file> <file>data/qml/ArtistInfoScene.qml</file>
<file>data/qml/StationScene.qml</file> <file>data/qml/StationScene.qml</file>
<file>data/qml/CoverImage.qml</file> <file>data/qml/CoverImage.qml</file>
<file>data/qml/TagCloud.qml</file>
<file>data/qml/StationConfig.qml</file>
<file>data/qml/StationView.qml</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@@ -30,7 +30,9 @@
class DLLEXPORT PlayableItem : public QObject class DLLEXPORT PlayableItem : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QString name READ name NOTIFY dataChanged)
Q_PROPERTY(QString artistName READ artistName NOTIFY dataChanged)
Q_PROPERTY(QString albumName READ albumName NOTIFY dataChanged)
public: public:
~PlayableItem(); ~PlayableItem();

View File

@@ -583,3 +583,11 @@ PlayableProxyModel::setFilter( const QString& pattern )
emit filterChanged( pattern ); emit filterChanged( pattern );
} }
} }
PlayableItem*
PlayableProxyModel::itemFromIndex(int itemIndex) const
{
qDebug() << "returning item" << sourceModel()->itemFromIndex( itemIndex )->name();
QModelIndex modelIndex = index( itemIndex, 0 );
return sourceModel()->itemFromIndex( mapToSource( modelIndex ) );
}

View File

@@ -67,7 +67,7 @@ public:
virtual void setMaxVisibleItems( int items ); virtual void setMaxVisibleItems( int items );
virtual PlayableItem* itemFromIndex( const QModelIndex& index ) const { return sourceModel()->itemFromIndex( index ); } virtual PlayableItem* itemFromIndex( const QModelIndex& index ) const { return sourceModel()->itemFromIndex( index ); }
Q_INVOKABLE virtual PlayableItem* itemFromIndex( int itemIndex ) const { return sourceModel()->itemFromIndex( itemIndex ); } Q_INVOKABLE virtual PlayableItem* itemFromIndex( int itemIndex ) const;
virtual Tomahawk::playlistinterface_ptr playlistInterface(); virtual Tomahawk::playlistinterface_ptr playlistInterface();

View File

@@ -7,13 +7,25 @@ namespace Tomahawk
{ {
EchonestStation::EchonestStation( PlayableProxyModel *model, geninterface_ptr generator, QObject *parent ) EchonestStation::EchonestStation( PlayableProxyModel *model, geninterface_ptr generator, QObject *parent )
: QObject(parent) : QObject( parent )
, m_model(model) , m_name( model->sourceModel()->title() )
, m_generator(generator) , m_model( model )
, m_generator( generator )
{ {
} }
QString EchonestStation::name() const
{
return m_name;
}
void EchonestStation::setName(const QString &name)
{
m_name = name;
emit nameChanged();
}
Tomahawk::DynamicControl* EchonestStation::mainControl() { Tomahawk::DynamicControl* EchonestStation::mainControl() {
foreach(dyncontrol_ptr control, m_generator->controls()) { foreach(dyncontrol_ptr control, m_generator->controls()) {
qDebug() << "got control" << control->selectedType(); qDebug() << "got control" << control->selectedType();

View File

@@ -9,12 +9,16 @@ namespace Tomahawk
class EchonestStation: public QObject class EchonestStation: public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(bool configured READ configured NOTIFY configuredChanged) Q_PROPERTY( QString name READ name WRITE setName NOTIFY nameChanged )
Q_PROPERTY(Tomahawk::DynamicControl* mainControl READ mainControl) Q_PROPERTY( bool configured READ configured NOTIFY configuredChanged )
Q_PROPERTY( Tomahawk::DynamicControl* mainControl READ mainControl )
public: public:
EchonestStation( PlayableProxyModel *model, geninterface_ptr generator, QObject *parent = 0); EchonestStation( PlayableProxyModel *model, geninterface_ptr generator, QObject *parent = 0);
QString name() const;
void setName( const QString &name );
Tomahawk::DynamicControl* mainControl(); Tomahawk::DynamicControl* mainControl();
bool configured(); bool configured();
@@ -24,9 +28,11 @@ public slots:
void setMainControl(const QString &type); void setMainControl(const QString &type);
signals: signals:
void nameChanged();
void configuredChanged(); void configuredChanged();
private: private:
QString m_name;
PlayableProxyModel *m_model; PlayableProxyModel *m_model;
geninterface_ptr m_generator; geninterface_ptr m_generator;
}; };

View File

@@ -56,6 +56,7 @@ DynamicQmlWidget::DynamicQmlWidget( const dynplaylist_ptr& playlist, QWidget* pa
qmlRegisterUncreatableType<DynamicControl>("tomahawk", 1, 0, "DynamicControl", "use generator.createControl() isntead"); qmlRegisterUncreatableType<DynamicControl>("tomahawk", 1, 0, "DynamicControl", "use generator.createControl() isntead");
qmlRegisterUncreatableType<EchonestControl>("tomahawk", 1, 0, "EchonestControl", "use Generator.createControl() instead"); qmlRegisterUncreatableType<EchonestControl>("tomahawk", 1, 0, "EchonestControl", "use Generator.createControl() instead");
qmlRegisterUncreatableType<GeneratorInterface>("tomahawk", 1, 0, "Generator", "you cannot create it on your own - should be set in context"); qmlRegisterUncreatableType<GeneratorInterface>("tomahawk", 1, 0, "Generator", "you cannot create it on your own - should be set in context");
qmlRegisterUncreatableType<PlayableItem>("tomahawk", 1, 0, "PlayableItem", "you cannot create it on your own - they will appear in the model");
QStringList generatorControls; QStringList generatorControls;
@@ -66,7 +67,7 @@ DynamicQmlWidget::DynamicQmlWidget( const dynplaylist_ptr& playlist, QWidget* pa
ControlModel *controls = new ControlModel(m_playlist->generator(), this); ControlModel *controls = new ControlModel(m_playlist->generator(), this);
EchonestStation *station = new EchonestStation(m_proxyModel, m_playlist->generator(), this); EchonestStation *station = new EchonestStation( m_proxyModel, m_playlist->generator(), this);
rootContext()->setContextProperty( "echonestStation", station); rootContext()->setContextProperty( "echonestStation", station);
rootContext()->setContextProperty( "controlModel", controls ); rootContext()->setContextProperty( "controlModel", controls );
rootContext()->setContextProperty( "dynamicModel", m_proxyModel ); rootContext()->setContextProperty( "dynamicModel", m_proxyModel );

View File

@@ -2,6 +2,7 @@
#include "PlayableItem.h" #include "PlayableItem.h"
#include "playlist/PlayableProxyModel.h" #include "playlist/PlayableProxyModel.h"
#include "Query.h" #include "Query.h"
#include "Album.h"
#include <QDeclarativeImageProvider> #include <QDeclarativeImageProvider>
#include <QModelIndex> #include <QModelIndex>
@@ -30,13 +31,18 @@ QPixmap DeclarativeCoverArtProvider::requestPixmap(const QString &id, QSize *siz
if( size ) if( size )
*size = QSize( width, height ); *size = QSize( width, height );
PlayableItem *item = m_model->itemFromIndex( id.toInt() ); // PlayableItem *item = m_model->itemFromIndex( id.toInt() );
if( item ) { // if( item ) {
qDebug() << "item:" << item; // qDebug() << "item:" << item;
qDebug() << "item2:" << item->artistName() << item->name(); // qDebug() << "item2:" << item->artistName() << item->name();
if ( !item->query().isNull() ) { // if ( !item->query().isNull() ) {
return item->query()->displayQuery()->cover( *size ); // return item->query()->displayQuery()->cover( *size );
} // }
// }
album_ptr album = Album::getByUniqueId(id);
if ( !album.isNull() ) {
return album->cover(requestedSize);
} }
// TODO: create default cover art image // TODO: create default cover art image