Sort album covers by image size. Fixes issue 2048

This commit is contained in:
David Sansome 2011-07-26 12:17:28 +01:00
parent 3eb9aee989
commit 5c90404915
7 changed files with 102 additions and 4 deletions

View File

@ -73,6 +73,7 @@ set(SOURCES
core/gnomeglobalshortcutbackend.cpp
core/logging.cpp
core/mergedproxymodel.cpp
core/multisortfilterproxy.cpp
core/musicstorage.cpp
core/network.cpp
core/networkproxyfactory.cpp

View File

@ -0,0 +1,65 @@
#include "logging.h"
#include "multisortfilterproxy.h"
#include <QDate>
#include <QDateTime>
#include <QTime>
MultiSortFilterProxy::MultiSortFilterProxy(QObject* parent)
: QSortFilterProxyModel(parent)
{
}
void MultiSortFilterProxy::AddSortSpec(int role, Qt::SortOrder order) {
sorting_ << SortSpec(role, order);
}
bool MultiSortFilterProxy::lessThan(const QModelIndex& left,
const QModelIndex& right) const {
foreach (const SortSpec& spec, sorting_) {
const int ret = compare(left.data(spec.first), right.data(spec.first));
if (ret < 0) {
return spec.second == Qt::AscendingOrder;
} else if (ret > 0) {
return spec.second != Qt::AscendingOrder;
}
}
return left.row() < right.row();
}
int MultiSortFilterProxy::compare(const QVariant& left, const QVariant& right) const {
// Copied from the QSortFilterProxyModel::lessThan implementation, but returns
// -1, 0 or 1 instead of true or false.
#define docompare(left, right) \
if (left < right) return -1; \
if (left > right) return 1; \
return 0;
switch (left.userType()) {
case QVariant::Invalid:
return (right.type() != QVariant::Invalid) ? -1 : 0;
case QVariant::Int: docompare(left.toInt(), right.toInt());
case QVariant::UInt: docompare(left.toUInt(), right.toUInt());
case QVariant::LongLong: docompare(left.toLongLong(), right.toLongLong());
case QVariant::ULongLong: docompare(left.toULongLong(), right.toULongLong());
case QMetaType::Float: docompare(left.toFloat(), right.toFloat());
case QVariant::Double: docompare(left.toDouble(), right.toDouble());
case QVariant::Char: docompare(left.toChar(), right.toChar());
case QVariant::Date: docompare(left.toDate(), right.toDate());
case QVariant::Time: docompare(left.toTime(), right.toTime());
case QVariant::DateTime: docompare(left.toDateTime(), right.toDateTime());
case QVariant::String:
default:
if (isSortLocaleAware())
return left.toString().localeAwareCompare(right.toString());
else
return left.toString().compare(right.toString(), sortCaseSensitivity());
}
#undef docompare
return 0;
}

View File

@ -0,0 +1,22 @@
#ifndef MULTISORTFILTERPROXY_H
#define MULTISORTFILTERPROXY_H
#include <QSortFilterProxyModel>
class MultiSortFilterProxy : public QSortFilterProxyModel {
public:
MultiSortFilterProxy(QObject* parent = NULL);
void AddSortSpec(int role, Qt::SortOrder order = Qt::AscendingOrder);
protected:
bool lessThan(const QModelIndex& left, const QModelIndex& right) const;
private:
int compare(const QVariant& left, const QVariant& right) const;
typedef QPair<int, Qt::SortOrder> SortSpec;
QList<SortSpec> sorting_;
};
#endif // MULTISORTFILTERPROXY_H

View File

@ -42,6 +42,7 @@ AlbumCoverSearcher::AlbumCoverSearcher(const QIcon& no_cover_icon, QWidget* pare
ui_->busy->hide();
ui_->covers->set_header_text(tr("Covers from %1"));
ui_->covers->AddSortSpec(Role_ImageDimensions, Qt::DescendingOrder);
ui_->covers->setModel(model_);
loader_->Start(true);
@ -162,6 +163,7 @@ void AlbumCoverSearcher::ImageLoaded(quint64 id, const QImage& image) {
QStandardItem* item = cover_loading_tasks_.take(id);
item->setData(true, Role_ImageFetchFinished);
item->setData(image.width() * image.height(), Role_ImageDimensions);
item->setIcon(icon);
item->setToolTip(item->text() + " (" + QString::number(image.width()) + "x" +
QString::number(image.height()) + ")");

View File

@ -46,6 +46,7 @@ public:
Role_ImageURL = Qt::UserRole + 1,
Role_ImageRequestId,
Role_ImageFetchFinished,
Role_ImageDimensions,
};
void Init(AlbumCoverFetcher* fetcher);

View File

@ -16,6 +16,7 @@
*/
#include "groupediconview.h"
#include "core/multisortfilterproxy.h"
#include <QPainter>
#include <QPaintEvent>
@ -29,7 +30,7 @@ const int GroupedIconView::kBarMarginTop = 3;
GroupedIconView::GroupedIconView(QWidget* parent)
: QListView(parent),
proxy_model_(new QSortFilterProxyModel(this)),
proxy_model_(new MultiSortFilterProxy(this)),
default_header_height_(fontMetrics().height() +
kBarMarginTop + kBarThickness),
header_spacing_(10),
@ -43,12 +44,16 @@ GroupedIconView::GroupedIconView(QWidget* parent)
setWordWrap(true);
setDragEnabled(false);
proxy_model_->setSortRole(Role_Group);
proxy_model_->AddSortSpec(Role_Group);
proxy_model_->setDynamicSortFilter(true);
connect(proxy_model_, SIGNAL(modelReset()), SLOT(LayoutItems()));
}
void GroupedIconView::AddSortSpec(int role, Qt::SortOrder order) {
proxy_model_->AddSortSpec(role, order);
}
void GroupedIconView::setModel(QAbstractItemModel* model) {
proxy_model_->setSourceModel(model);
proxy_model_->sort(0);

View File

@ -20,7 +20,7 @@
#include <QListView>
class QSortFilterProxyModel;
class MultiSortFilterProxy;
class GroupedIconView : public QListView {
@ -45,6 +45,8 @@ public:
Role_Group = 1158300,
};
void AddSortSpec(int role, Qt::SortOrder order = Qt::AscendingOrder);
int header_spacing() const { return header_spacing_; }
int header_indent() const { return header_indent_; }
int item_indent() const { return item_indent_; }
@ -95,7 +97,7 @@ private:
// Returns the index of the item above (d=-1) or below (d=+1) the given item.
int IndexAboveOrBelow(int index, int d) const;
QSortFilterProxyModel* proxy_model_;
MultiSortFilterProxy* proxy_model_;
QVector<QRect> visual_rects_;
QVector<Header> headers_;