mirror of
https://github.com/clementine-player/Clementine
synced 2025-01-30 19:15:08 +01:00
Add a Mood column to the playlist
This commit is contained in:
parent
f1dee1171b
commit
19c3e1d5ec
@ -199,6 +199,7 @@ set(SOURCES
|
||||
library/sqlrow.cpp
|
||||
|
||||
moodbar/moodbarcontroller.cpp
|
||||
moodbar/moodbaritemdelegate.cpp
|
||||
moodbar/moodbarloader.cpp
|
||||
moodbar/moodbarpipeline.cpp
|
||||
moodbar/moodbarproxystyle.cpp
|
||||
@ -466,6 +467,7 @@ set(HEADERS
|
||||
library/librarywatcher.h
|
||||
|
||||
moodbar/moodbarcontroller.h
|
||||
moodbar/moodbaritemdelegate.h
|
||||
moodbar/moodbarloader.h
|
||||
moodbar/moodbarpipeline.h
|
||||
moodbar/moodbarproxystyle.h
|
||||
|
108
src/moodbar/moodbaritemdelegate.cpp
Normal file
108
src/moodbar/moodbaritemdelegate.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
/* This file is part of Clementine.
|
||||
Copyright 2012, David Sansome <me@davidsansome.com>
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "moodbaritemdelegate.h"
|
||||
#include "moodbarloader.h"
|
||||
#include "moodbarpipeline.h"
|
||||
#include "moodbarrenderer.h"
|
||||
#include "core/application.h"
|
||||
#include "core/closure.h"
|
||||
#include "playlist/playlist.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QPainter>
|
||||
|
||||
MoodbarItemDelegate::MoodbarItemDelegate(Application* app, QObject* parent)
|
||||
: QItemDelegate(parent),
|
||||
app_(app)
|
||||
{
|
||||
}
|
||||
|
||||
void MoodbarItemDelegate::paint(
|
||||
QPainter* painter, const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const {
|
||||
QPixmap pixmap = const_cast<MoodbarItemDelegate*>(this)->PixmapForIndex(
|
||||
index, option.rect.size(), option.palette);
|
||||
if (!pixmap.isNull()) {
|
||||
painter->drawPixmap(option.rect, pixmap);
|
||||
}
|
||||
}
|
||||
|
||||
QPixmap MoodbarItemDelegate::PixmapForIndex(
|
||||
const QModelIndex& index, const QSize& size, const QPalette& palette) {
|
||||
// Do we have a pixmap already that's the right size?
|
||||
QPixmap pixmap = index.data(Playlist::Role_MoodbarPixmap).value<QPixmap>();
|
||||
if (!pixmap.isNull() && pixmap.size() == size) {
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
// Do we have colors?
|
||||
ColorVector colors = index.data(Playlist::Role_MoodbarColors).value<ColorVector>();
|
||||
if (colors.isEmpty()) {
|
||||
// Nope - we need to load a mood file for this song and generate some colors
|
||||
// from it.
|
||||
const QUrl url(index.sibling(index.row(), Playlist::Column_Filename).data().toUrl());
|
||||
|
||||
QByteArray data;
|
||||
MoodbarPipeline* pipeline = NULL;
|
||||
switch (app_->moodbar_loader()->Load(url, &data, &pipeline)) {
|
||||
case MoodbarLoader::CannotLoad:
|
||||
return QPixmap();
|
||||
|
||||
case MoodbarLoader::Loaded:
|
||||
// Aww yeah
|
||||
colors = MoodbarRenderer::Colors(data, MoodbarRenderer::Style_Normal, palette);
|
||||
break;
|
||||
|
||||
case MoodbarLoader::WillLoadAsync:
|
||||
// Maybe in a little while.
|
||||
qLog(Debug) << "Loading" << pipeline;
|
||||
NewClosure(pipeline, SIGNAL(Finished(bool)),
|
||||
this, SLOT(RequestFinished(MoodbarPipeline*,QModelIndex,QUrl)),
|
||||
pipeline, index, url);
|
||||
return QPixmap();
|
||||
}
|
||||
}
|
||||
|
||||
// We've got colors, let's make a pixmap.
|
||||
pixmap = QPixmap(size);
|
||||
QPainter p(&pixmap);
|
||||
MoodbarRenderer::Render(colors, &p, QRect(QPoint(0, 0), size));
|
||||
p.end();
|
||||
|
||||
// Set these on the item so we don't have to look them up again.
|
||||
QAbstractItemModel* model = const_cast<QAbstractItemModel*>(index.model());
|
||||
model->setData(index, QVariant::fromValue(colors), Playlist::Role_MoodbarColors);
|
||||
model->setData(index, pixmap, Playlist::Role_MoodbarPixmap);
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
void MoodbarItemDelegate::RequestFinished(
|
||||
MoodbarPipeline* pipeline, const QModelIndex& index, const QUrl& url) {
|
||||
qLog(Debug) << "Finished" << pipeline;
|
||||
// Is this index still valid, and does it still point to the same URL?
|
||||
if (!index.isValid() || index.sibling(index.row(), Playlist::Column_Filename).data().toUrl() != url) {
|
||||
return;
|
||||
}
|
||||
|
||||
// It's good. Create the color list and set them on the item.
|
||||
ColorVector colors = MoodbarRenderer::Colors(
|
||||
pipeline->data(), MoodbarRenderer::Style_Normal, qApp->palette());
|
||||
QAbstractItemModel* model = const_cast<QAbstractItemModel*>(index.model());
|
||||
model->setData(index, QVariant::fromValue(colors), Playlist::Role_MoodbarColors);
|
||||
}
|
49
src/moodbar/moodbaritemdelegate.h
Normal file
49
src/moodbar/moodbaritemdelegate.h
Normal file
@ -0,0 +1,49 @@
|
||||
/* This file is part of Clementine.
|
||||
Copyright 2012, David Sansome <me@davidsansome.com>
|
||||
|
||||
Clementine is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef MOODBARITEMDELEGATE_H
|
||||
#define MOODBARITEMDELEGATE_H
|
||||
|
||||
#include <QItemDelegate>
|
||||
|
||||
class Application;
|
||||
class MoodbarPipeline;
|
||||
|
||||
class QModelIndex;
|
||||
|
||||
class MoodbarItemDelegate : public QItemDelegate {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MoodbarItemDelegate(Application* app, QObject* parent = 0);
|
||||
|
||||
void paint(QPainter* painter, const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const;
|
||||
|
||||
private slots:
|
||||
void RequestFinished(MoodbarPipeline* pipeline, const QModelIndex& index,
|
||||
const QUrl& url);
|
||||
|
||||
private:
|
||||
QPixmap PixmapForIndex(const QModelIndex& index, const QSize& size,
|
||||
const QPalette& palette);
|
||||
|
||||
private:
|
||||
Application* app_;
|
||||
};
|
||||
|
||||
#endif // MOODBARITEMDELEGATE_H
|
@ -23,6 +23,8 @@
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QNetworkDiskCache>
|
||||
#include <QTimer>
|
||||
#include <QThread>
|
||||
#include <QUrl>
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
@ -30,7 +32,8 @@
|
||||
MoodbarLoader::MoodbarLoader(QObject* parent)
|
||||
: QObject(parent),
|
||||
cache_(new QNetworkDiskCache(this)),
|
||||
save_alongside_originals_(true)
|
||||
kMaxActiveRequests(QThread::idealThreadCount()),
|
||||
save_alongside_originals_(false)
|
||||
{
|
||||
cache_->setCacheDirectory(Utilities::GetConfigPath(Utilities::Path_MoodbarCache));
|
||||
cache_->setMaximumCacheSize(1024 * 1024); // 1MB - enough for 333 moodbars
|
||||
@ -86,22 +89,35 @@ MoodbarLoader::Result MoodbarLoader::Load(
|
||||
|
||||
// There was no existing file, analyze the audio file and create one.
|
||||
MoodbarPipeline* pipeline = new MoodbarPipeline(filename);
|
||||
if (!pipeline->Start()) {
|
||||
delete pipeline;
|
||||
return CannotLoad;
|
||||
}
|
||||
|
||||
qLog(Info) << "Creating moodbar data for" << filename;
|
||||
|
||||
active_requests_[filename] = pipeline;
|
||||
NewClosure(pipeline, SIGNAL(Finished(bool)),
|
||||
this, SLOT(RequestFinished(MoodbarPipeline*,QUrl)),
|
||||
pipeline, url);
|
||||
|
||||
|
||||
active_requests_[url] = pipeline;
|
||||
|
||||
if (active_requests_.count() > kMaxActiveRequests) {
|
||||
// Just queue this request now, start it later when another request
|
||||
// finishes.
|
||||
queued_requests_ << url;
|
||||
} else if (!StartQueuedRequest(url)) {
|
||||
return CannotLoad;
|
||||
}
|
||||
|
||||
*async_pipeline = pipeline;
|
||||
return WillLoadAsync;
|
||||
}
|
||||
|
||||
bool MoodbarLoader::StartQueuedRequest(const QUrl& url) {
|
||||
if (!active_requests_[url]->Start()) {
|
||||
delete active_requests_.take(url);
|
||||
return false;
|
||||
}
|
||||
|
||||
qLog(Info) << "Creating moodbar data for" << url.toLocalFile();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MoodbarLoader::RequestFinished(MoodbarPipeline* request, const QUrl& url) {
|
||||
if (request->success()) {
|
||||
qLog(Info) << "Moodbar data generated successfully for" << url.toLocalFile();
|
||||
@ -125,8 +141,14 @@ void MoodbarLoader::RequestFinished(MoodbarPipeline* request, const QUrl& url) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
qLog(Debug) << "Deleting" << request;
|
||||
|
||||
// Remove the request from the active list and delete it
|
||||
active_requests_.take(url);
|
||||
request->deleteLater();
|
||||
QTimer::singleShot(10, request, SLOT(deleteLater()));
|
||||
|
||||
if (!queued_requests_.isEmpty()) {
|
||||
StartQueuedRequest(queued_requests_.takeFirst());
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
#include <QPair>
|
||||
|
||||
class QNetworkDiskCache;
|
||||
class QUrl;
|
||||
@ -53,11 +54,15 @@ private slots:
|
||||
|
||||
private:
|
||||
static QStringList MoodFilenames(const QString& song_filename);
|
||||
bool StartQueuedRequest(const QUrl& url);
|
||||
|
||||
private:
|
||||
QNetworkDiskCache* cache_;
|
||||
|
||||
const int kMaxActiveRequests;
|
||||
|
||||
QMap<QUrl, MoodbarPipeline*> active_requests_;
|
||||
QList<QUrl> queued_requests_;
|
||||
|
||||
bool save_alongside_originals_;
|
||||
};
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "core/logging.h"
|
||||
|
||||
bool MoodbarPipeline::sIsAvailable = false;
|
||||
QMutex MoodbarPipeline::sFftwMutex;
|
||||
|
||||
MoodbarPipeline::MoodbarPipeline(const QString& local_filename)
|
||||
: QObject(NULL),
|
||||
@ -31,6 +32,7 @@ MoodbarPipeline::MoodbarPipeline(const QString& local_filename)
|
||||
}
|
||||
|
||||
MoodbarPipeline::~MoodbarPipeline() {
|
||||
qLog(Debug) << "Actually deleting" << this;
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
@ -84,6 +86,8 @@ bool MoodbarPipeline::Start() {
|
||||
pipeline_ = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
QMutexLocker l(&sFftwMutex);
|
||||
|
||||
// Join them together
|
||||
gst_element_link(filesrc, decodebin);
|
||||
@ -188,14 +192,13 @@ GstBusSyncReply MoodbarPipeline::BusCallbackSync(GstBus*, GstMessage* msg, gpoin
|
||||
void MoodbarPipeline::Stop(bool success) {
|
||||
success_ = success;
|
||||
emit Finished(success);
|
||||
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
void MoodbarPipeline::Cleanup() {
|
||||
if (pipeline_) {
|
||||
gst_bus_set_sync_handler(gst_pipeline_get_bus(GST_PIPELINE(pipeline_)), NULL, NULL);
|
||||
g_source_remove(bus_callback_id_);
|
||||
gst_element_set_state(pipeline_, GST_STATE_NULL);
|
||||
gst_object_unref(pipeline_);
|
||||
pipeline_ = NULL;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define MOODBARPIPELINE_H
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QMutex>
|
||||
#include <QObject>
|
||||
|
||||
#include <gst/gst.h>
|
||||
@ -56,6 +57,7 @@ private:
|
||||
|
||||
private:
|
||||
static bool sIsAvailable;
|
||||
static QMutex sFftwMutex;
|
||||
|
||||
QString local_filename_;
|
||||
GstElement* pipeline_;
|
||||
|
@ -34,7 +34,7 @@ MoodbarProxyStyle::MoodbarProxyStyle(QSlider* slider)
|
||||
: QProxyStyle(slider->style()),
|
||||
slider_(slider),
|
||||
enabled_(true),
|
||||
moodbar_style_(MoodbarRenderer::Style_SystemDefault),
|
||||
moodbar_style_(MoodbarRenderer::Style_Normal),
|
||||
state_(MoodbarOff),
|
||||
fade_timeline_(new QTimeLine(1000, this)),
|
||||
moodbar_colors_dirty_(true),
|
||||
@ -238,15 +238,14 @@ void MoodbarProxyStyle::DrawArrow(const QStyleOptionSlider* option,
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
painter->translate(0.5, 0.5);
|
||||
painter->setPen(slider_->palette().color(QPalette::Active, QPalette::Highlight));
|
||||
painter->setPen(Qt::black);
|
||||
painter->setBrush(slider_->palette().brush(QPalette::Active, QPalette::Base));
|
||||
painter->drawPolygon(poly);
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
QPixmap MoodbarProxyStyle::MoodbarPixmap(
|
||||
const MoodbarRenderer::ColorList& colors, const QSize& size,
|
||||
const QPalette& palette) {
|
||||
QPixmap MoodbarProxyStyle::MoodbarPixmap(const ColorVector& colors,
|
||||
const QSize& size, const QPalette& palette) {
|
||||
QRect rect(QPoint(0, 0), size);
|
||||
QRect border_rect(rect);
|
||||
border_rect.adjust(kMarginSize, kMarginSize, -kMarginSize, -kMarginSize);
|
||||
@ -261,7 +260,7 @@ QPixmap MoodbarProxyStyle::MoodbarPixmap(
|
||||
MoodbarRenderer::Render(colors, &p, inner_rect);
|
||||
|
||||
// Draw the border
|
||||
p.setPen(QPen(palette.brush(QPalette::Active, QPalette::Highlight),
|
||||
p.setPen(QPen(Qt::black,
|
||||
kBorderSize, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
|
||||
p.drawRect(border_rect.adjusted(0, 0, -1, -1));
|
||||
|
||||
|
@ -69,7 +69,7 @@ private:
|
||||
void EnsureMoodbarRendered();
|
||||
void DrawArrow(const QStyleOptionSlider* option, QPainter* painter) const;
|
||||
|
||||
static QPixmap MoodbarPixmap(const MoodbarRenderer::ColorList& colors,
|
||||
static QPixmap MoodbarPixmap(const ColorVector& colors,
|
||||
const QSize& size, const QPalette& palette);
|
||||
|
||||
private slots:
|
||||
@ -90,7 +90,7 @@ private:
|
||||
|
||||
bool moodbar_colors_dirty_;
|
||||
bool moodbar_pixmap_dirty_;
|
||||
MoodbarRenderer::ColorList moodbar_colors_;
|
||||
ColorVector moodbar_colors_;
|
||||
QPixmap moodbar_pixmap_;
|
||||
};
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
const int MoodbarRenderer::kNumHues = 12;
|
||||
|
||||
MoodbarRenderer::ColorList MoodbarRenderer::Colors(
|
||||
ColorVector MoodbarRenderer::Colors(
|
||||
const QByteArray& data, MoodbarStyle style, const QPalette& palette) {
|
||||
const int samples = data.size() / 3;
|
||||
|
||||
@ -32,6 +32,7 @@ MoodbarRenderer::ColorList MoodbarRenderer::Colors(
|
||||
case Style_Angry: properties = StyleProperties(samples / 360 * 9, 45, -45, 200, 100); break;
|
||||
case Style_Frozen: properties = StyleProperties(samples / 360 * 1, 140, 160, 50, 100); break;
|
||||
case Style_Happy: properties = StyleProperties(samples / 360 * 2, 0, 359, 150, 250); break;
|
||||
case Style_Normal: properties = StyleProperties(samples / 360 * 3, 0, 359, 100, 100); break;
|
||||
case Style_SystemDefault:
|
||||
default: {
|
||||
const QColor highlight_color(palette.color(QPalette::Active, QPalette::Highlight));
|
||||
@ -52,7 +53,7 @@ MoodbarRenderer::ColorList MoodbarRenderer::Colors(
|
||||
|
||||
memset(hue_distribution, 0, sizeof(hue_distribution));
|
||||
|
||||
ColorList colors;
|
||||
ColorVector colors;
|
||||
|
||||
// Read the colors, keeping track of some histograms
|
||||
for (int i=0; i<samples; ++i) {
|
||||
@ -81,7 +82,7 @@ MoodbarRenderer::ColorList MoodbarRenderer::Colors(
|
||||
|
||||
// Now huedist is a hue mapper: huedist[h] is the new hue value
|
||||
// for a bar with hue h
|
||||
for (ColorList::iterator it = colors.begin() ; it != colors.end() ; ++it) {
|
||||
for (ColorVector::iterator it = colors.begin() ; it != colors.end() ; ++it) {
|
||||
const int hue = qMax(0, it->hue());
|
||||
|
||||
*it = QColor::fromHsv(
|
||||
@ -93,9 +94,9 @@ MoodbarRenderer::ColorList MoodbarRenderer::Colors(
|
||||
return colors;
|
||||
}
|
||||
|
||||
void MoodbarRenderer::Render(const ColorList& colors, QPainter* p, const QRect& rect) {
|
||||
void MoodbarRenderer::Render(const ColorVector& colors, QPainter* p, const QRect& rect) {
|
||||
// Sample the colors and map them to screen pixels.
|
||||
ColorList screen_colors;
|
||||
ColorVector screen_colors;
|
||||
for (int x=0; x<rect.width(); ++x) {
|
||||
int r = 0;
|
||||
int g = 0;
|
||||
|
@ -20,26 +20,27 @@
|
||||
|
||||
#include <QColor>
|
||||
#include <QPixmap>
|
||||
#include <QMetaType>
|
||||
#include <QVector>
|
||||
|
||||
class QPalette;
|
||||
typedef QVector<QColor> ColorVector;
|
||||
|
||||
class MoodbarRenderer {
|
||||
public:
|
||||
typedef QVector<QColor> ColorList;
|
||||
|
||||
enum MoodbarStyle {
|
||||
Style_Angry,
|
||||
Style_Frozen,
|
||||
Style_Happy,
|
||||
Style_Normal,
|
||||
Style_SystemDefault
|
||||
};
|
||||
|
||||
static const int kNumHues;
|
||||
|
||||
static ColorList Colors(const QByteArray& data, MoodbarStyle style,
|
||||
const QPalette& palette);
|
||||
static void Render(const ColorList& colors, QPainter* p, const QRect& rect);
|
||||
static ColorVector Colors(const QByteArray& data, MoodbarStyle style,
|
||||
const QPalette& palette);
|
||||
static void Render(const ColorVector& colors, QPainter* p, const QRect& rect);
|
||||
|
||||
private:
|
||||
MoodbarRenderer();
|
||||
@ -58,4 +59,6 @@ private:
|
||||
};
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(QVector<QColor>)
|
||||
|
||||
#endif // MOODBARRENDERER_H
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "library/librarybackend.h"
|
||||
#include "library/librarymodel.h"
|
||||
#include "library/libraryplaylistitem.h"
|
||||
#include "moodbar/moodbarrenderer.h"
|
||||
#include "smartplaylists/generator.h"
|
||||
#include "smartplaylists/generatorinserter.h"
|
||||
#include "smartplaylists/generatormimedata.h"
|
||||
@ -243,6 +244,12 @@ QVariant Playlist::data(const QModelIndex& index, int role) const {
|
||||
items_[index.row()]->IsLocalLibraryItem() &&
|
||||
items_[index.row()]->Metadata().id() != -1;
|
||||
|
||||
case Role_MoodbarColors:
|
||||
return QVariant::fromValue(items_[index.row()]->MoodbarColors());
|
||||
|
||||
case Role_MoodbarPixmap:
|
||||
return items_[index.row()]->MoodbarPixmap();
|
||||
|
||||
case Qt::EditRole:
|
||||
case Qt::ToolTipRole:
|
||||
case Qt::DisplayRole: {
|
||||
@ -309,9 +316,20 @@ QVariant Playlist::data(const QModelIndex& index, int role) const {
|
||||
}
|
||||
}
|
||||
|
||||
bool Playlist::setData(const QModelIndex &index, const QVariant &value, int) {
|
||||
bool Playlist::setData(const QModelIndex& index, const QVariant& value, int role) {
|
||||
int row = index.row();
|
||||
Song song = item_at(row)->Metadata();
|
||||
PlaylistItemPtr item = item_at(row);
|
||||
Song song = item->Metadata();
|
||||
|
||||
if (role == Role_MoodbarColors) {
|
||||
item->SetMoodbarColors(value.value<QVector<QColor> >());
|
||||
emit dataChanged(index.sibling(index.row(), Column_Mood),
|
||||
index.sibling(index.row(), Column_Mood));
|
||||
return true;
|
||||
} else if (role == Role_MoodbarPixmap) {
|
||||
item->SetMoodbarPixmap(value.value<QPixmap>());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (index.data() == value)
|
||||
return false;
|
||||
@ -1152,6 +1170,7 @@ QString Playlist::column_name(Column column) {
|
||||
|
||||
case Column_Comment: return tr("Comment");
|
||||
case Column_Source: return tr("Source");
|
||||
case Column_Mood: return tr("Mood");
|
||||
default: return QString();
|
||||
}
|
||||
return "";
|
||||
|
@ -111,6 +111,7 @@ class Playlist : public QAbstractListModel {
|
||||
Column_Comment,
|
||||
|
||||
Column_Source,
|
||||
Column_Mood,
|
||||
|
||||
ColumnCount
|
||||
};
|
||||
@ -121,6 +122,8 @@ class Playlist : public QAbstractListModel {
|
||||
Role_StopAfter,
|
||||
Role_QueuePosition,
|
||||
Role_CanSetRating,
|
||||
Role_MoodbarColors,
|
||||
Role_MoodbarPixmap,
|
||||
};
|
||||
|
||||
enum LastFMStatus {
|
||||
|
@ -32,6 +32,10 @@
|
||||
#include <QtDebug>
|
||||
|
||||
|
||||
PlaylistItem::~PlaylistItem() {
|
||||
delete moodbar_pixmap_;
|
||||
}
|
||||
|
||||
PlaylistItem* PlaylistItem::NewFromType(const QString& type) {
|
||||
if (type == "Library")
|
||||
return new LibraryPlaylistItem(type);
|
||||
@ -120,3 +124,17 @@ QColor PlaylistItem::GetCurrentForegroundColor() const {
|
||||
bool PlaylistItem::HasCurrentForegroundColor() const {
|
||||
return !foreground_colors_.isEmpty();
|
||||
}
|
||||
|
||||
QPixmap PlaylistItem::MoodbarPixmap() const {
|
||||
if (!moodbar_pixmap_) {
|
||||
return QPixmap();
|
||||
}
|
||||
return *moodbar_pixmap_;
|
||||
}
|
||||
|
||||
void PlaylistItem::SetMoodbarPixmap(const QPixmap& pixmap) {
|
||||
if (!moodbar_pixmap_) {
|
||||
moodbar_pixmap_ = new QPixmap;
|
||||
}
|
||||
*moodbar_pixmap_ = pixmap;
|
||||
}
|
||||
|
@ -33,8 +33,9 @@ class SqlRow;
|
||||
class PlaylistItem : public boost::enable_shared_from_this<PlaylistItem> {
|
||||
public:
|
||||
PlaylistItem(const QString& type)
|
||||
: type_(type) {}
|
||||
virtual ~PlaylistItem() {}
|
||||
: type_(type),
|
||||
moodbar_pixmap_(NULL) {}
|
||||
virtual ~PlaylistItem();
|
||||
|
||||
static PlaylistItem* NewFromType(const QString& type);
|
||||
static PlaylistItem* NewFromSongsTable(const QString& table, const Song& song);
|
||||
@ -92,6 +93,12 @@ class PlaylistItem : public boost::enable_shared_from_this<PlaylistItem> {
|
||||
// before actually using it.
|
||||
virtual bool IsLocalLibraryItem() const { return false; }
|
||||
|
||||
// Moodbar accessors. These are lazy-loaded by MoodbarItemDelegate.
|
||||
const QVector<QColor>& MoodbarColors() const { return moodbar_colors_; }
|
||||
void SetMoodbarColors(const QVector<QColor>& colors) { moodbar_colors_ = colors; }
|
||||
QPixmap MoodbarPixmap() const;
|
||||
void SetMoodbarPixmap(const QPixmap& pixmap);
|
||||
|
||||
protected:
|
||||
enum DatabaseColumn {
|
||||
Column_LibraryId,
|
||||
@ -108,6 +115,10 @@ class PlaylistItem : public boost::enable_shared_from_this<PlaylistItem> {
|
||||
|
||||
QMap<short, QColor> background_colors_;
|
||||
QMap<short, QColor> foreground_colors_;
|
||||
|
||||
private:
|
||||
QVector<QColor> moodbar_colors_;
|
||||
QPixmap* moodbar_pixmap_;
|
||||
};
|
||||
typedef boost::shared_ptr<PlaylistItem> PlaylistItemPtr;
|
||||
typedef QList<PlaylistItemPtr> PlaylistItemList;
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "core/logging.h"
|
||||
#include "core/player.h"
|
||||
#include "covers/currentartloader.h"
|
||||
#include "moodbar/moodbaritemdelegate.h"
|
||||
|
||||
#include <QCleanlooksStyle>
|
||||
#include <QClipboard>
|
||||
@ -198,6 +199,7 @@ void PlaylistView::SetItemDelegates(LibraryBackend* backend) {
|
||||
setItemDelegateForColumn(Playlist::Column_Filename, new NativeSeparatorsDelegate(this));
|
||||
setItemDelegateForColumn(Playlist::Column_Rating, rating_delegate_);
|
||||
setItemDelegateForColumn(Playlist::Column_LastPlayed, new LastPlayedItemDelegate(this));
|
||||
setItemDelegateForColumn(Playlist::Column_Mood, new MoodbarItemDelegate(app_, this));
|
||||
|
||||
if (app_ && app_->player()) {
|
||||
setItemDelegateForColumn(Playlist::Column_Source, new SongSourceDelegate(this, app_->player()));
|
||||
|
Loading…
x
Reference in New Issue
Block a user