Support for playing tracks from local library
This commit is contained in:
parent
21be90a941
commit
c1041ed6d4
|
@ -40,6 +40,8 @@ void GlobalSearch::AddProvider(SearchProvider* provider) {
|
||||||
SLOT(SearchFinishedSlot(int)));
|
SLOT(SearchFinishedSlot(int)));
|
||||||
connect(provider, SIGNAL(ArtLoaded(int,QImage)),
|
connect(provider, SIGNAL(ArtLoaded(int,QImage)),
|
||||||
SLOT(ArtLoadedSlot(int,QImage)));
|
SLOT(ArtLoadedSlot(int,QImage)));
|
||||||
|
connect(provider, SIGNAL(TracksLoaded(int,MimeData*)),
|
||||||
|
SIGNAL(TracksLoaded(int,MimeData*)));
|
||||||
connect(provider, SIGNAL(destroyed(QObject*)),
|
connect(provider, SIGNAL(destroyed(QObject*)),
|
||||||
SLOT(ProviderDestroyedSlot(QObject*)));
|
SLOT(ProviderDestroyedSlot(QObject*)));
|
||||||
|
|
||||||
|
@ -190,3 +192,11 @@ bool GlobalSearch::FindCachedPixmap(const SearchProvider::Result& result,
|
||||||
return pixmap_cache_.find(result.pixmap_cache_key_, pixmap);
|
return pixmap_cache_.find(result.pixmap_cache_key_, pixmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GlobalSearch::LoadTracksAsync(const SearchProvider::Result& result) {
|
||||||
|
const int id = next_id_ ++;
|
||||||
|
|
||||||
|
result.provider_->LoadTracksAsync(id, result);
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ public:
|
||||||
|
|
||||||
int SearchAsync(const QString& query);
|
int SearchAsync(const QString& query);
|
||||||
int LoadArtAsync(const SearchProvider::Result& result);
|
int LoadArtAsync(const SearchProvider::Result& result);
|
||||||
|
int LoadTracksAsync(const SearchProvider::Result& result);
|
||||||
|
|
||||||
void CancelSearch(int id);
|
void CancelSearch(int id);
|
||||||
void CancelArt(int id);
|
void CancelArt(int id);
|
||||||
|
@ -49,6 +50,8 @@ signals:
|
||||||
|
|
||||||
void ArtLoaded(int id, const QPixmap& pixmap);
|
void ArtLoaded(int id, const QPixmap& pixmap);
|
||||||
|
|
||||||
|
void TracksLoaded(int id, MimeData* mime_data);
|
||||||
|
|
||||||
void ProviderDestroyed(SearchProvider* provider);
|
void ProviderDestroyed(SearchProvider* provider);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "ui_globalsearchwidget.h"
|
#include "ui_globalsearchwidget.h"
|
||||||
#include "core/logging.h"
|
#include "core/logging.h"
|
||||||
#include "core/utilities.h"
|
#include "core/utilities.h"
|
||||||
|
#include "playlist/songmimedata.h"
|
||||||
#include "widgets/stylehelper.h"
|
#include "widgets/stylehelper.h"
|
||||||
|
|
||||||
#ifdef HAVE_SPOTIFY
|
#ifdef HAVE_SPOTIFY
|
||||||
|
@ -73,6 +74,8 @@ GlobalSearchWidget::GlobalSearchWidget(QWidget* parent)
|
||||||
SLOT(AddResults(int,SearchProvider::ResultList)));
|
SLOT(AddResults(int,SearchProvider::ResultList)));
|
||||||
connect(engine_, SIGNAL(SearchFinished(int)), SLOT(SearchFinished(int)));
|
connect(engine_, SIGNAL(SearchFinished(int)), SLOT(SearchFinished(int)));
|
||||||
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(view_, SIGNAL(doubleClicked(QModelIndex)), SLOT(AddCurrent()));
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalSearchWidget::~GlobalSearchWidget() {
|
GlobalSearchWidget::~GlobalSearchWidget() {
|
||||||
|
@ -276,7 +279,7 @@ bool GlobalSearchWidget::eventFilter(QObject* o, QEvent* e) {
|
||||||
case Qt::Key_Enter:
|
case Qt::Key_Enter:
|
||||||
case Qt::Key_Tab:
|
case Qt::Key_Tab:
|
||||||
view_->hide();
|
view_->hide();
|
||||||
// TODO: complete
|
AddCurrent();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Qt::Key_F4:
|
case Qt::Key_F4:
|
||||||
|
@ -339,3 +342,24 @@ void GlobalSearchWidget::ArtLoaded(int id, const QPixmap& pixmap) {
|
||||||
model_->itemFromIndex(index)->setData(pixmap, Qt::DecorationRole);
|
model_->itemFromIndex(index)->setData(pixmap, Qt::DecorationRole);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GlobalSearchWidget::AddCurrent() {
|
||||||
|
QModelIndex index = view_->currentIndex();
|
||||||
|
if (!index.isValid())
|
||||||
|
index = proxy_->index(0, 0);
|
||||||
|
|
||||||
|
if (!index.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
engine_->LoadTracksAsync(index.data(Role_Result).value<SearchProvider::Result>());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalSearchWidget::TracksLoaded(int id, MimeData* mime_data) {
|
||||||
|
Q_UNUSED(id);
|
||||||
|
|
||||||
|
if (!mime_data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mime_data->from_doubleclick_ = true;
|
||||||
|
emit AddToPlaylist(mime_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ class LibraryBackendInterface;
|
||||||
class Ui_GlobalSearchWidget;
|
class Ui_GlobalSearchWidget;
|
||||||
|
|
||||||
class QListView;
|
class QListView;
|
||||||
|
class QMimeData;
|
||||||
class QModelIndex;
|
class QModelIndex;
|
||||||
class QSortFilterProxyModel;
|
class QSortFilterProxyModel;
|
||||||
class QStandardItemModel;
|
class QStandardItemModel;
|
||||||
|
@ -55,6 +56,9 @@ public:
|
||||||
// QWidget
|
// QWidget
|
||||||
bool eventFilter(QObject* o, QEvent* e);
|
bool eventFilter(QObject* o, QEvent* e);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void AddToPlaylist(QMimeData* data);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void resizeEvent(QResizeEvent* e);
|
void resizeEvent(QResizeEvent* e);
|
||||||
void paintEvent(QPaintEvent* e);
|
void paintEvent(QPaintEvent* e);
|
||||||
|
@ -66,6 +70,10 @@ private slots:
|
||||||
|
|
||||||
void ArtLoaded(int id, const QPixmap& pixmap);
|
void ArtLoaded(int id, const QPixmap& pixmap);
|
||||||
|
|
||||||
|
void TracksLoaded(int id, MimeData* mime_data);
|
||||||
|
|
||||||
|
void AddCurrent();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Reset();
|
void Reset();
|
||||||
void RepositionPopup();
|
void RepositionPopup();
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "library/librarybackend.h"
|
#include "library/librarybackend.h"
|
||||||
#include "library/libraryquery.h"
|
#include "library/libraryquery.h"
|
||||||
#include "library/sqlrow.h"
|
#include "library/sqlrow.h"
|
||||||
|
#include "playlist/songmimedata.h"
|
||||||
|
|
||||||
|
|
||||||
LibrarySearchProvider::LibrarySearchProvider(LibraryBackendInterface* backend,
|
LibrarySearchProvider::LibrarySearchProvider(LibraryBackendInterface* backend,
|
||||||
|
@ -122,5 +123,40 @@ void LibrarySearchProvider::AlbumArtLoaded(quint64 id, const QImage& image) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void LibrarySearchProvider::LoadTracksAsync(int id, const Result& result) {
|
void LibrarySearchProvider::LoadTracksAsync(int id, const Result& result) {
|
||||||
emit TracksLoaded(id, SongList());
|
SongList ret;
|
||||||
|
|
||||||
|
switch (result.type_) {
|
||||||
|
case Result::Type_Track:
|
||||||
|
// This is really easy - we just emit the track again.
|
||||||
|
ret << result.metadata_;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Result::Type_Album: {
|
||||||
|
// Find all the songs in this album.
|
||||||
|
LibraryQuery query;
|
||||||
|
query.SetOrderBy("track");
|
||||||
|
query.SetColumnSpec("ROWID, " + Song::kColumnSpec);
|
||||||
|
query.AddCompilationRequirement(result.metadata_.is_compilation());
|
||||||
|
query.AddWhere("album", result.metadata_.album());
|
||||||
|
|
||||||
|
if (!result.metadata_.is_compilation())
|
||||||
|
query.AddWhere("artist", result.metadata_.artist());
|
||||||
|
|
||||||
|
if (!backend_->ExecQuery(&query)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (query.Next()) {
|
||||||
|
Song song;
|
||||||
|
song.InitFromQuery(query, true);
|
||||||
|
ret << song;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SongMimeData* mime_data = new SongMimeData;
|
||||||
|
mime_data->backend = backend_;
|
||||||
|
mime_data->songs = ret;
|
||||||
|
|
||||||
|
emit TracksLoaded(id, mime_data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,9 @@
|
||||||
|
|
||||||
#include "core/song.h"
|
#include "core/song.h"
|
||||||
|
|
||||||
|
class MimeData;
|
||||||
|
|
||||||
|
|
||||||
class SearchProvider : public QObject {
|
class SearchProvider : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -93,7 +96,7 @@ signals:
|
||||||
|
|
||||||
void ArtLoaded(int id, const QImage& image);
|
void ArtLoaded(int id, const QImage& image);
|
||||||
|
|
||||||
void TracksLoaded(int id, const SongList& tracks);
|
void TracksLoaded(int id, MimeData* mime_data);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// These functions treat queries in the same way as LibraryQuery. They're
|
// These functions treat queries in the same way as LibraryQuery. They're
|
||||||
|
|
|
@ -134,7 +134,7 @@ void SpotifySearchProvider::ArtLoadedSlot(const QString& id, const QImage& image
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpotifySearchProvider::LoadTracksAsync(int id, const Result& result) {
|
void SpotifySearchProvider::LoadTracksAsync(int id, const Result& result) {
|
||||||
emit TracksLoaded(id, SongList());
|
emit TracksLoaded(id, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,8 @@ public:
|
||||||
};
|
};
|
||||||
typedef QList<Album> AlbumList;
|
typedef QList<Album> AlbumList;
|
||||||
|
|
||||||
|
virtual QString songs_table() const = 0;
|
||||||
|
|
||||||
// Get a list of directories in the library. Emits DirectoriesDiscovered.
|
// Get a list of directories in the library. Emits DirectoriesDiscovered.
|
||||||
virtual void LoadDirectoriesAsync() = 0;
|
virtual void LoadDirectoriesAsync() = 0;
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#include "core/mimedata.h"
|
#include "core/mimedata.h"
|
||||||
#include "core/song.h"
|
#include "core/song.h"
|
||||||
|
|
||||||
class LibraryBackend;
|
class LibraryBackendInterface;
|
||||||
|
|
||||||
class SongMimeData : public MimeData {
|
class SongMimeData : public MimeData {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -32,7 +32,7 @@ public:
|
||||||
SongMimeData()
|
SongMimeData()
|
||||||
: backend(NULL) {}
|
: backend(NULL) {}
|
||||||
|
|
||||||
LibraryBackend* backend;
|
LibraryBackendInterface* backend;
|
||||||
SongList songs;
|
SongList songs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "albumcovermanager.h"
|
#include "albumcovermanager.h"
|
||||||
#include "albumcovermanagerlist.h"
|
#include "albumcovermanagerlist.h"
|
||||||
|
#include "library/librarybackend.h"
|
||||||
#include "playlist/songmimedata.h"
|
#include "playlist/songmimedata.h"
|
||||||
|
|
||||||
#include <boost/scoped_ptr.hpp>
|
#include <boost/scoped_ptr.hpp>
|
||||||
|
|
|
@ -229,7 +229,9 @@ MainWindow::MainWindow(
|
||||||
|
|
||||||
// Initialise the global search widget
|
// Initialise the global search widget
|
||||||
StyleHelper::setBaseColor(palette().color(QPalette::Highlight).darker());
|
StyleHelper::setBaseColor(palette().color(QPalette::Highlight).darker());
|
||||||
|
|
||||||
ui_->global_search->Init(library_->backend());
|
ui_->global_search->Init(library_->backend());
|
||||||
|
connect(ui_->global_search, SIGNAL(AddToPlaylist(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
|
||||||
|
|
||||||
// Add tabs to the fancy tab widget
|
// Add tabs to the fancy tab widget
|
||||||
ui_->tabs->AddTab(library_view_, IconLoader::Load("folder-sound"), tr("Library"));
|
ui_->tabs->AddTab(library_view_, IconLoader::Load("folder-sound"), tr("Library"));
|
||||||
|
|
Loading…
Reference in New Issue