From 1cd0d0503da05173721050114a7ee118a9d57799 Mon Sep 17 00:00:00 2001 From: m0dB <79429057+m0dB@users.noreply.github.com> Date: Sun, 25 Jun 2023 18:24:44 +0200 Subject: [PATCH] shortkey for clear/cut/copy/paste tracks (library, playlists, crates and autodj), for quick focus change between sidebar and tableview, for unselecting all tracks; add method to add tracks by id --- CMakeLists.txt | 1 + src/library/basetracktablemodel.cpp | 25 +++++ src/library/basetracktablemodel.h | 4 + src/library/library.cpp | 4 + src/library/playlisttablemodel.cpp | 13 +-- src/library/playlisttablemodel.h | 2 +- src/library/sidebarmodel.cpp | 6 +- src/library/trackmodel.h | 15 +++ src/library/trackset/baseplaylistfeature.cpp | 2 +- src/library/trackset/baseplaylistfeature.h | 2 +- .../trackset/crate/cratetablemodel.cpp | 8 +- src/library/trackset/crate/cratetablemodel.h | 2 +- src/library/trackset/tracksettablemodel.cpp | 12 +++ src/library/trackset/tracksettablemodel.h | 2 + src/util/clipboard.cpp | 35 +++++++ src/util/clipboard.h | 14 +++ src/widget/wlibrary.cpp | 6 ++ src/widget/wlibrary.h | 5 + src/widget/wlibrarysidebar.cpp | 8 ++ src/widget/wlibrarytableview.cpp | 5 +- src/widget/wlibrarytableview.h | 2 + src/widget/wlibrarytextbrowser.cpp | 10 ++ src/widget/wlibrarytextbrowser.h | 4 + src/widget/wtracktableview.cpp | 94 ++++++++++++++++++- src/widget/wtracktableview.h | 5 + 25 files changed, 260 insertions(+), 26 deletions(-) create mode 100644 src/util/clipboard.cpp create mode 100644 src/util/clipboard.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 54c16263a1c..8cb2c1cd469 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1008,6 +1008,7 @@ add_library(mixxx-lib STATIC EXCLUDE_FROM_ALL src/track/taglib/trackmetadata_xiph.cpp src/util/battery/battery.cpp src/util/cache.cpp + src/util/clipboard.cpp src/util/cmdlineargs.cpp src/util/colorcomponents.cpp src/util/color/color.cpp diff --git a/src/library/basetracktablemodel.cpp b/src/library/basetracktablemodel.cpp index e3414e29338..7450875ca16 100644 --- a/src/library/basetracktablemodel.cpp +++ b/src/library/basetracktablemodel.cpp @@ -19,6 +19,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" @@ -362,6 +363,30 @@ 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::begin(); + for (const QModelIndex& index : indices) { + if (index.isValid()) { + Clipboard::add(QUrl::fromLocalFile(getTrackLocation(index))); + } + } + Clipboard::end(); +} + +int BaseTrackTableModel::pasteTracks(const QModelIndex& insertionIndex) { + const QList urls = Clipboard::urls(); + const QList trackIds = m_pTrackCollectionManager->resolveTrackIdsFromUrls(urls, false); + if (trackIds.isEmpty()) { + return 0; + } + return addTracksWithTrackIds(insertionIndex, trackIds); +} + bool BaseTrackTableModel::isColumnHiddenByDefault( int column) { return column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_ALBUMARTIST) || diff --git a/src/library/basetracktablemodel.h b/src/library/basetracktablemodel.h index 9b258e3dce3..b61a44a2add 100644 --- a/src/library/basetracktablemodel.h +++ b/src/library/basetracktablemodel.h @@ -82,6 +82,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; + int pasteTracks(const QModelIndex& index) override; + bool isColumnHiddenByDefault( int column) override; diff --git a/src/library/library.cpp b/src/library/library.cpp index 7d6f50ad1a4..69562b2226e 100644 --- a/src/library/library.cpp +++ b/src/library/library.cpp @@ -404,6 +404,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, diff --git a/src/library/playlisttablemodel.cpp b/src/library/playlisttablemodel.cpp index c8ce2dead4f..d7cdda73774 100644 --- a/src/library/playlisttablemodel.cpp +++ b/src/library/playlisttablemodel.cpp @@ -189,15 +189,12 @@ void PlaylistTableModel::selectPlaylist(int playlistId) { setSort(defaultSortColumn(), defaultSortOrder()); } -int PlaylistTableModel::addTracks(const QModelIndex& index, - const QList& locations) { - if (locations.isEmpty()) { +int PlaylistTableModel::addTracksWithTrackIds(const QModelIndex& index, + const QList& trackIds) { + if (trackIds.isEmpty()) { return 0; } - QList trackIds = m_pTrackCollectionManager->resolveTrackIdsFromLocations( - locations); - const int positionColumn = fieldIndex(ColumnCache::COLUMN_PLAYLISTTRACKSTABLE_POSITION); int position = index.sibling(index.row(), positionColumn).data().toInt(); @@ -209,9 +206,9 @@ int PlaylistTableModel::addTracks(const QModelIndex& index, int tracksAdded = m_pTrackCollectionManager->internalCollection()->getPlaylistDAO().insertTracksIntoPlaylist( trackIds, m_iPlaylistId, position); - if (locations.size() - tracksAdded > 0) { + if (trackIds.size() - tracksAdded > 0) { qDebug() << "PlaylistTableModel::addTracks could not add" - << locations.size() - tracksAdded + << trackIds.size() - tracksAdded << "to playlist" << m_iPlaylistId; } return tracksAdded; diff --git a/src/library/playlisttablemodel.h b/src/library/playlisttablemodel.h index bc68c9cf7c8..e5af3deca58 100644 --- a/src/library/playlisttablemodel.h +++ b/src/library/playlisttablemodel.h @@ -25,7 +25,7 @@ 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& locations) final; + int addTracksWithTrackIds(const QModelIndex& index, const QList& trackIds) final; bool isLocked() final; Capabilities getCapabilities() const final; diff --git a/src/library/sidebarmodel.cpp b/src/library/sidebarmodel.cpp index e0539fd95d9..1d2d6a9d8c9 100644 --- a/src/library/sidebarmodel.cpp +++ b/src/library/sidebarmodel.cpp @@ -477,7 +477,7 @@ QModelIndex SidebarModel::translateIndex( } void SidebarModel::slotDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight) { - //qDebug() << "slotDataChanged topLeft:" << topLeft << "bottomRight:" << bottomRight; + // qDebug() << "slotDataChanged topLeft:" << topLeft << "bottomRight:" << bottomRight; QModelIndex topLeftTranslated = translateSourceIndex(topLeft); QModelIndex bottomRightTranslated = translateSourceIndex(bottomRight); emit dataChanged(topLeftTranslated, bottomRightTranslated); @@ -501,8 +501,8 @@ void SidebarModel::slotRowsInserted(const QModelIndex& parent, int start, int en Q_UNUSED(parent); Q_UNUSED(start); Q_UNUSED(end); - //qDebug() << "slotRowsInserted" << parent << start << end; - //QModelIndex newParent = translateSourceIndex(parent); + // qDebug() << "slotRowsInserted" << parent << start << end; + // QModelIndex newParent = translateSourceIndex(parent); endInsertRows(); } diff --git a/src/library/trackmodel.h b/src/library/trackmodel.h index c811114709a..cca0a04bd87 100644 --- a/src/library/trackmodel.h +++ b/src/library/trackmodel.h @@ -140,6 +140,16 @@ class TrackModel { virtual void removeTracks(const QModelIndexList& indices) { Q_UNUSED(indices); } + virtual void cutTracks(const QModelIndexList& indices) { + Q_UNUSED(indices); + } + virtual void copyTracks(const QModelIndexList& indices) const { + Q_UNUSED(indices); + } + virtual int pasteTracks(const QModelIndex& index) { + Q_UNUSED(index); + return 0; + } virtual void hideTracks(const QModelIndexList& indices) { Q_UNUSED(indices); } @@ -154,6 +164,11 @@ class TrackModel { Q_UNUSED(locations); return 0; } + virtual int addTracksWithTrackIds(const QModelIndex& index, const QList& tracks) { + Q_UNUSED(index); + Q_UNUSED(tracks); + return 0; + } virtual void moveTrack(const QModelIndex& sourceIndex, const QModelIndex& destIndex) { Q_UNUSED(sourceIndex); diff --git a/src/library/trackset/baseplaylistfeature.cpp b/src/library/trackset/baseplaylistfeature.cpp index 30ca7cc4a98..eb3d5e1279e 100644 --- a/src/library/trackset/baseplaylistfeature.cpp +++ b/src/library/trackset/baseplaylistfeature.cpp @@ -169,7 +169,7 @@ void BasePlaylistFeature::connectPlaylistDAO() { &BasePlaylistFeature::slotPlaylistTableRenamed); } -int BasePlaylistFeature::playlistIdFromIndex(const QModelIndex& index) { +int BasePlaylistFeature::playlistIdFromIndex(const QModelIndex& index) const { TreeItem* item = static_cast(index.internalPointer()); if (item == nullptr) { return kInvalidPlaylistId; diff --git a/src/library/trackset/baseplaylistfeature.h b/src/library/trackset/baseplaylistfeature.h index 3eb0829e6cb..2dab348a4f7 100644 --- a/src/library/trackset/baseplaylistfeature.h +++ b/src/library/trackset/baseplaylistfeature.h @@ -90,7 +90,7 @@ class BasePlaylistFeature : public BaseTrackSetFeature { virtual void decorateChild(TreeItem* pChild, int playlistId) = 0; virtual void addToAutoDJ(PlaylistDAO::AutoDJSendLoc loc); - int playlistIdFromIndex(const QModelIndex& index); + int playlistIdFromIndex(const QModelIndex& index) const; // Get the QModelIndex of a playlist based on its id. Returns QModelIndex() // on failure. QModelIndex indexFromPlaylistId(int playlistId); diff --git a/src/library/trackset/crate/cratetablemodel.cpp b/src/library/trackset/crate/cratetablemodel.cpp index 43c5a6c59d7..cc79f615d47 100644 --- a/src/library/trackset/crate/cratetablemodel.cpp +++ b/src/library/trackset/crate/cratetablemodel.cpp @@ -150,17 +150,15 @@ TrackModel::Capabilities CrateTableModel::getCapabilities() const { return caps; } -int CrateTableModel::addTracks( - const QModelIndex& index, const QList& locations) { +int CrateTableModel::addTracksWithTrackIds( + const QModelIndex& index, const QList& trackIds) { Q_UNUSED(index); // If a track is dropped but it isn't in the library, then add it because // the user probably dropped a file from outside Mixxx into this crate. - QList trackIds = - m_pTrackCollectionManager->resolveTrackIdsFromLocations(locations); if (!m_pTrackCollectionManager->internalCollection()->addCrateTracks( m_selectedCrate, trackIds)) { qWarning() << "CrateTableModel::addTracks could not add" - << locations.size() << "tracks to crate" << m_selectedCrate; + << trackIds.size() << "tracks to crate" << m_selectedCrate; return 0; } diff --git a/src/library/trackset/crate/cratetablemodel.h b/src/library/trackset/crate/cratetablemodel.h index f146464bf4f..a509a501879 100644 --- a/src/library/trackset/crate/cratetablemodel.h +++ b/src/library/trackset/crate/cratetablemodel.h @@ -20,7 +20,7 @@ class CrateTableModel final : public TrackSetTableModel { void removeTracks(const QModelIndexList& indices) final; /// Returns the number of unsuccessful additions. - int addTracks(const QModelIndex& index, const QList& locations) final; + int addTracksWithTrackIds(const QModelIndex& index, const QList& tracks) final; Capabilities getCapabilities() const final; QString modelKey(bool noSearch) const override; diff --git a/src/library/trackset/tracksettablemodel.cpp b/src/library/trackset/tracksettablemodel.cpp index f27bd25efae..67e113e5ca2 100644 --- a/src/library/trackset/tracksettablemodel.cpp +++ b/src/library/trackset/tracksettablemodel.cpp @@ -26,3 +26,15 @@ bool TrackSetTableModel::isColumnInternal(int column) { column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COVERART_DIGEST) || column == fieldIndex(ColumnCache::COLUMN_LIBRARYTABLE_COVERART_HASH); } + +int TrackSetTableModel::addTracks(const QModelIndex& index, + const QList& locations) { + if (locations.isEmpty()) { + return 0; + } + + QList trackIds = m_pTrackCollectionManager->resolveTrackIdsFromLocations( + locations); + + return addTracksWithTrackIds(index, trackIds); +} diff --git a/src/library/trackset/tracksettablemodel.h b/src/library/trackset/tracksettablemodel.h index 649d33ef325..94202c9a853 100644 --- a/src/library/trackset/tracksettablemodel.h +++ b/src/library/trackset/tracksettablemodel.h @@ -11,4 +11,6 @@ class TrackSetTableModel : public BaseSqlTableModel { const char* settingsNamespace); bool isColumnInternal(int column) override; + + int addTracks(const QModelIndex& index, const QList& locations) final; }; diff --git a/src/util/clipboard.cpp b/src/util/clipboard.cpp new file mode 100644 index 00000000000..671edeb1840 --- /dev/null +++ b/src/util/clipboard.cpp @@ -0,0 +1,35 @@ +#include "clipboard.h" + +#include +#include + +QString& Clipboard::text() { + static QString s_text; + return s_text; +} + +void Clipboard::begin() { + text() = ""; +} + +void Clipboard::add(const QUrl& url) { + text().append(url.toString() + "\n"); +} + +void Clipboard::end() { + QApplication::clipboard()->setText(text()); +} + +QList Clipboard::urls() { + const QString text = QApplication::clipboard()->text(); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + QStringList strings = text.split("\n", Qt::SkipEmptyParts); +#else + QStringList strings = text.split("\n", QString::SkipEmptyParts); +#endif + QList result; + for (QString string : strings) { + result.append(QUrl(string)); + } + return result; +} diff --git a/src/util/clipboard.h b/src/util/clipboard.h new file mode 100644 index 00000000000..92e89ff2f2a --- /dev/null +++ b/src/util/clipboard.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include + +class Clipboard { + static QString& text(); + + public: + static QList urls(); + static void begin(); + static void end(); + static void add(const QUrl& url); +}; diff --git a/src/widget/wlibrary.cpp b/src/widget/wlibrary.cpp index 9165346bdf0..b2bd65c570f 100644 --- a/src/widget/wlibrary.cpp +++ b/src/widget/wlibrary.cpp @@ -142,3 +142,9 @@ bool WLibrary::event(QEvent* pEvent) { } return QStackedWidget::event(pEvent); } + +void WLibrary::keyPressEvent(QKeyEvent* event) { + if (event->key() == Qt::Key_Left && event->modifiers() & Qt::ControlModifier) { + emit setLibraryFocus(FocusWidget::Sidebar); + } +} diff --git a/src/widget/wlibrary.h b/src/widget/wlibrary.h index bfe4acb0e0d..4a23eb610c6 100644 --- a/src/widget/wlibrary.h +++ b/src/widget/wlibrary.h @@ -5,6 +5,7 @@ #include #include +#include "library/library_decl.h" #include "library/libraryview.h" #include "skin/legacy/skincontext.h" #include "util/compatibility/qmutex.h" @@ -48,6 +49,9 @@ class WLibrary : public QStackedWidget, public WBaseWidget { return m_bShowButtonText; } + signals: + FocusWidget setLibraryFocus(FocusWidget newFocus); + public slots: // Show the view registered with the given name. Does nothing if the current // view is the specified view, or if the name does not specify any @@ -59,6 +63,7 @@ class WLibrary : public QStackedWidget, public WBaseWidget { protected: bool event(QEvent* pEvent) override; + void keyPressEvent(QKeyEvent* event) override; private: QT_RECURSIVE_MUTEX m_mutex; diff --git a/src/widget/wlibrarysidebar.cpp b/src/widget/wlibrarysidebar.cpp index cab2646b001..c16e020738e 100644 --- a/src/widget/wlibrarysidebar.cpp +++ b/src/widget/wlibrarysidebar.cpp @@ -269,6 +269,14 @@ void WLibrarySidebar::keyPressEvent(QKeyEvent* event) { emit pressed(selIndex); return; } + case Qt::Key_Right: { + if (event->modifiers() & Qt::ControlModifier) { + emit setLibraryFocus(FocusWidget::TracksTable); + } else { + QTreeView::keyPressEvent(event); + } + return; + } case Qt::Key_Left: { QModelIndexList selectedIndices = selectionModel()->selectedRows(); if (selectedIndices.isEmpty()) { diff --git a/src/widget/wlibrarytableview.cpp b/src/widget/wlibrarytableview.cpp index 59898391814..5ea19401e7b 100644 --- a/src/widget/wlibrarytableview.cpp +++ b/src/widget/wlibrarytableview.cpp @@ -267,12 +267,15 @@ void WLibraryTableView::focusInEvent(QFocusEvent* event) { QTableView::focusInEvent(event); if (event->reason() == Qt::TabFocusReason || - event->reason() == Qt::BacktabFocusReason) { + event->reason() == Qt::BacktabFocusReason || + event->reason() == Qt::OtherFocusReason) { // On FocusIn caused by a tab action with no focused item, select the // current or first track which can then instantly be loaded to a deck. // This is especially helpful if the table has only one track, which can // not be selected with up/down buttons, either physical or emulated via // [Library],MoveVertical controls. See #9548 + // Qt::OtherFocusReason is setFocus called by LibraryControl::setLibraryFocus, + // in response to shortkey Ctrl-Right if (model()->rowCount() > 0) { if (selectionModel()->hasSelection()) { DEBUG_ASSERT(!selectionModel()->selectedIndexes().isEmpty()); diff --git a/src/widget/wlibrarytableview.h b/src/widget/wlibrarytableview.h index c48a9c17175..905cd3dcb64 100644 --- a/src/widget/wlibrarytableview.h +++ b/src/widget/wlibrarytableview.h @@ -6,6 +6,7 @@ #include #include +#include "library/library_decl.h" #include "library/libraryview.h" #include "preferences/usersettings.h" #include "track/track_decl.h" @@ -58,6 +59,7 @@ class WLibraryTableView : public QTableView, public virtual LibraryView { void trackSelected(TrackPointer pTrack); void onlyCachedCoverArt(bool); void scrollValueChanged(int); + FocusWidget setLibraryFocus(FocusWidget newFocus); public slots: void setTrackTableFont(const QFont& font); diff --git a/src/widget/wlibrarytextbrowser.cpp b/src/widget/wlibrarytextbrowser.cpp index 82d35ed6e5b..ebc6484079e 100644 --- a/src/widget/wlibrarytextbrowser.cpp +++ b/src/widget/wlibrarytextbrowser.cpp @@ -1,5 +1,7 @@ #include "widget/wlibrarytextbrowser.h" +#include + #include "moc_wlibrarytextbrowser.cpp" WLibraryTextBrowser::WLibraryTextBrowser(QWidget* parent) @@ -13,3 +15,11 @@ bool WLibraryTextBrowser::hasFocus() const { void WLibraryTextBrowser::setFocus() { QWidget::setFocus(); } + +void WLibraryTextBrowser::keyPressEvent(QKeyEvent* event) { + if (event->key() == Qt::Key_Left && event->modifiers() & Qt::ControlModifier) { + event->ignore(); + return; + } + QTextBrowser::keyPressEvent(event); +} diff --git a/src/widget/wlibrarytextbrowser.h b/src/widget/wlibrarytextbrowser.h index 206664f0693..264ad90f2e6 100644 --- a/src/widget/wlibrarytextbrowser.h +++ b/src/widget/wlibrarytextbrowser.h @@ -2,6 +2,7 @@ #include +#include "library/library_decl.h" #include "library/libraryview.h" class WLibraryTextBrowser : public QTextBrowser, public LibraryView { @@ -11,4 +12,7 @@ class WLibraryTextBrowser : public QTextBrowser, public LibraryView { void onShow() override {} bool hasFocus() const override; void setFocus() override; + void keyPressEvent(QKeyEvent* event) override; + signals: + FocusWidget setLibraryFocus(FocusWidget newFocus); }; diff --git a/src/widget/wtracktableview.cpp b/src/widget/wtracktableview.cpp index 3fe112c55e8..4583869926e 100644 --- a/src/widget/wtracktableview.cpp +++ b/src/widget/wtracktableview.cpp @@ -818,6 +818,65 @@ TrackModel* WTrackTableView::getTrackModel() const { return trackModel; } +namespace { +QModelIndex calculateCutIndex(const QModelIndex& currentIndex, + const QModelIndexList& removedIndices) { + if (removedIndices.empty()) { + return QModelIndex(); + } + const int row = currentIndex.row(); + int rowAfterRemove = row; + for (const auto& removeIndex : removedIndices) { + if (removeIndex.row() < row) { + rowAfterRemove--; + } + } + return currentIndex.siblingAtRow(rowAfterRemove); +} +} // namespace + +void WTrackTableView::removeSelectedTracks() { + const QModelIndexList indices = selectionModel()->selectedRows(); + const QModelIndex newIndex = calculateCutIndex(currentIndex(), indices); + getTrackModel()->removeTracks(indices); + setCurrentIndex(newIndex); +} + +void WTrackTableView::cutSelectedTracks() { + const QModelIndexList indices = selectionModel()->selectedRows(); + const QModelIndex newIndex = calculateCutIndex(currentIndex(), indices); + getTrackModel()->cutTracks(indices); + setCurrentIndex(newIndex); +} + +void WTrackTableView::copySelectedTracks() { + const QModelIndexList indices = selectionModel()->selectedRows(); + getTrackModel()->copyTracks(indices); +} + +void WTrackTableView::pasteTracks() { + auto index = currentIndex(); + const bool appending = !index.isValid(); + int n = getTrackModel()->pasteTracks(index); + if (n == 0) { + return; + } + if (appending) { + index = model()->index(model()->rowCount() - n, 1); + } + setCurrentIndex(index); + int insertRow = index.row(); + for (int i = 0; i < n; i++) { + selectionModel()->select(model()->index(insertRow + i, 0), + QItemSelectionModel::Select | QItemSelectionModel::Rows); + } + if (appending) { + scrollTo(index, PositionAtCenter); + } + // will trigger a repaint of the sidebar to show the increased track count + // emit trackSelected(TrackPointer()); +} + void WTrackTableView::keyPressEvent(QKeyEvent* event) { switch (event->key()) { case kPropertiesShortcutKey: { @@ -832,16 +891,41 @@ void WTrackTableView::keyPressEvent(QKeyEvent* event) { m_pTrackMenu->slotShowDlgTrackInfo(); } } - } break; + return; + } case kHideRemoveShortcutKey: { if (event->modifiers() == kHideRemoveShortcutModifier) { hideOrRemoveSelectedTracks(); - return; } - } break; + return; + } default: - QTableView::keyPressEvent(event); + break; + } + TrackModel* trackModel = getTrackModel(); + if (trackModel && !trackModel->isLocked()) { + if (event->matches(QKeySequence::Delete) || event->key() == Qt::Key_Backspace) { + removeSelectedTracks(); + return; + } + if (event->matches(QKeySequence::Cut)) { + cutSelectedTracks(); + return; + } + if (event->matches(QKeySequence::Copy)) { + copySelectedTracks(); + return; + } + if (event->matches(QKeySequence::Paste)) { + pasteTracks(); + return; + } + if (event->key() == Qt::Key_Escape) { + clearSelection(); + setCurrentIndex(QModelIndex()); + } } + QTableView::keyPressEvent(event); } void WTrackTableView::hideOrRemoveSelectedTracks() { @@ -1278,7 +1362,7 @@ bool WTrackTableView::hasFocus() const { } void WTrackTableView::setFocus() { - QWidget::setFocus(); + QWidget::setFocus(Qt::OtherFocusReason); } QString WTrackTableView::getModelStateKey() const { diff --git a/src/widget/wtracktableview.h b/src/widget/wtracktableview.h index 433da9d9733..c6d4059c156 100644 --- a/src/widget/wtracktableview.h +++ b/src/widget/wtracktableview.h @@ -46,6 +46,11 @@ class WTrackTableView : public WLibraryTableView { TrackId getCurrentTrackId() const; bool setCurrentTrackId(const TrackId& trackId, int column = 0, bool scrollToTrack = false); + void removeSelectedTracks(); + void cutSelectedTracks(); + void copySelectedTracks(); + void pasteTracks(); + double getBackgroundColorOpacity() const { return m_backgroundColorOpacity; }