Add a "tooltip" that shows the songs within each album in the global search results
This commit is contained in:
parent
02f2d5dc88
commit
4ac16f0dd4
@ -1,2 +1,2 @@
|
|||||||
# Increment this whenever the user needs to download a new blob
|
# Increment this whenever the user needs to download a new blob
|
||||||
set(SPOTIFY_BLOB_VERSION 5)
|
set(SPOTIFY_BLOB_VERSION 6)
|
||||||
|
@ -233,9 +233,17 @@ void SpotifyClient::SendSearchResponse(sp_search* result) {
|
|||||||
QList<sp_albumbrowse*> browses = pending_search_album_browses_.take(result);
|
QList<sp_albumbrowse*> browses = pending_search_album_browses_.take(result);
|
||||||
foreach (sp_albumbrowse* browse, browses) {
|
foreach (sp_albumbrowse* browse, browses) {
|
||||||
sp_album* album = sp_albumbrowse_album(browse);
|
sp_album* album = sp_albumbrowse_album(browse);
|
||||||
spotify_pb::Track* track = response->add_album();
|
spotify_pb::Album* msg = response->add_album();
|
||||||
ConvertAlbum(album, track);
|
|
||||||
ConvertAlbumBrowse(browse, track);
|
ConvertAlbum(album, msg->mutable_metadata());
|
||||||
|
ConvertAlbumBrowse(browse, msg->mutable_metadata());
|
||||||
|
|
||||||
|
// Add all tracks
|
||||||
|
const int tracks = sp_albumbrowse_num_tracks(browse);
|
||||||
|
for (int i=0 ; i<tracks ; ++i) {
|
||||||
|
ConvertTrack(sp_albumbrowse_track(browse, i), msg->add_track());
|
||||||
|
}
|
||||||
|
|
||||||
sp_albumbrowse_release(browse);
|
sp_albumbrowse_release(browse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +68,11 @@ message Track {
|
|||||||
required string album_art_id = 11;
|
required string album_art_id = 11;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message Album {
|
||||||
|
required Track metadata = 1;
|
||||||
|
repeated Track track = 2;
|
||||||
|
}
|
||||||
|
|
||||||
enum PlaylistType {
|
enum PlaylistType {
|
||||||
Starred = 1;
|
Starred = 1;
|
||||||
Inbox = 2;
|
Inbox = 2;
|
||||||
@ -116,7 +121,9 @@ message SearchResponse {
|
|||||||
optional string did_you_mean = 4;
|
optional string did_you_mean = 4;
|
||||||
optional string error = 5;
|
optional string error = 5;
|
||||||
|
|
||||||
repeated Track album = 6;
|
// field 6 is deprecated
|
||||||
|
|
||||||
|
repeated Album album = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ImageRequest {
|
message ImageRequest {
|
||||||
|
@ -119,9 +119,11 @@ set(SOURCES
|
|||||||
globalsearch/globalsearchitemdelegate.cpp
|
globalsearch/globalsearchitemdelegate.cpp
|
||||||
globalsearch/globalsearchpopup.cpp
|
globalsearch/globalsearchpopup.cpp
|
||||||
globalsearch/globalsearchsortmodel.cpp
|
globalsearch/globalsearchsortmodel.cpp
|
||||||
|
globalsearch/globalsearchtooltip.cpp
|
||||||
globalsearch/globalsearchwidget.cpp
|
globalsearch/globalsearchwidget.cpp
|
||||||
globalsearch/librarysearchprovider.cpp
|
globalsearch/librarysearchprovider.cpp
|
||||||
globalsearch/searchprovider.cpp
|
globalsearch/searchprovider.cpp
|
||||||
|
globalsearch/tooltipresultwidget.cpp
|
||||||
|
|
||||||
internet/digitallyimportedservice.cpp
|
internet/digitallyimportedservice.cpp
|
||||||
internet/digitallyimportedservicebase.cpp
|
internet/digitallyimportedservicebase.cpp
|
||||||
@ -358,8 +360,10 @@ set(HEADERS
|
|||||||
globalsearch/librarysearchprovider.h
|
globalsearch/librarysearchprovider.h
|
||||||
globalsearch/globalsearch.h
|
globalsearch/globalsearch.h
|
||||||
globalsearch/globalsearchpopup.h
|
globalsearch/globalsearchpopup.h
|
||||||
|
globalsearch/globalsearchtooltip.h
|
||||||
globalsearch/globalsearchwidget.h
|
globalsearch/globalsearchwidget.h
|
||||||
globalsearch/searchprovider.h
|
globalsearch/searchprovider.h
|
||||||
|
globalsearch/tooltipresultwidget.h
|
||||||
|
|
||||||
internet/digitallyimportedservicebase.h
|
internet/digitallyimportedservicebase.h
|
||||||
internet/digitallyimportedsettingspage.h
|
internet/digitallyimportedsettingspage.h
|
||||||
|
83
src/globalsearch/globalsearchtooltip.cpp
Normal file
83
src/globalsearch/globalsearchtooltip.cpp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2010, 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 "globalsearchtooltip.h"
|
||||||
|
#include "tooltipresultwidget.h"
|
||||||
|
#include "core/logging.h"
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QKeyEvent>
|
||||||
|
#include <QLayoutItem>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
GlobalSearchTooltip::GlobalSearchTooltip(QObject* event_target)
|
||||||
|
: QWidget(NULL),
|
||||||
|
event_target_(event_target)
|
||||||
|
{
|
||||||
|
setWindowFlags(Qt::Popup);
|
||||||
|
setFocusPolicy(Qt::NoFocus);
|
||||||
|
setAttribute(Qt::WA_OpaquePaintEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalSearchTooltip::SetResults(const SearchProvider::ResultList& results) {
|
||||||
|
results_ = results;
|
||||||
|
|
||||||
|
qDeleteAll(widgets_);
|
||||||
|
widgets_.clear();
|
||||||
|
|
||||||
|
// Using a QVBoxLayout here made some weird flickering that I couldn't figure
|
||||||
|
// out how to fix, so do layout manually.
|
||||||
|
int y = 0;
|
||||||
|
int w = 0;
|
||||||
|
|
||||||
|
foreach (const SearchProvider::Result& result, results) {
|
||||||
|
QWidget* widget = new TooltipResultWidget(result, this);
|
||||||
|
widget->move(0, y);
|
||||||
|
widget->show();
|
||||||
|
widgets_ << widget;
|
||||||
|
|
||||||
|
QSize size_hint(widget->sizeHint());
|
||||||
|
y += size_hint.height();
|
||||||
|
w = qMax(w, size_hint.width());
|
||||||
|
}
|
||||||
|
|
||||||
|
resize(w, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalSearchTooltip::ShowAt(const QPoint& pointing_to) {
|
||||||
|
move(pointing_to);
|
||||||
|
|
||||||
|
if (!isVisible())
|
||||||
|
show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalSearchTooltip::keyPressEvent(QKeyEvent* e) {
|
||||||
|
// Copy the event to send to the target
|
||||||
|
QKeyEvent e2(e->type(), e->key(), e->modifiers(), e->text(),
|
||||||
|
e->isAutoRepeat(), e->count());
|
||||||
|
|
||||||
|
qApp->sendEvent(event_target_, &e2);
|
||||||
|
|
||||||
|
e->accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalSearchTooltip::paintEvent(QPaintEvent*) {
|
||||||
|
QPainter p(this);
|
||||||
|
|
||||||
|
p.fillRect(rect(), palette().base());
|
||||||
|
}
|
48
src/globalsearch/globalsearchtooltip.h
Normal file
48
src/globalsearch/globalsearchtooltip.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2010, 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 GLOBALSEARCHTOOLTIP_H
|
||||||
|
#define GLOBALSEARCHTOOLTIP_H
|
||||||
|
|
||||||
|
#include "searchprovider.h"
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class QVBoxLayout;
|
||||||
|
|
||||||
|
class GlobalSearchTooltip : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
GlobalSearchTooltip(QObject* event_target);
|
||||||
|
|
||||||
|
void SetResults(const SearchProvider::ResultList& results);
|
||||||
|
void ShowAt(const QPoint& pointing_to);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void keyPressEvent(QKeyEvent* e);
|
||||||
|
void paintEvent(QPaintEvent*);
|
||||||
|
|
||||||
|
private:
|
||||||
|
SearchProvider::ResultList results_;
|
||||||
|
|
||||||
|
QObject* event_target_;
|
||||||
|
|
||||||
|
QWidgetList widgets_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GLOBALSEARCHTOOLTIP_H
|
@ -19,6 +19,7 @@
|
|||||||
#include "globalsearch.h"
|
#include "globalsearch.h"
|
||||||
#include "globalsearchitemdelegate.h"
|
#include "globalsearchitemdelegate.h"
|
||||||
#include "globalsearchsortmodel.h"
|
#include "globalsearchsortmodel.h"
|
||||||
|
#include "globalsearchtooltip.h"
|
||||||
#include "globalsearchwidget.h"
|
#include "globalsearchwidget.h"
|
||||||
#include "librarysearchprovider.h"
|
#include "librarysearchprovider.h"
|
||||||
#include "ui_globalsearchwidget.h"
|
#include "ui_globalsearchwidget.h"
|
||||||
@ -92,6 +93,8 @@ GlobalSearchWidget::GlobalSearchWidget(QWidget* parent)
|
|||||||
connect(engine_, SIGNAL(ArtLoaded(int,QPixmap)), SLOT(ArtLoaded(int,QPixmap)));
|
connect(engine_, SIGNAL(ArtLoaded(int,QPixmap)), SLOT(ArtLoaded(int,QPixmap)));
|
||||||
connect(engine_, SIGNAL(TracksLoaded(int,MimeData*)), SLOT(TracksLoaded(int,MimeData*)));
|
connect(engine_, SIGNAL(TracksLoaded(int,MimeData*)), SLOT(TracksLoaded(int,MimeData*)));
|
||||||
connect(view_, SIGNAL(doubleClicked(QModelIndex)), SLOT(AddCurrent()));
|
connect(view_, SIGNAL(doubleClicked(QModelIndex)), SLOT(AddCurrent()));
|
||||||
|
connect(view_->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
|
||||||
|
SLOT(UpdateTooltip()));
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalSearchWidget::~GlobalSearchWidget() {
|
GlobalSearchWidget::~GlobalSearchWidget() {
|
||||||
@ -243,7 +246,7 @@ void GlobalSearchWidget::AddResults(int id, const SearchProvider::ResultList& re
|
|||||||
|
|
||||||
void GlobalSearchWidget::RepositionPopup() {
|
void GlobalSearchWidget::RepositionPopup() {
|
||||||
if (model_->rowCount() == 0) {
|
if (model_->rowCount() == 0) {
|
||||||
view_->hide();
|
HidePopup();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,7 +349,7 @@ bool GlobalSearchWidget::EventFilterPopup(QObject*, QEvent* e) {
|
|||||||
if (e->isAccepted() || !view_->isVisible()) {
|
if (e->isAccepted() || !view_->isVisible()) {
|
||||||
// widget lost focus, hide the popup
|
// widget lost focus, hide the popup
|
||||||
if (!ui_->search->hasFocus())
|
if (!ui_->search->hasFocus())
|
||||||
view_->hide();
|
HidePopup();
|
||||||
if (e->isAccepted())
|
if (e->isAccepted())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -356,18 +359,18 @@ bool GlobalSearchWidget::EventFilterPopup(QObject*, QEvent* e) {
|
|||||||
case Qt::Key_Return:
|
case Qt::Key_Return:
|
||||||
case Qt::Key_Enter:
|
case Qt::Key_Enter:
|
||||||
case Qt::Key_Tab:
|
case Qt::Key_Tab:
|
||||||
view_->hide();
|
HidePopup();
|
||||||
AddCurrent();
|
AddCurrent();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qt::Key_F4:
|
case Qt::Key_F4:
|
||||||
if (ke->modifiers() & Qt::AltModifier)
|
if (ke->modifiers() & Qt::AltModifier)
|
||||||
view_->hide();
|
HidePopup();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qt::Key_Backtab:
|
case Qt::Key_Backtab:
|
||||||
case Qt::Key_Escape:
|
case Qt::Key_Escape:
|
||||||
view_->hide();
|
HidePopup();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -379,7 +382,7 @@ bool GlobalSearchWidget::EventFilterPopup(QObject*, QEvent* e) {
|
|||||||
|
|
||||||
case QEvent::MouseButtonPress:
|
case QEvent::MouseButtonPress:
|
||||||
if (!view_->underMouse()) {
|
if (!view_->underMouse()) {
|
||||||
view_->hide();
|
HidePopup();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -501,3 +504,32 @@ void GlobalSearchWidget::CombineResults(const QModelIndex& superior, const QMode
|
|||||||
model_->invisibleRootItem()->removeRow(inferior_item->row());
|
model_->invisibleRootItem()->removeRow(inferior_item->row());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GlobalSearchWidget::HidePopup() {
|
||||||
|
if (tooltip_)
|
||||||
|
tooltip_->hide();
|
||||||
|
view_->hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalSearchWidget::UpdateTooltip() {
|
||||||
|
if (!view_->isVisible()) {
|
||||||
|
if (tooltip_)
|
||||||
|
tooltip_->hide();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QModelIndex current = view_->selectionModel()->currentIndex();
|
||||||
|
if (!current.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const SearchProvider::ResultList results = current.data(Role_AllResults)
|
||||||
|
.value<SearchProvider::ResultList>();
|
||||||
|
|
||||||
|
if (!tooltip_) {
|
||||||
|
tooltip_.reset(new GlobalSearchTooltip(view_));
|
||||||
|
tooltip_->setFont(view_->font());
|
||||||
|
tooltip_->setPalette(view_->palette());
|
||||||
|
}
|
||||||
|
|
||||||
|
tooltip_->SetResults(results);
|
||||||
|
tooltip_->ShowAt(view_->mapToGlobal(view_->visualRect(current).topRight()));
|
||||||
|
}
|
||||||
|
@ -20,9 +20,11 @@
|
|||||||
|
|
||||||
#include "searchprovider.h"
|
#include "searchprovider.h"
|
||||||
|
|
||||||
|
#include <QScopedPointer>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
class GlobalSearch;
|
class GlobalSearch;
|
||||||
|
class GlobalSearchTooltip;
|
||||||
class LibraryBackendInterface;
|
class LibraryBackendInterface;
|
||||||
class Ui_GlobalSearchWidget;
|
class Ui_GlobalSearchWidget;
|
||||||
|
|
||||||
@ -81,6 +83,9 @@ private slots:
|
|||||||
|
|
||||||
void AddCurrent();
|
void AddCurrent();
|
||||||
|
|
||||||
|
void HidePopup();
|
||||||
|
void UpdateTooltip();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Return values from CanCombineResults
|
// Return values from CanCombineResults
|
||||||
enum CombineAction {
|
enum CombineAction {
|
||||||
@ -118,6 +123,8 @@ private:
|
|||||||
|
|
||||||
bool combine_identical_results_;
|
bool combine_identical_results_;
|
||||||
QStringList provider_order_;
|
QStringList provider_order_;
|
||||||
|
|
||||||
|
QScopedPointer<GlobalSearchTooltip> tooltip_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GLOBALSEARCHWIDGET_H
|
#endif // GLOBALSEARCHWIDGET_H
|
||||||
|
@ -104,6 +104,10 @@ SearchProvider::ResultList LibrarySearchProvider::Search(int id, const QString&
|
|||||||
MatchQuality(tokens, result.metadata_.albumartist()),
|
MatchQuality(tokens, result.metadata_.albumartist()),
|
||||||
qMin(MatchQuality(tokens, result.metadata_.artist()),
|
qMin(MatchQuality(tokens, result.metadata_.artist()),
|
||||||
MatchQuality(tokens, result.metadata_.album())));
|
MatchQuality(tokens, result.metadata_.album())));
|
||||||
|
|
||||||
|
result.album_songs_ = albums.values(key);
|
||||||
|
SortSongs(&result.album_songs_);
|
||||||
|
|
||||||
ret << result;
|
ret << result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +139,6 @@ void LibrarySearchProvider::LoadTracksAsync(int id, const Result& result) {
|
|||||||
case Result::Type_Album: {
|
case Result::Type_Album: {
|
||||||
// Find all the songs in this album.
|
// Find all the songs in this album.
|
||||||
LibraryQuery query;
|
LibraryQuery query;
|
||||||
query.SetOrderBy("track");
|
|
||||||
query.SetColumnSpec("ROWID, " + Song::kColumnSpec);
|
query.SetColumnSpec("ROWID, " + Song::kColumnSpec);
|
||||||
query.AddCompilationRequirement(result.metadata_.is_compilation());
|
query.AddCompilationRequirement(result.metadata_.is_compilation());
|
||||||
query.AddWhere("album", result.metadata_.album());
|
query.AddWhere("album", result.metadata_.album());
|
||||||
@ -155,6 +158,8 @@ void LibrarySearchProvider::LoadTracksAsync(int id, const Result& result) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SortSongs(&ret);
|
||||||
|
|
||||||
SongMimeData* mime_data = new SongMimeData;
|
SongMimeData* mime_data = new SongMimeData;
|
||||||
mime_data->backend = backend_;
|
mime_data->backend = backend_;
|
||||||
mime_data->songs = ret;
|
mime_data->songs = ret;
|
||||||
|
@ -122,3 +122,18 @@ QImage SearchProvider::ScaleAndPad(const QImage& image) {
|
|||||||
|
|
||||||
return padded_image;
|
return padded_image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
bool SortSongsCompare(const Song& left, const Song& right) {
|
||||||
|
if (left.disc() < right.disc())
|
||||||
|
return true;
|
||||||
|
if (left.disc() > right.disc())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return left.track() < right.track();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SearchProvider::SortSongs(SongList* list) {
|
||||||
|
qStableSort(list->begin(), list->end(), SortSongsCompare);
|
||||||
|
}
|
||||||
|
@ -67,6 +67,10 @@ public:
|
|||||||
// How many songs in the album - valid only if type == Type_Album.
|
// How many songs in the album - valid only if type == Type_Album.
|
||||||
int album_size_;
|
int album_size_;
|
||||||
|
|
||||||
|
// Songs in the album - valid only if type == Type_Album. This is only
|
||||||
|
// used for display in the tooltip, so it's fine not to provide it.
|
||||||
|
SongList album_songs_;
|
||||||
|
|
||||||
QString pixmap_cache_key_;
|
QString pixmap_cache_key_;
|
||||||
};
|
};
|
||||||
typedef QList<Result> ResultList;
|
typedef QList<Result> ResultList;
|
||||||
@ -106,6 +110,9 @@ protected:
|
|||||||
static QStringList TokenizeQuery(const QString& query);
|
static QStringList TokenizeQuery(const QString& query);
|
||||||
static Result::MatchQuality MatchQuality(const QStringList& tokens, const QString& string);
|
static Result::MatchQuality MatchQuality(const QStringList& tokens, const QString& string);
|
||||||
|
|
||||||
|
// Sorts a list of songs by disc, then by track.
|
||||||
|
static void SortSongs(SongList* list);
|
||||||
|
|
||||||
// Subclasses must call this from their constructor
|
// Subclasses must call this from their constructor
|
||||||
void Init(const QString& name, const QString& id, const QIcon& icon,
|
void Init(const QString& name, const QString& id, const QIcon& icon,
|
||||||
bool delay_searches, bool serialised_art);
|
bool delay_searches, bool serialised_art);
|
||||||
|
@ -95,15 +95,22 @@ void SpotifySearchProvider::SearchFinishedSlot(const spotify_pb::SearchResponse&
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0 ; i<response.album_size() ; ++i) {
|
for (int i=0 ; i<response.album_size() ; ++i) {
|
||||||
const spotify_pb::Track& track = response.album(i);
|
const spotify_pb::Album& album = response.album(i);
|
||||||
|
|
||||||
Result result(this);
|
Result result(this);
|
||||||
result.type_ = Result::Type_Album;
|
result.type_ = Result::Type_Album;
|
||||||
SpotifyService::SongFromProtobuf(track, &result.metadata_);
|
SpotifyService::SongFromProtobuf(album.metadata(), &result.metadata_);
|
||||||
result.match_quality_ =
|
result.match_quality_ =
|
||||||
qMin(MatchQuality(state.tokens_, result.metadata_.album()),
|
qMin(MatchQuality(state.tokens_, result.metadata_.album()),
|
||||||
MatchQuality(state.tokens_, result.metadata_.artist()));
|
MatchQuality(state.tokens_, result.metadata_.artist()));
|
||||||
result.album_size_ = track.track();
|
result.album_size_ = album.metadata().track();
|
||||||
|
|
||||||
|
for (int j=0; j < album.track_size() ; ++j) {
|
||||||
|
Song track_song;
|
||||||
|
SpotifyService::SongFromProtobuf(album.track(j), &track_song);
|
||||||
|
result.album_songs_ << track_song;
|
||||||
|
}
|
||||||
|
|
||||||
ret << result;
|
ret << result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
145
src/globalsearch/tooltipresultwidget.cpp
Normal file
145
src/globalsearch/tooltipresultwidget.cpp
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2010, 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 "tooltipresultwidget.h"
|
||||||
|
#include "core/logging.h"
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
const int TooltipResultWidget::kBorder = 6;
|
||||||
|
const int TooltipResultWidget::kSpacing = 3;
|
||||||
|
const int TooltipResultWidget::kTrackNoSpacing = 6;
|
||||||
|
const int TooltipResultWidget::kLineHeight = 1;
|
||||||
|
const int TooltipResultWidget::kIconSize = 16;
|
||||||
|
|
||||||
|
TooltipResultWidget::TooltipResultWidget(const SearchProvider::Result& result,
|
||||||
|
QWidget* parent)
|
||||||
|
: QWidget(parent),
|
||||||
|
result_(result),
|
||||||
|
kTextHeight(fontMetrics().height()),
|
||||||
|
kTrackNoWidth(fontMetrics().width("0000")),
|
||||||
|
bold_metrics_(fontMetrics())
|
||||||
|
{
|
||||||
|
bold_font_ = font();
|
||||||
|
bold_font_.setBold(true);
|
||||||
|
bold_metrics_ = QFontMetrics(bold_font_);
|
||||||
|
|
||||||
|
size_hint_ = CalculateSizeHint();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize TooltipResultWidget::sizeHint() const {
|
||||||
|
return size_hint_;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize TooltipResultWidget::CalculateSizeHint() const {
|
||||||
|
int w = 0;
|
||||||
|
int h = 0;
|
||||||
|
|
||||||
|
// Title text
|
||||||
|
h += kBorder + kIconSize + kBorder + kLineHeight;
|
||||||
|
w = qMax(w, kBorder + kIconSize + kBorder + bold_metrics_.width(TitleText()) + kBorder);
|
||||||
|
|
||||||
|
switch (result_.type_) {
|
||||||
|
case SearchProvider::Result::Type_Track:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SearchProvider::Result::Type_Album:
|
||||||
|
if (result_.album_songs_.isEmpty())
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Song list
|
||||||
|
h += kBorder + kSpacing * (result_.album_songs_.count() - 1) +
|
||||||
|
kTextHeight * result_.album_songs_.count();
|
||||||
|
foreach (const Song& song, result_.album_songs_) {
|
||||||
|
w = qMax(w, kTrackNoWidth + kTrackNoSpacing +
|
||||||
|
fontMetrics().width(song.TitleWithCompilationArtist()) +
|
||||||
|
kBorder);
|
||||||
|
}
|
||||||
|
|
||||||
|
h += kBorder + kLineHeight;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QSize(w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TooltipResultWidget::TitleText() const {
|
||||||
|
return result_.provider_->name();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TooltipResultWidget::paintEvent(QPaintEvent*) {
|
||||||
|
QPainter p(this);
|
||||||
|
p.setPen(palette().color(QPalette::Text));
|
||||||
|
|
||||||
|
int y = kBorder;
|
||||||
|
|
||||||
|
// Title icon
|
||||||
|
QRect icon_rect(kBorder, y, kIconSize, kIconSize);
|
||||||
|
p.drawPixmap(icon_rect, result_.provider_->icon().pixmap(kIconSize));
|
||||||
|
|
||||||
|
// Title text
|
||||||
|
QRect text_rect(icon_rect.right() + kBorder, y,
|
||||||
|
width() - kBorder*2 - icon_rect.right(), kIconSize);
|
||||||
|
p.setFont(bold_font_);
|
||||||
|
p.drawText(text_rect, Qt::AlignVCenter, TitleText());
|
||||||
|
|
||||||
|
// Line
|
||||||
|
y += kIconSize + kBorder;
|
||||||
|
p.drawLine(0, y, width(), y);
|
||||||
|
y += kLineHeight;
|
||||||
|
|
||||||
|
switch (result_.type_) {
|
||||||
|
case SearchProvider::Result::Type_Track:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SearchProvider::Result::Type_Album:
|
||||||
|
if (result_.album_songs_.isEmpty())
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Song list
|
||||||
|
y += kBorder;
|
||||||
|
|
||||||
|
p.setFont(font());
|
||||||
|
|
||||||
|
foreach (const Song& song, result_.album_songs_) {
|
||||||
|
QRect number_rect(0, y, kTrackNoWidth, kTextHeight);
|
||||||
|
if (song.track() > 0) {
|
||||||
|
// Track number
|
||||||
|
p.drawText(number_rect, Qt::AlignRight | Qt::AlignHCenter,
|
||||||
|
QString::number(song.track()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Song title
|
||||||
|
QRect title_rect(number_rect.right() + kTrackNoSpacing, y,
|
||||||
|
width() - number_rect.right() - kTrackNoSpacing - kBorder,
|
||||||
|
kTextHeight);
|
||||||
|
p.drawText(title_rect, song.TitleWithCompilationArtist());
|
||||||
|
|
||||||
|
y += kTextHeight + kSpacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
y -= kSpacing;
|
||||||
|
y += kBorder;
|
||||||
|
|
||||||
|
// Line
|
||||||
|
p.drawLine(0, y, width(), y);
|
||||||
|
y += kLineHeight;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
58
src/globalsearch/tooltipresultwidget.h
Normal file
58
src/globalsearch/tooltipresultwidget.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2010, 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 TOOLTIPRESULTWIDGET_H
|
||||||
|
#define TOOLTIPRESULTWIDGET_H
|
||||||
|
|
||||||
|
#include "searchprovider.h"
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class TooltipResultWidget : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
TooltipResultWidget(const SearchProvider::Result& result, QWidget* parent = 0);
|
||||||
|
|
||||||
|
static const int kBorder;
|
||||||
|
static const int kSpacing;
|
||||||
|
static const int kTrackNoSpacing;
|
||||||
|
static const int kLineHeight;
|
||||||
|
static const int kIconSize;
|
||||||
|
|
||||||
|
QSize sizeHint() const;
|
||||||
|
|
||||||
|
QString TitleText() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent*);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QSize CalculateSizeHint() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SearchProvider::Result result_;
|
||||||
|
const int kTextHeight;
|
||||||
|
const int kTrackNoWidth;
|
||||||
|
|
||||||
|
QSize size_hint_;
|
||||||
|
|
||||||
|
QFont bold_font_;
|
||||||
|
QFontMetrics bold_metrics_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // TOOLTIPRESULTWIDGET_H
|
Loading…
x
Reference in New Issue
Block a user