Auto-expand tree items and lazy load album cover art
This commit is contained in:
parent
9c36cfa199
commit
41fab25569
@ -138,6 +138,7 @@ set(SOURCES
|
||||
|
||||
globalsearch/digitallyimportedsearchprovider.cpp
|
||||
globalsearch/globalsearch.cpp
|
||||
globalsearch/globalsearchitemdelegate.cpp
|
||||
globalsearch/globalsearchsettingspage.cpp
|
||||
globalsearch/globalsearchsortmodel.cpp
|
||||
globalsearch/globalsearchview.cpp
|
||||
|
34
src/globalsearch/globalsearchitemdelegate.cpp
Normal file
34
src/globalsearch/globalsearchitemdelegate.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
/* 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 "globalsearchitemdelegate.h"
|
||||
#include "globalsearchview.h"
|
||||
|
||||
GlobalSearchItemDelegate::GlobalSearchItemDelegate(GlobalSearchView* view)
|
||||
: LibraryItemDelegate(view),
|
||||
view_(view)
|
||||
{
|
||||
}
|
||||
|
||||
void GlobalSearchItemDelegate::paint(
|
||||
QPainter* painter, const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const {
|
||||
// Tell the view we painted this item so it can lazy load some art.
|
||||
const_cast<GlobalSearchView*>(view_)->LazyLoadArt(index);
|
||||
|
||||
LibraryItemDelegate::paint(painter, option, index);
|
||||
}
|
36
src/globalsearch/globalsearchitemdelegate.h
Normal file
36
src/globalsearch/globalsearchitemdelegate.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* 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 GLOBALSEARCHITEMDELEGATE_H
|
||||
#define GLOBALSEARCHITEMDELEGATE_H
|
||||
|
||||
#include "library/libraryview.h"
|
||||
|
||||
class GlobalSearchView;
|
||||
|
||||
class GlobalSearchItemDelegate : public LibraryItemDelegate {
|
||||
public:
|
||||
GlobalSearchItemDelegate(GlobalSearchView* view);
|
||||
|
||||
void paint(QPainter* painter, const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const;
|
||||
|
||||
private:
|
||||
GlobalSearchView* view_;
|
||||
};
|
||||
|
||||
#endif // GLOBALSEARCHITEMDELEGATE_H
|
@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "globalsearch.h"
|
||||
#include "globalsearchitemdelegate.h"
|
||||
#include "globalsearchsortmodel.h"
|
||||
#include "globalsearchview.h"
|
||||
#include "searchprovider.h"
|
||||
@ -24,7 +25,6 @@
|
||||
#include "core/logging.h"
|
||||
#include "core/mimedata.h"
|
||||
#include "library/librarymodel.h"
|
||||
#include "library/libraryview.h"
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QStandardItem>
|
||||
@ -44,18 +44,24 @@ GlobalSearchView::GlobalSearchView(Application* app, QWidget* parent)
|
||||
front_proxy_(new GlobalSearchSortModel(this)),
|
||||
back_proxy_(new GlobalSearchSortModel(this)),
|
||||
current_proxy_(front_proxy_),
|
||||
swap_models_timer_(new QTimer(this))
|
||||
swap_models_timer_(new QTimer(this)),
|
||||
artist_icon_(":/icons/22x22/x-clementine-artist.png"),
|
||||
album_icon_(":/icons/22x22/x-clementine-album.png")
|
||||
{
|
||||
ui_->setupUi(this);
|
||||
|
||||
connect(ui_->search, SIGNAL(textChanged(QString)), SLOT(TextEdited(QString)));
|
||||
|
||||
ui_->results->setItemDelegate(new LibraryItemDelegate(this));
|
||||
ui_->results->setItemDelegate(new GlobalSearchItemDelegate(this));
|
||||
|
||||
group_by_[0] = LibraryModel::GroupBy_Artist;
|
||||
group_by_[1] = LibraryModel::GroupBy_Album;
|
||||
group_by_[2] = LibraryModel::GroupBy_None;
|
||||
|
||||
no_cover_icon_ = QPixmap(":nocover.png").scaled(
|
||||
LibraryModel::kPrettyCoverSize, LibraryModel::kPrettyCoverSize,
|
||||
Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
|
||||
// Set up the sorting proxy model
|
||||
front_proxy_->setSourceModel(front_model_);
|
||||
front_proxy_->setDynamicSortFilter(true);
|
||||
@ -164,6 +170,7 @@ QStandardItem* GlobalSearchView::BuildContainers(
|
||||
return parent;
|
||||
}
|
||||
|
||||
QIcon icon;
|
||||
QString display_text;
|
||||
QString sort_text;
|
||||
int year = 0;
|
||||
@ -172,12 +179,14 @@ QStandardItem* GlobalSearchView::BuildContainers(
|
||||
case LibraryModel::GroupBy_Artist:
|
||||
display_text = LibraryModel::TextOrUnknown(s.artist());
|
||||
sort_text = LibraryModel::SortTextForArtist(s.artist());
|
||||
icon = artist_icon_;
|
||||
break;
|
||||
|
||||
case LibraryModel::GroupBy_YearAlbum:
|
||||
year = qMax(0, s.year());
|
||||
display_text = LibraryModel::PrettyYearAlbum(year, s.album());
|
||||
sort_text = LibraryModel::SortTextForYear(year) + s.album();
|
||||
icon = album_icon_;
|
||||
break;
|
||||
|
||||
case LibraryModel::GroupBy_Year:
|
||||
@ -192,6 +201,7 @@ QStandardItem* GlobalSearchView::BuildContainers(
|
||||
case LibraryModel::GroupBy_AlbumArtist: if (display_text.isNull()) display_text = s.effective_albumartist();
|
||||
display_text = LibraryModel::TextOrUnknown(display_text);
|
||||
sort_text = LibraryModel::SortTextForArtist(display_text);
|
||||
icon = album_icon_;
|
||||
break;
|
||||
|
||||
case LibraryModel::GroupBy_FileType:
|
||||
@ -207,7 +217,7 @@ QStandardItem* GlobalSearchView::BuildContainers(
|
||||
key->group_[level] = display_text;
|
||||
QStandardItem* container = containers_[*key];
|
||||
if (!container) {
|
||||
container = new QStandardItem(display_text);
|
||||
container = new QStandardItem(icon, display_text);
|
||||
container->setData(key->provider_index_, Role_ProviderIndex);
|
||||
container->setData(sort_text, LibraryModel::Role_SortText);
|
||||
container->setData(group_by_[level], LibraryModel::Role_ContainerType);
|
||||
@ -237,12 +247,30 @@ void GlobalSearchView::LazyLoadArt(const QModelIndex& proxy_index) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only load art for albums
|
||||
const LibraryModel::GroupBy container_type = LibraryModel::GroupBy(
|
||||
proxy_index.data(LibraryModel::Role_ContainerType).toInt());
|
||||
if (container_type != LibraryModel::GroupBy_Album &&
|
||||
container_type != LibraryModel::GroupBy_AlbumArtist &&
|
||||
container_type != LibraryModel::GroupBy_YearAlbum) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Mark the item as loading art
|
||||
const QModelIndex source_index = front_proxy_->mapToSource(proxy_index);
|
||||
front_model_->itemFromIndex(source_index)->setData(true, Role_LazyLoadingArt);
|
||||
QStandardItem* item = front_model_->itemFromIndex(source_index);
|
||||
item->setData(true, Role_LazyLoadingArt);
|
||||
|
||||
// Walk down the item's children until we find a track
|
||||
while (item->rowCount()) {
|
||||
item = item->child(0);
|
||||
}
|
||||
|
||||
// Get the track's Result
|
||||
const SearchProvider::Result result =
|
||||
source_index.data(Role_Result).value<SearchProvider::Result>();
|
||||
item->data(Role_Result).value<SearchProvider::Result>();
|
||||
|
||||
// Load the art.
|
||||
int id = engine_->LoadArtAsync(result);
|
||||
art_requests_[id] = source_index;
|
||||
}
|
||||
|
@ -106,6 +106,10 @@ private:
|
||||
|
||||
QMap<int, QAction*> track_requests_;
|
||||
QMap<int, QModelIndex> art_requests_;
|
||||
|
||||
QIcon artist_icon_;
|
||||
QIcon album_icon_;
|
||||
QPixmap no_cover_icon_;
|
||||
};
|
||||
|
||||
inline uint qHash(const GlobalSearchView::ContainerKey& key) {
|
||||
|
@ -28,7 +28,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="results">
|
||||
<widget class="AutoExpandingTreeView" name="results">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
@ -48,6 +48,11 @@
|
||||
<extends>QLineEdit</extends>
|
||||
<header>widgets/lineedit.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>AutoExpandingTreeView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>widgets/autoexpandingtreeview.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
@ -71,7 +71,6 @@ LibraryModel::LibraryModel(LibraryBackend* backend, Application* app,
|
||||
total_song_count_(0),
|
||||
artist_icon_(":/icons/22x22/x-clementine-artist.png"),
|
||||
album_icon_(":/icons/22x22/x-clementine-album.png"),
|
||||
no_cover_icon_(":nocover.png"),
|
||||
playlists_dir_icon_(IconLoader::Load("folder-sound")),
|
||||
playlist_icon_(":/icons/22x22/x-clementine-albums.png"),
|
||||
init_task_id_(-1),
|
||||
@ -92,7 +91,7 @@ LibraryModel::LibraryModel(LibraryBackend* backend, Application* app,
|
||||
SIGNAL(ImageLoaded(quint64,QImage)),
|
||||
SLOT(AlbumArtLoaded(quint64,QImage)));
|
||||
|
||||
no_cover_icon_pretty_ = QPixmap(":nocover.png").scaled(
|
||||
no_cover_icon_ = QPixmap(":nocover.png").scaled(
|
||||
kPrettyCoverSize, kPrettyCoverSize,
|
||||
Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
@ -405,7 +404,7 @@ QString LibraryModel::AlbumIconPixmapCacheKey(const QModelIndex& index) const {
|
||||
QVariant LibraryModel::AlbumIcon(const QModelIndex& index) {
|
||||
LibraryItem* item = IndexToItem(index);
|
||||
if (!item)
|
||||
return no_cover_icon_pretty_;
|
||||
return no_cover_icon_;
|
||||
|
||||
// Check the cache for a pixmap we already loaded.
|
||||
const QString cache_key = AlbumIconPixmapCacheKey(index);
|
||||
@ -416,7 +415,7 @@ QVariant LibraryModel::AlbumIcon(const QModelIndex& index) {
|
||||
|
||||
// Maybe we're loading a pixmap already?
|
||||
if (pending_cache_keys_.contains(cache_key)) {
|
||||
return no_cover_icon_pretty_;
|
||||
return no_cover_icon_;
|
||||
}
|
||||
|
||||
// No art is cached and we're not loading it already. Load art for the first
|
||||
@ -429,7 +428,7 @@ QVariant LibraryModel::AlbumIcon(const QModelIndex& index) {
|
||||
pending_cache_keys_.insert(cache_key);
|
||||
}
|
||||
|
||||
return no_cover_icon_pretty_;
|
||||
return no_cover_icon_;
|
||||
}
|
||||
|
||||
void LibraryModel::AlbumArtLoaded(quint64 id, const QImage& image) {
|
||||
@ -444,7 +443,7 @@ void LibraryModel::AlbumArtLoaded(quint64 id, const QImage& image) {
|
||||
// Insert this image in the cache.
|
||||
if (image.isNull()) {
|
||||
// Set the no_cover image so we don't continually try to load art.
|
||||
QPixmapCache::insert(cache_key, no_cover_icon_pretty_);
|
||||
QPixmapCache::insert(cache_key, no_cover_icon_);
|
||||
} else {
|
||||
QPixmapCache::insert(cache_key, QPixmap::fromImage(image));
|
||||
}
|
||||
|
@ -136,8 +136,9 @@ class LibraryModel : public SimpleTreeModel<LibraryItem> {
|
||||
|
||||
// Whether or not to use album cover art, if it exists, in the library view
|
||||
void set_pretty_covers(bool use_pretty_covers);
|
||||
bool use_pretty_covers() const { return use_pretty_covers_; }
|
||||
|
||||
//Whether or not to show letters heading in the library view
|
||||
// Whether or not to show letters heading in the library view
|
||||
void set_show_dividers(bool show_dividers);
|
||||
|
||||
// Utility functions for manipulating text
|
||||
@ -259,8 +260,7 @@ class LibraryModel : public SimpleTreeModel<LibraryItem> {
|
||||
QIcon album_icon_;
|
||||
// used as a generic icon to show when no cover art is found,
|
||||
// fixed to the same size as the artwork (32x32)
|
||||
QPixmap no_cover_icon_pretty_;
|
||||
QIcon no_cover_icon_;
|
||||
QPixmap no_cover_icon_;
|
||||
QIcon playlists_dir_icon_;
|
||||
QIcon playlist_icon_;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user