Enable dragging and double clicking from the album cover manager to add albums to the playlist
Update issue #169 Status: Fixed I hadn't forgotten about this, honest... :)
This commit is contained in:
parent
efcd2c968a
commit
516f769a75
|
@ -104,6 +104,7 @@ set(SOURCES
|
|||
ui/about.cpp
|
||||
ui/addstreamdialog.cpp
|
||||
ui/albumcovermanager.cpp
|
||||
ui/albumcovermanagerlist.cpp
|
||||
ui/edittagdialog.cpp
|
||||
ui/equalizer.cpp
|
||||
ui/globalshortcutgrabber.cpp
|
||||
|
@ -201,6 +202,7 @@ set(HEADERS
|
|||
ui/about.h
|
||||
ui/addstreamdialog.h
|
||||
ui/albumcovermanager.h
|
||||
ui/albumcovermanagerlist.h
|
||||
ui/edittagdialog.h
|
||||
ui/equalizer.h
|
||||
ui/globalshortcutgrabber.h
|
||||
|
|
|
@ -57,6 +57,7 @@ AlbumCoverManager::AlbumCoverManager(NetworkAccessManager* network,
|
|||
missing_covers_(0)
|
||||
{
|
||||
ui_->setupUi(this);
|
||||
ui_->albums->set_cover_manager(this);
|
||||
|
||||
// Icons
|
||||
ui_->action_fetch->setIcon(IconLoader::Load("download"));
|
||||
|
@ -66,6 +67,8 @@ AlbumCoverManager::AlbumCoverManager(NetworkAccessManager* network,
|
|||
ui_->clear->setIcon(IconLoader::Load("edit-clear-locationbar-ltr"));
|
||||
ui_->view->setIcon(IconLoader::Load("view-choose"));
|
||||
ui_->fetch->setIcon(IconLoader::Load("download"));
|
||||
ui_->action_add_to_playlist->setIcon(IconLoader::Load("media-playback-start"));
|
||||
ui_->action_load->setIcon(IconLoader::Load("media-playback-start"));
|
||||
|
||||
// Get a square version of nocover.png
|
||||
QImage nocover(":/nocover.png");
|
||||
|
@ -111,6 +114,9 @@ void AlbumCoverManager::Init() {
|
|||
context_menu_->addAction(ui_->action_choose_manual);
|
||||
context_menu_->addSeparator();
|
||||
context_menu_->addAction(ui_->action_unset_cover);
|
||||
context_menu_->addSeparator();
|
||||
context_menu_->addAction(ui_->action_load);
|
||||
context_menu_->addAction(ui_->action_add_to_playlist);
|
||||
ui_->albums->installEventFilter(this);
|
||||
|
||||
// Connections
|
||||
|
@ -127,6 +133,9 @@ void AlbumCoverManager::Init() {
|
|||
connect(ui_->action_fetch, SIGNAL(triggered()), SLOT(FetchSingleCover()));
|
||||
connect(ui_->action_choose_manual, SIGNAL(triggered()), SLOT(ChooseManualCover()));
|
||||
connect(ui_->action_unset_cover, SIGNAL(triggered()), SLOT(UnsetCover()));
|
||||
connect(ui_->albums, SIGNAL(doubleClicked(QModelIndex)), SLOT(AlbumDoubleClicked(QModelIndex)));
|
||||
connect(ui_->action_add_to_playlist, SIGNAL(triggered()), SLOT(AddSelectedToPlaylist()));
|
||||
connect(ui_->action_load, SIGNAL(triggered()), SLOT(LoadSelectedToPlaylist()));
|
||||
|
||||
// Restore settings
|
||||
QSettings s;
|
||||
|
@ -239,6 +248,8 @@ void AlbumCoverManager::ArtistChanged(QListWidgetItem* current) {
|
|||
QListWidgetItem* item = new QListWidgetItem(no_cover_icon_, info.album_name, ui_->albums);
|
||||
item->setData(Role_ArtistName, info.artist);
|
||||
item->setData(Role_AlbumName, info.album_name);
|
||||
item->setData(Qt::TextAlignmentRole, QVariant(Qt::AlignTop | Qt::AlignHCenter));
|
||||
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
|
||||
|
||||
if (!info.art_automatic.isEmpty() || !info.art_manual.isEmpty()) {
|
||||
quint64 id = cover_loader_->Worker()->LoadImageAsync(
|
||||
|
@ -497,3 +508,49 @@ void AlbumCoverManager::UnsetCover() {
|
|||
AlbumCoverLoader::kManuallyUnsetCover);
|
||||
}
|
||||
}
|
||||
|
||||
SongList AlbumCoverManager::GetSongsInAlbum(const QModelIndex& index) const {
|
||||
SongList ret;
|
||||
|
||||
LibraryQuery q;
|
||||
q.SetColumnSpec("ROWID," + Song::kColumnSpec);
|
||||
q.AddWhere("album", index.data(Role_AlbumName).toString());
|
||||
q.SetOrderBy("disc, track, title");
|
||||
|
||||
QString artist = index.data(Role_ArtistName).toString();
|
||||
q.AddCompilationRequirement(artist.isEmpty());
|
||||
if (!artist.isEmpty())
|
||||
q.AddWhere("artist", artist);
|
||||
|
||||
if (!backend_->ExecQuery(&q))
|
||||
return ret;
|
||||
|
||||
while (q.Next()) {
|
||||
Song song;
|
||||
song.InitFromQuery(q);
|
||||
ret << song;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
SongList AlbumCoverManager::GetSongsInAlbums(const QModelIndexList& indexes) const {
|
||||
SongList ret;
|
||||
foreach (const QModelIndex& index, indexes) {
|
||||
ret << GetSongsInAlbum(index);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void AlbumCoverManager::AlbumDoubleClicked(const QModelIndex &index) {
|
||||
emit SongsDoubleClicked(GetSongsInAlbum(index));
|
||||
}
|
||||
|
||||
void AlbumCoverManager::AddSelectedToPlaylist() {
|
||||
emit AddSongsToPlaylist(GetSongsInAlbums(
|
||||
ui_->albums->selectionModel()->selectedIndexes()));
|
||||
}
|
||||
|
||||
void AlbumCoverManager::LoadSelectedToPlaylist() {
|
||||
emit LoadSongsToPlaylist(GetSongsInAlbums(
|
||||
ui_->albums->selectionModel()->selectedIndexes()));
|
||||
}
|
||||
|
|
|
@ -19,11 +19,13 @@
|
|||
|
||||
#include <QMainWindow>
|
||||
#include <QIcon>
|
||||
#include <QModelIndex>
|
||||
|
||||
#include "gtest/gtest_prod.h"
|
||||
|
||||
#include "core/albumcoverloader.h"
|
||||
#include "core/backgroundthread.h"
|
||||
#include "core/song.h"
|
||||
|
||||
class LibraryBackend;
|
||||
class AlbumCoverFetcher;
|
||||
|
@ -43,10 +45,19 @@ class AlbumCoverManager : public QMainWindow {
|
|||
|
||||
static const char* kSettingsGroup;
|
||||
|
||||
void Reset();
|
||||
LibraryBackend* backend() const { return backend_; }
|
||||
|
||||
void Reset();
|
||||
void Init();
|
||||
|
||||
SongList GetSongsInAlbum(const QModelIndex& index) const;
|
||||
SongList GetSongsInAlbums(const QModelIndexList& indexes) const;
|
||||
|
||||
signals:
|
||||
void AddSongsToPlaylist(const SongList& songs);
|
||||
void LoadSongsToPlaylist(const SongList& songs);
|
||||
void SongsDoubleClicked(const SongList& songs);
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *);
|
||||
void closeEvent(QCloseEvent *);
|
||||
|
@ -69,6 +80,11 @@ class AlbumCoverManager : public QMainWindow {
|
|||
void ChooseManualCover();
|
||||
void UnsetCover();
|
||||
|
||||
// For adding albums to the playlist
|
||||
void AlbumDoubleClicked(const QModelIndex& index);
|
||||
void AddSelectedToPlaylist();
|
||||
void LoadSelectedToPlaylist();
|
||||
|
||||
private:
|
||||
enum ArtistItemType {
|
||||
All_Artists,
|
||||
|
|
|
@ -115,7 +115,13 @@
|
|||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QListWidget" name="albums">
|
||||
<widget class="AlbumCoverManagerList" name="albums">
|
||||
<property name="dragEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragOnly</enum>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
|
@ -128,9 +134,6 @@
|
|||
<height>120</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="movement">
|
||||
<enum>QListView::Static</enum>
|
||||
</property>
|
||||
<property name="flow">
|
||||
<enum>QListView::LeftToRight</enum>
|
||||
</property>
|
||||
|
@ -181,6 +184,16 @@
|
|||
<string>Unset cover</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_load">
|
||||
<property name="text">
|
||||
<string>Load</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_add_to_playlist">
|
||||
<property name="text">
|
||||
<string>Add to playlist</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
|
@ -188,6 +201,11 @@
|
|||
<extends>QLineEdit</extends>
|
||||
<header>widgets/lineedit.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>AlbumCoverManagerList</class>
|
||||
<extends>QListWidget</extends>
|
||||
<header>ui/albumcovermanagerlist.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>artists</tabstop>
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
/* This file is part of Clementine.
|
||||
|
||||
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 "albumcovermanager.h"
|
||||
#include "albumcovermanagerlist.h"
|
||||
#include "playlist/songmimedata.h"
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
#include <QUrl>
|
||||
#include <QtDebug>
|
||||
|
||||
AlbumCoverManagerList::AlbumCoverManagerList(QWidget *parent)
|
||||
: QListWidget(parent),
|
||||
manager_(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
QMimeData* AlbumCoverManagerList::mimeData(const QList<QListWidgetItem*> items) const {
|
||||
// Get songs
|
||||
SongList songs;
|
||||
foreach (QListWidgetItem* item, items) {
|
||||
songs << manager_->GetSongsInAlbum(indexFromItem(item));
|
||||
}
|
||||
|
||||
if (songs.isEmpty())
|
||||
return NULL;
|
||||
|
||||
// Get URLs from the songs
|
||||
QList<QUrl> urls;
|
||||
foreach (const Song& song, songs) {
|
||||
urls << QUrl::fromLocalFile(song.filename());
|
||||
}
|
||||
|
||||
// Get the QAbstractItemModel data so the picture works
|
||||
boost::scoped_ptr<QMimeData> orig_data(QListWidget::mimeData(items));
|
||||
|
||||
SongMimeData* mime_data = new SongMimeData;
|
||||
mime_data->backend = manager_->backend();
|
||||
mime_data->songs = songs;
|
||||
mime_data->setUrls(urls);
|
||||
mime_data->setData(orig_data->formats()[0], orig_data->data(orig_data->formats()[0]));
|
||||
return mime_data;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/* This file is part of Clementine.
|
||||
|
||||
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 ALBUMCOVERMANAGERLIST_H
|
||||
#define ALBUMCOVERMANAGERLIST_H
|
||||
|
||||
#include <QListWidget>
|
||||
|
||||
class AlbumCoverManager;
|
||||
|
||||
class AlbumCoverManagerList : public QListWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AlbumCoverManagerList(QWidget *parent = 0);
|
||||
|
||||
void set_cover_manager(AlbumCoverManager* manager) { manager_ = manager; }
|
||||
|
||||
protected:
|
||||
QMimeData* mimeData(const QList<QListWidgetItem*> items) const;
|
||||
|
||||
private:
|
||||
AlbumCoverManager* manager_;
|
||||
};
|
||||
|
||||
#endif // ALBUMCOVERMANAGERLIST_H
|
|
@ -215,6 +215,11 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg
|
|||
connect(ui_->file_view, SIGNAL(DoubleClicked(QList<QUrl>)), SLOT(FilesDoubleClicked(QList<QUrl>)));
|
||||
connect(ui_->file_view, SIGNAL(PathChanged(QString)), SLOT(FilePathChanged(QString)));
|
||||
|
||||
// Cover manager connections
|
||||
connect(cover_manager_.get(), SIGNAL(AddSongsToPlaylist(SongList)), SLOT(AddLibrarySongsToPlaylist(SongList)));
|
||||
connect(cover_manager_.get(), SIGNAL(LoadSongsToPlaylist(SongList)), SLOT(LoadLibrarySongsToPlaylist(SongList)));
|
||||
connect(cover_manager_.get(), SIGNAL(SongsDoubleClicked(SongList)), SLOT(LibrarySongsDoubleClicked(SongList)));
|
||||
|
||||
// Action connections
|
||||
connect(ui_->action_next_track, SIGNAL(triggered()), player_, SLOT(Next()));
|
||||
connect(ui_->action_previous_track, SIGNAL(triggered()), player_, SLOT(Previous()));
|
||||
|
@ -542,6 +547,35 @@ void MainWindow::AddFilesToPlaylist(bool clear_first, const QList<QUrl>& urls) {
|
|||
}
|
||||
}
|
||||
|
||||
void MainWindow::AddLibrarySongsToPlaylist(const SongList &songs) {
|
||||
AddLibrarySongsToPlaylist(false, songs);
|
||||
}
|
||||
|
||||
void MainWindow::LoadLibrarySongsToPlaylist(const SongList &songs) {
|
||||
AddLibrarySongsToPlaylist(true, songs);
|
||||
}
|
||||
|
||||
void MainWindow::LibrarySongsDoubleClicked(const SongList &songs) {
|
||||
AddLibrarySongsToPlaylist(autoclear_playlist_, songs);
|
||||
}
|
||||
|
||||
void MainWindow::AddLibrarySongsToPlaylist(bool clear_first, const SongList &songs) {
|
||||
if (clear_first)
|
||||
playlists_->ClearCurrent();
|
||||
|
||||
QModelIndex first_song = playlists_->current()->InsertLibraryItems(songs);
|
||||
|
||||
if (!playlists_->current()->proxy()->mapFromSource(first_song).isValid()) {
|
||||
// The first song doesn't match the filter, so don't play it
|
||||
return;
|
||||
}
|
||||
|
||||
if (first_song.isValid() && player_->GetState() != Engine::Playing) {
|
||||
playlists_->SetActiveToCurrent();
|
||||
player_->PlayAt(first_song.row(), Engine::First, true);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::MediaStopped() {
|
||||
ui_->action_stop->setEnabled(false);
|
||||
ui_->action_stop_after_this_track->setEnabled(false);
|
||||
|
@ -655,21 +689,7 @@ void MainWindow::AddLibraryItemToPlaylist(bool clear_first, const QModelIndexLis
|
|||
source_indexes << index;
|
||||
}
|
||||
|
||||
if (clear_first)
|
||||
playlists_->ClearCurrent();
|
||||
|
||||
QModelIndex first_song = playlists_->current()->InsertLibraryItems(
|
||||
library_->model()->GetChildSongs(source_indexes));
|
||||
|
||||
if (!playlists_->current()->proxy()->mapFromSource(first_song).isValid()) {
|
||||
// The first song doesn't match the filter, so don't play it
|
||||
return;
|
||||
}
|
||||
|
||||
if (first_song.isValid() && player_->GetState() != Engine::Playing) {
|
||||
playlists_->SetActiveToCurrent();
|
||||
player_->PlayAt(first_song.row(), Engine::First, true);
|
||||
}
|
||||
AddLibrarySongsToPlaylist(clear_first, library_->model()->GetChildSongs(source_indexes));
|
||||
}
|
||||
|
||||
void MainWindow::VolumeWheelEvent(int delta) {
|
||||
|
|
|
@ -118,6 +118,10 @@ class MainWindow : public QMainWindow {
|
|||
void AddFilesToPlaylist(const QList<QUrl>& urls);
|
||||
void FilesDoubleClicked(const QList<QUrl>& urls);
|
||||
|
||||
void LoadLibrarySongsToPlaylist(const SongList& songs);
|
||||
void AddLibrarySongsToPlaylist(const SongList& songs);
|
||||
void LibrarySongsDoubleClicked(const SongList& songs);
|
||||
|
||||
void VolumeWheelEvent(int delta);
|
||||
void TrayClicked(QSystemTrayIcon::ActivationReason reason);
|
||||
|
||||
|
@ -149,6 +153,7 @@ class MainWindow : public QMainWindow {
|
|||
void SaveGeometry();
|
||||
void AddFilesToPlaylist(bool clear_first, const QList<QUrl>& urls);
|
||||
void AddLibraryItemToPlaylist(bool clear_first, const QModelIndexList& indexes);
|
||||
void AddLibrarySongsToPlaylist(bool clear_first, const SongList& songs);
|
||||
|
||||
private:
|
||||
static const int kStateVersion;
|
||||
|
|
Loading…
Reference in New Issue