Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

shortkeys for track list management #12020

Merged
merged 17 commits into from
Mar 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1141,6 +1141,7 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL
src/track/trackref.cpp
src/util/battery/battery.cpp
src/util/cache.cpp
src/util/clipboard.cpp
src/util/cmdlineargs.cpp
src/util/color/color.cpp
src/util/color/colorpalette.cpp
Expand Down
4 changes: 4 additions & 0 deletions src/coreservices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "skin/skincontrols.h"
#include "soundio/soundmanager.h"
#include "sources/soundsourceproxy.h"
#include "util/clipboard.h"
#include "util/db/dbconnectionpooled.h"
#include "util/font.h"
#include "util/logger.h"
Expand Down Expand Up @@ -335,6 +336,7 @@ void CoreServices::initialize(QApplication* pApp) {

emit initializationProgressUpdate(50, tr("library"));
CoverArtCache::createInstance();
Clipboard::createInstance();

m_pTrackCollectionManager = std::make_shared<TrackCollectionManager>(
this,
Expand Down Expand Up @@ -580,6 +582,8 @@ void CoreServices::finalize() {
// CoverArtCache is fairly independent of everything else.
CoverArtCache::destroy();

Clipboard::destroy();

// PlayerManager depends on Engine, SoundManager, VinylControlManager, and Config
// The player manager has to be deleted before the library to ensure
// that all modified track metadata of loaded tracks is saved.
Expand Down
10 changes: 10 additions & 0 deletions src/library/autodj/autodjfeature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include "moc_autodjfeature.cpp"
#include "sources/soundsourceproxy.h"
#include "track/track.h"
#include "util/clipboard.h"
#include "util/dnd.h"
#include "widget/wlibrary.h"
#include "widget/wlibrarysidebar.h"

Expand Down Expand Up @@ -161,6 +163,14 @@ void AutoDJFeature::activate() {
emit enableCoverArtDisplay(true);
}

void AutoDJFeature::clear() {
m_playlistDao.clearAutoDJQueue();
}

void AutoDJFeature::paste() {
emit pasteFromSidebar();
}

bool AutoDJFeature::dropAccept(const QList<QUrl>& urls, QObject* pSource) {
// If a track is dropped onto the Auto DJ tree node, but the track isn't in the
// library, then add the track to the library before adding it to the
Expand Down
3 changes: 3 additions & 0 deletions src/library/autodj/autodjfeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ class AutoDJFeature : public LibraryFeature {

QVariant title() override;

void clear() override;
void paste() override;

bool dropAccept(const QList<QUrl>& urls, QObject* pSource) override;
bool dragMoveAccept(const QUrl& url) override;

Expand Down
4 changes: 4 additions & 0 deletions src/library/autodj/dlgautodj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,10 @@ void DlgAutoDJ::setFocus() {
m_pTrackTableView->setFocus();
}

void DlgAutoDJ::pasteFromSidebar() {
m_pTrackTableView->pasteFromSidebar();
}

void DlgAutoDJ::keyPressEvent(QKeyEvent* pEvent) {
// If we receive key events either the mode selector or the spinbox are focused.
// Return, Enter and Escape move focus back to the previously focused
Expand Down
1 change: 1 addition & 0 deletions src/library/autodj/dlgautodj.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class DlgAutoDJ : public QWidget, public Ui::DlgAutoDJ, public LibraryView {
void onShow() override;
bool hasFocus() const override;
void setFocus() override;
void pasteFromSidebar() override;
void onSearch(const QString& text) override;
void activateSelectedTrack() override;
void loadSelectedTrackToGroup(const QString& group, bool play) override;
Expand Down
54 changes: 54 additions & 0 deletions src/library/basetracktablemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "moc_basetracktablemodel.cpp"
#include "track/track.h"
#include "util/assert.h"
#include "util/clipboard.h"
#include "util/datetime.h"
#include "util/db/sqlite.h"
#include "util/logger.h"
Expand Down Expand Up @@ -380,6 +381,59 @@ int BaseTrackTableModel::columnCount(const QModelIndex& parent) const {
return countValidColumnHeaders();
}

void BaseTrackTableModel::cutTracks(const QModelIndexList& indices) {
copyTracks(indices);
removeTracks(indices);
}

void BaseTrackTableModel::copyTracks(const QModelIndexList& indices) const {
Clipboard::start();
for (const QModelIndex& index : indices) {
if (index.isValid()) {
Clipboard::add(QUrl::fromLocalFile(getTrackLocation(index)));
}
}
Clipboard::finish();
}

QList<int> BaseTrackTableModel::pasteTracks(const QModelIndex& insertionIndex) {
// Don't paste into locked playlists and crates or into into History
if (isLocked() || !hasCapabilities(TrackModel::Capability::ReceiveDrops)) {
return QList<int>{};
}

int insertionPos = 0;
const QList<QUrl> urls = Clipboard::urls();
const QList<TrackId> trackIds = m_pTrackCollectionManager->resolveTrackIdsFromUrls(urls, true);
if (!trackIds.isEmpty()) {
addTracksWithTrackIds(insertionIndex, trackIds, &insertionPos);
}

QList<int> rows;
for (const auto& trackId : trackIds) {
const auto trackRows = getTrackRows(trackId);
for (int trackRow : trackRows) {
if (insertionPos == 0) {
rows.append(trackRow);
} else {
int pos =
index(
trackRow,
fieldIndex(ColumnCache::
COLUMN_PLAYLISTTRACKSTABLE_POSITION))
.data()
.toInt();
// trackRows includes all instances in the table of the pasted
// tracks. We only want to select the ones we just inserted
if (pos >= insertionPos && pos < insertionPos + trackIds.size()) {
rows.append(trackRow);
}
}
}
}
return rows;
}

bool BaseTrackTableModel::isColumnHiddenByDefault(
int column) {
return column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_ALBUMARTIST) ||
Expand Down
4 changes: 4 additions & 0 deletions src/library/basetracktablemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ class BaseTrackTableModel : public QAbstractTableModel, public TrackModel {
return m_columnCache.fieldIndex(fieldName);
}

void cutTracks(const QModelIndexList& indices) override;
void copyTracks(const QModelIndexList& indices) const override;
QList<int> pasteTracks(const QModelIndex& index) override;

bool isColumnHiddenByDefault(
int column) override;

Expand Down
15 changes: 15 additions & 0 deletions src/library/browse/browsetablemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "moc_browsetablemodel.cpp"
#include "recording/recordingmanager.h"
#include "track/track.h"
#include "util/clipboard.h"
#include "widget/wlibrarytableview.h"

namespace {
Expand Down Expand Up @@ -314,6 +315,20 @@ bool BrowseTableModel::isColumnHiddenByDefault(int column) {
void BrowseTableModel::moveTrack(const QModelIndex&, const QModelIndex&) {
}

void BrowseTableModel::copyTracks(const QModelIndexList& indices) const {
Clipboard::start();
for (const QModelIndex& index : indices) {
if (index.isValid()) {
Clipboard::add(QUrl::fromLocalFile(getTrackLocation(index)));
}
}
Clipboard::finish();

// TODO Investigate if we can also implement cut and paste (via QFile
// operations) so mixxx could manage files in the filesystem, rather than
// having to go switch between mixxx and the system file browser.
}

ronso0 marked this conversation as resolved.
Show resolved Hide resolved
void BrowseTableModel::removeTracks(const QModelIndexList&) {
}

Expand Down
1 change: 1 addition & 0 deletions src/library/browse/browsetablemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class BrowseTableModel final : public QStandardItemModel, public virtual TrackMo
const QString currentSearch() const override;
bool isColumnInternal(int) override;
void moveTrack(const QModelIndex&, const QModelIndex&) override;
void copyTracks(const QModelIndexList& indices) const override;
bool isLocked() override { return false; }
bool isColumnHiddenByDefault(int column) override;
const QList<int>& searchColumns() const override;
Expand Down
10 changes: 10 additions & 0 deletions src/library/dao/playlistdao.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,16 @@ int PlaylistDAO::insertTracksIntoPlaylist(const QList<TrackId>& trackIds,
return tracksAdded;
}

void PlaylistDAO::clearAutoDJQueue() {
const int iAutoDJPlaylistId = getPlaylistIdFromName(AUTODJ_TABLE);
// If the first track is already loaded to the player,
// alter the playlist only below the first track
const int position =
(m_pAutoDJProcessor && m_pAutoDJProcessor->nextTrackLoaded()) ? 2 : 1;

removeTracksFromPlaylist(iAutoDJPlaylistId, position);
}

void PlaylistDAO::addPlaylistToAutoDJQueue(const int playlistId, AutoDJSendLoc loc) {
//qDebug() << "Adding tracks from playlist " << playlistId << " to the Auto-DJ Queue";

Expand Down
2 changes: 2 additions & 0 deletions src/library/dao/playlistdao.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ class PlaylistDAO : public QObject, public virtual DAO {
bool insertTrackIntoPlaylist(TrackId trackId, int playlistId, int position);
// Inserts a list of tracks into playlist
int insertTracksIntoPlaylist(const QList<TrackId>& trackIds, const int playlistId, int position);
// Remove all tracks from the Auto-DJ Queue
void clearAutoDJQueue();
// Add a playlist to the Auto-DJ Queue
void addPlaylistToAutoDJQueue(const int playlistId, AutoDJSendLoc loc);
// Add a list of tracks to the Auto-DJ Queue
Expand Down
16 changes: 14 additions & 2 deletions src/library/library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,10 @@ void Library::bindLibraryWidget(
&Library::showTrackModel,
pTrackTableView,
&WTrackTableView::loadTrackModel);
connect(this,
&Library::pasteFromSidebar,
m_pLibraryWidget,
&WLibrary::pasteFromSidebar);
connect(pTrackTableView,
&WTrackTableView::loadTrack,
this,
Expand All @@ -399,6 +403,10 @@ void Library::bindLibraryWidget(
&Library::slotLoadTrackToPlayer);
m_pLibraryWidget->registerView(m_sTrackViewName, pTrackTableView);

connect(m_pLibraryWidget,
&WLibrary::setLibraryFocus,
m_pLibraryControl,
&LibraryControl::setLibraryFocus);
connect(this,
&Library::switchToView,
m_pLibraryWidget,
Expand Down Expand Up @@ -461,6 +469,10 @@ void Library::addFeature(LibraryFeature* feature) {
}
m_features.push_back(feature);
m_pSidebarModel->addLibraryFeature(feature);
connect(feature,
&LibraryFeature::pasteFromSidebar,
this,
&Library::pasteFromSidebar);
connect(feature,
&LibraryFeature::showTrackModel,
this,
Expand Down Expand Up @@ -517,7 +529,7 @@ void Library::onPlayerManagerTrackAnalyzerIdle() {
}

void Library::slotShowTrackModel(QAbstractItemModel* model) {
//qDebug() << "Library::slotShowTrackModel" << model;
// qDebug() << "Library::slotShowTrackModel" << model;
TrackModel* trackModel = dynamic_cast<TrackModel*>(model);
VERIFY_OR_DEBUG_ASSERT(trackModel) {
return;
Expand All @@ -528,7 +540,7 @@ void Library::slotShowTrackModel(QAbstractItemModel* model) {
}

void Library::slotSwitchToView(const QString& view) {
//qDebug() << "Library::slotSwitchToView" << view;
// qDebug() << "Library::slotSwitchToView" << view;
emit switchToView(view);
}

Expand Down
1 change: 1 addition & 0 deletions src/library/library.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ class Library: public QObject {
void restoreSearch(const QString&);
void search(const QString& text);
void disableSearch();
void pasteFromSidebar();
// emit this signal to enable/disable the cover art widget
void enableCoverArtDisplay(bool);
void selectTrack(const TrackId&);
Expand Down
8 changes: 8 additions & 0 deletions src/library/libraryfeature.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ class LibraryFeature : public QObject {
return false;
}

virtual void clear() {
}
virtual void paste() {
}
virtual void pasteChild(const QModelIndex& index) {
Q_UNUSED(index);
}
// Reimplement this to register custom views with the library widget.
virtual void bindLibraryWidget(WLibrary* /* libraryWidget */,
KeyboardEventFilter* /* keyboard */) {}
Expand Down Expand Up @@ -135,6 +142,7 @@ class LibraryFeature : public QObject {
void restoreModelState();
void restoreSearch(const QString&);
void disableSearch();
void pasteFromSidebar();
// emit this signal before you parse a large music collection, e.g., iTunes, Traktor.
// The second arg indicates if the feature should be "selected" when loading starts
void featureIsLoading(LibraryFeature*, bool selectFeature);
Expand Down
3 changes: 3 additions & 0 deletions src/library/libraryview.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ class LibraryView {
/// Reimplement if LibraryView should be able to search
virtual void onSearch(const QString& text) {Q_UNUSED(text);}

virtual void pasteFromSidebar() {
}

/// If applicable, requests that the LibraryView load the selected
/// track. Does nothing otherwise.
virtual void activateSelectedTrack() {
Expand Down
25 changes: 15 additions & 10 deletions src/library/playlisttablemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,30 +189,35 @@ void PlaylistTableModel::selectPlaylist(int playlistId) {
setSort(defaultSortColumn(), defaultSortOrder());
}

int PlaylistTableModel::addTracks(const QModelIndex& index,
const QList<QString>& locations) {
if (locations.isEmpty()) {
int PlaylistTableModel::addTracksWithTrackIds(const QModelIndex& insertionIndex,
const QList<TrackId>& trackIds,
int* pOutInsertionPos) {
if (trackIds.isEmpty()) {
return 0;
}

QList<TrackId> trackIds = m_pTrackCollectionManager->resolveTrackIdsFromLocations(
locations);

const int positionColumn = fieldIndex(ColumnCache::COLUMN_PLAYLISTTRACKSTABLE_POSITION);
int position = index.sibling(index.row(), positionColumn).data().toInt();
int position = index(insertionIndex.row(), positionColumn).data().toInt();

// Handle weird cases like a drag and drop to an invalid index
if (position <= 0) {
position = rowCount() + 1;
}

if (pOutInsertionPos) {
*pOutInsertionPos = position;
}

int tracksAdded = m_pTrackCollectionManager->internalCollection()->getPlaylistDAO().insertTracksIntoPlaylist(
trackIds, m_iPlaylistId, position);

if (locations.size() - tracksAdded > 0) {
if (trackIds.size() - tracksAdded > 0) {
QString playlistName = m_pTrackCollectionManager->internalCollection()
->getPlaylistDAO()
.getPlaylistName(m_iPlaylistId);
qDebug() << "PlaylistTableModel::addTracks could not add"
<< locations.size() - tracksAdded
<< "to playlist" << m_iPlaylistId;
<< trackIds.size() - tracksAdded
ronso0 marked this conversation as resolved.
Show resolved Hide resolved
<< "to playlist id" << m_iPlaylistId << "name" << playlistName;
}
return tracksAdded;
}
Expand Down
4 changes: 3 additions & 1 deletion src/library/playlisttablemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ class PlaylistTableModel final : public TrackSetTableModel {
/// This function should only be used by AUTODJ
void removeTracks(const QModelIndexList& indices) final;
/// Returns the number of successful additions.
int addTracks(const QModelIndex& index, const QList<QString>& locations) final;
int addTracksWithTrackIds(const QModelIndex& index,
const QList<TrackId>& trackIds,
int* pOutInsertionPos) final;
bool isLocked() final;

/// Get the total duration of all tracks referenced by the given model indices
Expand Down
11 changes: 11 additions & 0 deletions src/library/proxytrackmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,17 @@ void ProxyTrackModel::removeTracks(const QModelIndexList& indices) {
}
}

void ProxyTrackModel::copyTracks(const QModelIndexList& indices) const {
QModelIndexList translatedList;
foreach (QModelIndex index, indices) {
QModelIndex indexSource = mapToSource(index);
translatedList.append(indexSource);
}
if (m_pTrackModel) {
m_pTrackModel->copyTracks(translatedList);
}
}

void ProxyTrackModel::moveTrack(const QModelIndex& sourceIndex,
const QModelIndex& destIndex) {
QModelIndex sourceIndexSource = mapToSource(sourceIndex);
Expand Down
Loading
Loading