Add contextual searches to playlists, library and global search. (#5649)
* Closes #5567: Contextual album/artist search in library search, global search, and playlists. * Change artist/album search to 'search for this' in globalsearch * Change artist/album search to 'search for this' in library * Applying patch from @Fat-Zer to allow search incl year * Re-adding missing schema definition
This commit is contained in:
parent
4aee29982e
commit
203ec76973
@ -471,6 +471,7 @@
|
||||
<file>schema/schema-4.sql</file>
|
||||
<file>schema/schema-5.sql</file>
|
||||
<file>schema/schema-50.sql</file>
|
||||
<file>schema/schema-51.sql</file>
|
||||
<file>schema/schema-6.sql</file>
|
||||
<file>schema/schema-7.sql</file>
|
||||
<file>schema/schema-8.sql</file>
|
||||
|
15
data/schema/schema-51.sql
Normal file
15
data/schema/schema-51.sql
Normal file
@ -0,0 +1,15 @@
|
||||
DELETE FROM %allsongstables_fts;
|
||||
|
||||
DROP TABLE %allsongstables_fts;
|
||||
|
||||
CREATE VIRTUAL TABLE %allsongstables_fts USING fts3( ftstitle, ftsalbum, ftsartist, ftsalbumartist,
|
||||
ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment, ftsyear,
|
||||
tokenize=unicode
|
||||
);
|
||||
|
||||
INSERT INTO %allsongstables_fts ( ROWID, ftstitle, ftsalbum, ftsartist, ftsalbumartist,
|
||||
ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment, ftsyear)
|
||||
SELECT ROWID, title, album, artist, albumartist, composer, performer, grouping, genre, comment, year
|
||||
FROM %allsongstables;
|
||||
|
||||
UPDATE schema_version SET version=51;
|
@ -47,7 +47,7 @@
|
||||
#include <QVariant>
|
||||
|
||||
const char* Database::kDatabaseFilename = "clementine.db";
|
||||
const int Database::kSchemaVersion = 50;
|
||||
const int Database::kSchemaVersion = 51;
|
||||
const char* Database::kMagicAllSongsTables = "%allsongstables";
|
||||
|
||||
int Database::sNextConnectionId = 1;
|
||||
|
@ -130,7 +130,8 @@ const QStringList Song::kFtsColumns = QStringList() << "ftstitle"
|
||||
<< "ftsperformer"
|
||||
<< "ftsgrouping"
|
||||
<< "ftsgenre"
|
||||
<< "ftscomment";
|
||||
<< "ftscomment"
|
||||
<< "ftsyear";
|
||||
|
||||
const QString Song::kFtsColumnSpec = Song::kFtsColumns.join(", ");
|
||||
const QString Song::kFtsBindSpec =
|
||||
@ -996,6 +997,7 @@ void Song::BindToFtsQuery(QSqlQuery* query) const {
|
||||
query->bindValue(":ftsgrouping", d->grouping_);
|
||||
query->bindValue(":ftsgenre", d->genre_);
|
||||
query->bindValue(":ftscomment", d->comment_);
|
||||
query->bindValue(":ftsyear", d->year_);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBLASTFM
|
||||
|
@ -36,9 +36,11 @@
|
||||
#include "core/logging.h"
|
||||
#include "core/mimedata.h"
|
||||
#include "core/timeconstants.h"
|
||||
#include "internet/core/internetsongmimedata.h"
|
||||
#include "library/libraryfilterwidget.h"
|
||||
#include "library/librarymodel.h"
|
||||
#include "library/groupbydialog.h"
|
||||
#include "playlist/songmimedata.h"
|
||||
|
||||
using std::placeholders::_1;
|
||||
using std::placeholders::_2;
|
||||
@ -446,34 +448,38 @@ bool GlobalSearchView::SearchKeyEvent(QKeyEvent* event) {
|
||||
}
|
||||
|
||||
bool GlobalSearchView::ResultsContextMenuEvent(QContextMenuEvent* event) {
|
||||
if (!context_menu_) {
|
||||
context_menu_ = new QMenu(this);
|
||||
context_actions_ << context_menu_->addAction(
|
||||
IconLoader::Load("media-playback-start", IconLoader::Base),
|
||||
tr("Append to current playlist"), this,
|
||||
SLOT(AddSelectedToPlaylist()));
|
||||
context_actions_ << context_menu_->addAction(
|
||||
IconLoader::Load("media-playback-start", IconLoader::Base),
|
||||
tr("Replace current playlist"), this,
|
||||
SLOT(LoadSelected()));
|
||||
context_actions_ << context_menu_->addAction(
|
||||
IconLoader::Load("document-new", IconLoader::Base),
|
||||
tr("Open in new playlist"), this,
|
||||
SLOT(OpenSelectedInNewPlaylist()));
|
||||
context_menu_ = new QMenu(this);
|
||||
context_actions_ << context_menu_->addAction(
|
||||
IconLoader::Load("media-playback-start", IconLoader::Base),
|
||||
tr("Append to current playlist"), this, SLOT(AddSelectedToPlaylist()));
|
||||
context_actions_ << context_menu_->addAction(
|
||||
IconLoader::Load("media-playback-start", IconLoader::Base),
|
||||
tr("Replace current playlist"), this, SLOT(LoadSelected()));
|
||||
context_actions_ << context_menu_->addAction(
|
||||
IconLoader::Load("document-new", IconLoader::Base),
|
||||
tr("Open in new playlist"), this, SLOT(OpenSelectedInNewPlaylist()));
|
||||
|
||||
context_menu_->addSeparator();
|
||||
context_actions_ << context_menu_->addAction(
|
||||
IconLoader::Load("go-next", IconLoader::Base), tr("Queue track"),
|
||||
this, SLOT(AddSelectedToPlaylistEnqueue()));
|
||||
context_menu_->addSeparator();
|
||||
context_actions_ << context_menu_->addAction(
|
||||
IconLoader::Load("go-next", IconLoader::Base), tr("Queue track"), this,
|
||||
SLOT(AddSelectedToPlaylistEnqueue()));
|
||||
|
||||
context_menu_->addSeparator();
|
||||
context_menu_->addMenu(tr("Group by"))
|
||||
->addActions(group_by_actions_->actions());
|
||||
context_menu_->addAction(IconLoader::Load("configure", IconLoader::Base),
|
||||
tr("Configure global search..."), this,
|
||||
SLOT(OpenSettingsDialog()));
|
||||
context_menu_->addSeparator();
|
||||
|
||||
if (ui_->results->selectionModel() &&
|
||||
ui_->results->selectionModel()->selectedRows().length() == 1) {
|
||||
context_actions_ << context_menu_->addAction(
|
||||
IconLoader::Load("system-search", IconLoader::Base),
|
||||
tr("Search for this"), this, SLOT(SearchForThis()));
|
||||
}
|
||||
|
||||
context_menu_->addSeparator();
|
||||
context_menu_->addMenu(tr("Group by"))
|
||||
->addActions(group_by_actions_->actions());
|
||||
context_menu_->addAction(IconLoader::Load("configure", IconLoader::Base),
|
||||
tr("Configure global search..."), this,
|
||||
SLOT(OpenSettingsDialog()));
|
||||
|
||||
const bool enable_context_actions =
|
||||
ui_->results->selectionModel() &&
|
||||
ui_->results->selectionModel()->hasSelection();
|
||||
@ -515,6 +521,11 @@ void GlobalSearchView::OpenSelectedInNewPlaylist() {
|
||||
emit AddToPlaylist(data);
|
||||
}
|
||||
|
||||
void GlobalSearchView::SearchForThis() {
|
||||
StartSearch(
|
||||
ui_->results->selectionModel()->selectedRows().first().data().toString());
|
||||
}
|
||||
|
||||
void GlobalSearchView::showEvent(QShowEvent* e) {
|
||||
if (show_suggestions_) {
|
||||
UpdateSuggestions();
|
||||
@ -560,9 +571,12 @@ void GlobalSearchView::GroupByClicked(QAction* action) {
|
||||
}
|
||||
|
||||
void GlobalSearchView::SetGroupBy(const LibraryModel::Grouping& g) {
|
||||
// Clear requests: changing "group by" on the models will cause all the items to be removed/added
|
||||
// again, so all the QModelIndex here will become invalid. New requests will be created for those
|
||||
// songs when they will be displayed again anyway (when GlobalSearchItemDelegate::paint will call
|
||||
// Clear requests: changing "group by" on the models will cause all the items
|
||||
// to be removed/added
|
||||
// again, so all the QModelIndex here will become invalid. New requests will
|
||||
// be created for those
|
||||
// songs when they will be displayed again anyway (when
|
||||
// GlobalSearchItemDelegate::paint will call
|
||||
// LazyLoadArt)
|
||||
art_requests_.clear();
|
||||
// Update the models
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "searchprovider.h"
|
||||
#include "library/librarymodel.h"
|
||||
#include "ui/settingsdialog.h"
|
||||
#include "playlist/playlistmanager.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
@ -82,6 +83,8 @@ signals:
|
||||
void OpenSelectedInNewPlaylist();
|
||||
void AddSelectedToPlaylistEnqueue();
|
||||
|
||||
void SearchForThis();
|
||||
|
||||
void GroupByClicked(QAction* action);
|
||||
void SetGroupBy(const LibraryModel::Grouping& grouping);
|
||||
|
||||
|
@ -656,6 +656,9 @@ QVariant LibraryModel::data(const LibraryItem* item, int role) const {
|
||||
|
||||
case Role_SortText:
|
||||
return item->SortText();
|
||||
|
||||
case Role_DisplayText:
|
||||
return item->DisplayText();
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ class LibraryModel : public SimpleTreeModel<LibraryItem> {
|
||||
Role_Type = Qt::UserRole + 1,
|
||||
Role_ContainerType,
|
||||
Role_SortText,
|
||||
Role_DisplayText,
|
||||
Role_Key,
|
||||
Role_Artist,
|
||||
Role_IsDivider,
|
||||
|
@ -103,7 +103,7 @@ void LibraryItemDelegate::paint(QPainter* painter,
|
||||
// Draw the line under the item
|
||||
QColor line_color = opt.palette.color(QPalette::Text);
|
||||
QLinearGradient grad_color(opt.rect.bottomLeft(), opt.rect.bottomRight());
|
||||
const double fade_start_end = (opt.rect.width()/3.0)/opt.rect.width();
|
||||
const double fade_start_end = (opt.rect.width() / 3.0) / opt.rect.width();
|
||||
line_color.setAlphaF(0.0);
|
||||
grad_color.setColorAt(0, line_color);
|
||||
line_color.setAlphaF(0.5);
|
||||
@ -193,15 +193,17 @@ LibraryView::~LibraryView() {}
|
||||
void LibraryView::SaveFocus() {
|
||||
QModelIndex current = currentIndex();
|
||||
QVariant type = model()->data(current, LibraryModel::Role_Type);
|
||||
if (!type.isValid() || !(type.toInt() == LibraryItem::Type_Song ||
|
||||
type.toInt() == LibraryItem::Type_Container ||
|
||||
type.toInt() == LibraryItem::Type_Divider)) {
|
||||
if (!type.isValid() ||
|
||||
!(type.toInt() == LibraryItem::Type_Song ||
|
||||
type.toInt() == LibraryItem::Type_Container ||
|
||||
type.toInt() == LibraryItem::Type_Divider)) {
|
||||
return;
|
||||
}
|
||||
|
||||
last_selected_path_.clear();
|
||||
last_selected_song_ = Song();
|
||||
last_selected_container_ = QString();
|
||||
last_selected_text_ = QString();
|
||||
|
||||
switch (type.toInt()) {
|
||||
case LibraryItem::Type_Song: {
|
||||
@ -210,6 +212,7 @@ void LibraryView::SaveFocus() {
|
||||
SongList songs = app_->library_model()->GetChildSongs(index);
|
||||
if (!songs.isEmpty()) {
|
||||
last_selected_song_ = songs.last();
|
||||
last_selected_text_ = songs.last().title();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -217,8 +220,9 @@ void LibraryView::SaveFocus() {
|
||||
case LibraryItem::Type_Container:
|
||||
case LibraryItem::Type_Divider: {
|
||||
QString text =
|
||||
model()->data(current, LibraryModel::Role_SortText).toString();
|
||||
model()->data(current, LibraryModel::Role_Key).toString();
|
||||
last_selected_container_ = text;
|
||||
last_selected_text_ = model()->data(current, LibraryModel::Role_DisplayText).toString();
|
||||
break;
|
||||
}
|
||||
|
||||
@ -232,8 +236,9 @@ void LibraryView::SaveFocus() {
|
||||
void LibraryView::SaveContainerPath(const QModelIndex& child) {
|
||||
QModelIndex current = model()->parent(child);
|
||||
QVariant type = model()->data(current, LibraryModel::Role_Type);
|
||||
if (!type.isValid() || !(type.toInt() == LibraryItem::Type_Container ||
|
||||
type.toInt() == LibraryItem::Type_Divider)) {
|
||||
if (!type.isValid() ||
|
||||
!(type.toInt() == LibraryItem::Type_Container ||
|
||||
type.toInt() == LibraryItem::Type_Divider)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -276,7 +281,7 @@ bool LibraryView::RestoreLevelFocus(const QModelIndex& parent) {
|
||||
case LibraryItem::Type_Container:
|
||||
case LibraryItem::Type_Divider: {
|
||||
QString text =
|
||||
model()->data(current, LibraryModel::Role_SortText).toString();
|
||||
model()->data(current, LibraryModel::Role_Key).toString();
|
||||
if (!last_selected_container_.isEmpty() &&
|
||||
last_selected_container_ == text) {
|
||||
emit expand(current);
|
||||
@ -384,11 +389,13 @@ void LibraryView::contextMenuEvent(QContextMenuEvent* e) {
|
||||
tr("Open in new playlist"), this, SLOT(OpenInNewPlaylist()));
|
||||
|
||||
context_menu_->addSeparator();
|
||||
add_to_playlist_enqueue_ =
|
||||
context_menu_->addAction(IconLoader::Load("go-next", IconLoader::Base),
|
||||
tr("Queue track"), this,
|
||||
SLOT(AddToPlaylistEnqueue()));
|
||||
|
||||
add_to_playlist_enqueue_ = context_menu_->addAction(
|
||||
IconLoader::Load("go-next", IconLoader::Base), tr("Queue track"), this,
|
||||
SLOT(AddToPlaylistEnqueue()));
|
||||
context_menu_->addSeparator();
|
||||
search_for_this_ = context_menu_->addAction(
|
||||
IconLoader::Load("system-search", IconLoader::Base),
|
||||
tr("Search for this"), this, SLOT(SearchForThis()));
|
||||
context_menu_->addSeparator();
|
||||
new_smart_playlist_ = context_menu_->addAction(
|
||||
IconLoader::Load("document-new", IconLoader::Base),
|
||||
@ -401,23 +408,23 @@ void LibraryView::contextMenuEvent(QContextMenuEvent* e) {
|
||||
tr("Delete smart playlist"), this, SLOT(DeleteSmartPlaylist()));
|
||||
|
||||
context_menu_->addSeparator();
|
||||
organise_ = context_menu_->addAction(IconLoader::Load("edit-copy", IconLoader::Base),
|
||||
tr("Organise files..."), this,
|
||||
SLOT(Organise()));
|
||||
organise_ = context_menu_->addAction(
|
||||
IconLoader::Load("edit-copy", IconLoader::Base),
|
||||
tr("Organise files..."), this, SLOT(Organise()));
|
||||
copy_to_device_ = context_menu_->addAction(
|
||||
IconLoader::Load("multimedia-player-ipod-mini-blue", IconLoader::Base),
|
||||
tr("Copy to device..."), this, SLOT(CopyToDevice()));
|
||||
delete_ = context_menu_->addAction(IconLoader::Load("edit-delete", IconLoader::Base),
|
||||
tr("Delete from disk..."), this,
|
||||
SLOT(Delete()));
|
||||
delete_ = context_menu_->addAction(
|
||||
IconLoader::Load("edit-delete", IconLoader::Base),
|
||||
tr("Delete from disk..."), this, SLOT(Delete()));
|
||||
|
||||
context_menu_->addSeparator();
|
||||
edit_track_ = context_menu_->addAction(IconLoader::Load("edit-rename", IconLoader::Base),
|
||||
tr("Edit track information..."),
|
||||
this, SLOT(EditTracks()));
|
||||
edit_tracks_ = context_menu_->addAction(IconLoader::Load("edit-rename", IconLoader::Base),
|
||||
tr("Edit tracks information..."),
|
||||
this, SLOT(EditTracks()));
|
||||
edit_track_ = context_menu_->addAction(
|
||||
IconLoader::Load("edit-rename", IconLoader::Base),
|
||||
tr("Edit track information..."), this, SLOT(EditTracks()));
|
||||
edit_tracks_ = context_menu_->addAction(
|
||||
IconLoader::Load("edit-rename", IconLoader::Base),
|
||||
tr("Edit tracks information..."), this, SLOT(EditTracks()));
|
||||
show_in_browser_ = context_menu_->addAction(
|
||||
IconLoader::Load("document-open-folder", IconLoader::Base),
|
||||
tr("Show in file browser..."), this, SLOT(ShowInBrowser()));
|
||||
@ -458,6 +465,8 @@ void LibraryView::contextMenuEvent(QContextMenuEvent* e) {
|
||||
int regular_elements = 0;
|
||||
// number of editable non smart playlists selected
|
||||
int regular_editable = 0;
|
||||
// number of container elements selected
|
||||
int container_elements = 0;
|
||||
|
||||
for (const QModelIndex& index : selected_indexes) {
|
||||
int type =
|
||||
@ -467,6 +476,10 @@ void LibraryView::contextMenuEvent(QContextMenuEvent* e) {
|
||||
smart_playlists++;
|
||||
} else if (type == LibraryItem::Type_PlaylistContainer) {
|
||||
smart_playlists_header++;
|
||||
} else if (type == LibraryItem::Type_Container) {
|
||||
container_elements++;
|
||||
// To preserve expected behavior, since a container is "regular"
|
||||
regular_elements++;
|
||||
} else {
|
||||
regular_elements++;
|
||||
}
|
||||
@ -487,6 +500,10 @@ void LibraryView::contextMenuEvent(QContextMenuEvent* e) {
|
||||
songs_selected == smart_playlists + smart_playlists_header;
|
||||
const bool only_smart_playlist_selected =
|
||||
smart_playlists == 1 && songs_selected == 1;
|
||||
const bool one_regular_song_only =
|
||||
regular_elements_only && container_elements == 0 && regular_elements == 1;
|
||||
const bool one_container_only =
|
||||
container_elements == 1 && songs_selected == 1;
|
||||
|
||||
// in all modes
|
||||
load_->setEnabled(songs_selected);
|
||||
@ -509,6 +526,9 @@ void LibraryView::contextMenuEvent(QContextMenuEvent* e) {
|
||||
show_in_various_->setVisible(regular_elements_only);
|
||||
no_show_in_various_->setVisible(regular_elements_only);
|
||||
|
||||
// only when a single container or one song is selected exclusively
|
||||
search_for_this_->setVisible(one_container_only || one_regular_song_only);
|
||||
|
||||
// only when all selected items are editable
|
||||
organise_->setEnabled(regular_elements == regular_editable);
|
||||
copy_to_device_->setEnabled(regular_elements == regular_editable);
|
||||
@ -714,6 +734,13 @@ void LibraryView::FilterReturnPressed() {
|
||||
emit doubleClicked(currentIndex());
|
||||
}
|
||||
|
||||
void LibraryView::SearchForThis() {
|
||||
SaveFocus();
|
||||
if (!last_selected_text_.isEmpty()) {
|
||||
filter_->ShowInLibrary(last_selected_text_.simplified());
|
||||
}
|
||||
}
|
||||
|
||||
void LibraryView::NewSmartPlaylist() {
|
||||
Wizard* wizard = new Wizard(app_, app_->library_backend(), this);
|
||||
wizard->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
@ -101,6 +101,8 @@ signals:
|
||||
void ShowInVarious();
|
||||
void NoShowInVarious();
|
||||
|
||||
void SearchForThis();
|
||||
|
||||
void NewSmartPlaylist();
|
||||
void EditSmartPlaylist();
|
||||
void DeleteSmartPlaylist();
|
||||
@ -139,6 +141,8 @@ signals:
|
||||
QAction* show_in_various_;
|
||||
QAction* no_show_in_various_;
|
||||
|
||||
QAction* search_for_this_;
|
||||
|
||||
QAction* new_smart_playlist_;
|
||||
QAction* edit_smart_playlist_;
|
||||
QAction* delete_smart_playlist_;
|
||||
@ -151,6 +155,7 @@ signals:
|
||||
// Save focus
|
||||
Song last_selected_song_;
|
||||
QString last_selected_container_;
|
||||
QString last_selected_text_;
|
||||
QSet<QString> last_selected_path_;
|
||||
};
|
||||
|
||||
|
@ -676,7 +676,13 @@ MainWindow::MainWindow(Application* app, SystemTrayIcon* tray_icon, OSD* osd,
|
||||
ui_->playlist->addAction(playlist_queue_);
|
||||
playlist_skip_ = playlist_menu_->addAction("", this, SLOT(PlaylistSkip()));
|
||||
ui_->playlist->addAction(playlist_skip_);
|
||||
|
||||
playlist_menu_->addSeparator();
|
||||
search_for_artist_ = playlist_menu_->addAction(
|
||||
IconLoader::Load("system-search", IconLoader::Base),
|
||||
tr("Search for artist"), this, SLOT(SearchForArtist()));
|
||||
search_for_album_ = playlist_menu_->addAction(
|
||||
IconLoader::Load("system-search", IconLoader::Base),
|
||||
tr("Search for album"), this, SLOT(SearchForAlbum()));
|
||||
playlist_menu_->addSeparator();
|
||||
playlist_menu_->addAction(ui_->action_remove_from_playlist);
|
||||
playlist_undoredo_ = playlist_menu_->addSeparator();
|
||||
@ -1733,6 +1739,9 @@ void MainWindow::PlaylistRightClick(const QPoint& global_pos,
|
||||
playlist_delete_->setVisible(false);
|
||||
playlist_copy_to_device_->setVisible(false);
|
||||
|
||||
search_for_artist_->setVisible(all == 1);
|
||||
search_for_album_->setVisible(all == 1);
|
||||
|
||||
if (in_queue == 1 && not_in_queue == 0)
|
||||
playlist_queue_->setText(tr("Dequeue track"));
|
||||
else if (in_queue > 1 && not_in_queue == 0)
|
||||
@ -2484,6 +2493,26 @@ void MainWindow::PlaylistCopyToDevice() {
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::SearchForArtist() {
|
||||
PlaylistItemPtr item(
|
||||
app_->playlist_manager()->current()->item_at(playlist_menu_index_.row()));
|
||||
Song song = item->Metadata();
|
||||
if (!song.albumartist().isEmpty()) {
|
||||
DoGlobalSearch(song.albumartist().simplified());
|
||||
} else if (!song.artist().isEmpty()) {
|
||||
DoGlobalSearch(song.artist().simplified());
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::SearchForAlbum() {
|
||||
PlaylistItemPtr item(
|
||||
app_->playlist_manager()->current()->item_at(playlist_menu_index_.row()));
|
||||
Song song = item->Metadata();
|
||||
if (!song.album().isEmpty()) {
|
||||
DoGlobalSearch(song.album().simplified());
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::ChangeLibraryQueryMode(QAction* action) {
|
||||
if (action == library_show_duplicates_) {
|
||||
library_view_->filter()->SetQueryMode(QueryOptions::QueryMode_Duplicates);
|
||||
|
@ -147,7 +147,6 @@ signals:
|
||||
void StopAfterToggled(bool stop);
|
||||
|
||||
void IntroPointReached();
|
||||
|
||||
private slots:
|
||||
void FilePathChanged(const QString& path);
|
||||
|
||||
@ -178,6 +177,9 @@ signals:
|
||||
void PlaylistUndoRedoChanged(QAction* undo, QAction* redo);
|
||||
void AddFilesToTranscoder();
|
||||
|
||||
void SearchForArtist();
|
||||
void SearchForAlbum();
|
||||
|
||||
void PlaylistCopyToLibrary();
|
||||
void PlaylistMoveToLibrary();
|
||||
void PlaylistCopyToDevice();
|
||||
@ -365,6 +367,9 @@ signals:
|
||||
QAction* playlistitem_actions_separator_;
|
||||
QModelIndex playlist_menu_index_;
|
||||
|
||||
QAction* search_for_artist_;
|
||||
QAction* search_for_album_;
|
||||
|
||||
QSortFilterProxyModel* library_sort_model_;
|
||||
|
||||
QTimer* track_position_timer_;
|
||||
|
Loading…
x
Reference in New Issue
Block a user