From e718a1131638c6227dc78d7944102f07fd5d4892 Mon Sep 17 00:00:00 2001 From: Prince Gupta Date: Mon, 3 Feb 2025 20:32:22 +0530 Subject: [PATCH 1/7] qt: update qml_menu_wrapper(s) Have a common class in all menu wrappers that implement some basic functionality - visibility and memory management implement tableView_popup function for Network context menu --- modules/gui/qt/menus/qml_menu_wrapper.cpp | 88 +++++++++++++---------- modules/gui/qt/menus/qml_menu_wrapper.hpp | 62 ++++++++++------ 2 files changed, 92 insertions(+), 58 deletions(-) diff --git a/modules/gui/qt/menus/qml_menu_wrapper.cpp b/modules/gui/qt/menus/qml_menu_wrapper.cpp index 90c6f795e6d6..1c6a2caaf2ac 100644 --- a/modules/gui/qt/menus/qml_menu_wrapper.cpp +++ b/modules/gui/qt/menus/qml_menu_wrapper.cpp @@ -71,8 +71,7 @@ namespace void StringListMenu::popup(const QPoint &point, const QVariantList &stringList) { assert(m_ctx); - QMenu *m = new VLCMenu(m_ctx->getIntf()); - m->setAttribute(Qt::WA_DeleteOnClose); + QMenu *m = newMenu(); for (int i = 0; i != stringList.size(); ++i) { @@ -86,6 +85,30 @@ void StringListMenu::popup(const QPoint &point, const QVariantList &stringList) m->popup(point); } +QMenu *BasicMenuContainer::newMenu() +{ + QMenu *m = new VLCMenu(m_ctx->getIntf()); + m->setAttribute(Qt::WA_DeleteOnClose); + if (m_prevMenu) + { + setVisible(false); + m_prevMenu->disconnect(this); + } + + m_prevMenu = m; + connect(m, &QMenu::aboutToShow, this, [this](){ setVisible(true);}); + connect(m, &QMenu::aboutToHide, this, [this](){ setVisible(false);}); + return m; +} + +void BasicMenuContainer::setVisible(bool visible) +{ + if (m_visible == visible) return; + + m_visible = visible; + emit visibleChanged(); +} + // SortMenu void SortMenu::popup(const QPoint &point, const bool popupAbovePoint, const QVariantList &model) @@ -771,7 +794,7 @@ void QmlAudioContextMenu::popup(const QPoint & position) //================================================================================================= PlaylistListContextMenu::PlaylistListContextMenu(QObject * parent) - : QObject(parent) + : BasicMenuContainer(parent) {} @@ -787,17 +810,17 @@ void PlaylistListContextMenu::popup(const QModelIndexList & selected, QPoint pos for (const QModelIndex & modelIndex : selected) ids.push_back(m_model->data(modelIndex, MLPlaylistListModel::PLAYLIST_ID)); - m_menu = std::make_unique(m_ctx->getIntf()); + auto menu = newMenu(); MediaLib * ml = m_model->ml(); - QAction * action = m_menu->addAction(qtr("Add and play")); + QAction * action = menu->addAction(qtr("Add and play")); connect(action, &QAction::triggered, [ml, ids]() { ml->addAndPlay(ids); }); - action = m_menu->addAction(qtr("Enqueue")); + action = menu->addAction(qtr("Enqueue")); connect(action, &QAction::triggered, [ml, ids]() { ml->addToPlaylist(ids); @@ -805,7 +828,7 @@ void PlaylistListContextMenu::popup(const QModelIndexList & selected, QPoint pos if (ids.count() == 1) { - action = m_menu->addAction(qtr("Rename")); + action = menu->addAction(qtr("Rename")); QModelIndex index = selected.first(); @@ -814,20 +837,19 @@ void PlaylistListContextMenu::popup(const QModelIndexList & selected, QPoint pos }); } - action = m_menu->addAction(qtr("Delete")); + action = menu->addAction(qtr("Delete")); connect(action, &QAction::triggered, [this, ids]() { m_model->deletePlaylists(ids); }); - m_menu->popup(pos); + menu->popup(pos); } //================================================================================================= // PlaylistMediaContextMenu //================================================================================================= -PlaylistMediaContextMenu::PlaylistMediaContextMenu(QObject * parent) : QObject(parent) {} void PlaylistMediaContextMenu::popup(const QModelIndexList & selected, QPoint pos, QVariantMap options) @@ -842,38 +864,38 @@ void PlaylistMediaContextMenu::popup(const QModelIndexList & selected, QPoint po for (const QModelIndex& modelIndex : selected) ids.push_back(m_model->data(modelIndex, MLPlaylistModel::MEDIA_ID)); - m_menu = std::make_unique(m_ctx->getIntf()); + auto menu =newMenu(); MediaLib * ml = m_model->ml(); - QAction * action = m_menu->addAction(qtr("Add and play")); + QAction * action = menu->addAction(qtr("Add and play")); connect(action, &QAction::triggered, [ml, ids]() { ml->addAndPlay(ids); }); - action = m_menu->addAction(qtr("Enqueue")); + action = menu->addAction(qtr("Enqueue")); connect(action, &QAction::triggered, [ml, ids]() { ml->addToPlaylist(ids); }); - action = m_menu->addAction(qtr("Add to playlist")); + action = menu->addAction(qtr("Add to playlist")); connect(action, &QAction::triggered, [ids]() { DialogsProvider::getInstance()->playlistsDialog(ids); }); - action = m_menu->addAction(qtr("Play as audio")); + action = menu->addAction(qtr("Play as audio")); connect(action, &QAction::triggered, [ml, ids]() { ml->addAndPlay(ids, {":no-video"}); }); if (options.contains("information") && options["information"].typeId() == QMetaType::Int) { - action = m_menu->addAction(qtr("Information")); + action = menu->addAction(qtr("Information")); - QSignalMapper * mapper = new QSignalMapper(m_menu.get()); + QSignalMapper * mapper = new QSignalMapper(menu); connect(action, &QAction::triggered, mapper, QOverload<>::of(&QSignalMapper::map)); @@ -882,9 +904,9 @@ void PlaylistMediaContextMenu::popup(const QModelIndexList & selected, QPoint po this, &PlaylistMediaContextMenu::showMediaInformation); } - m_menu->addSeparator(); + menu->addSeparator(); - action = m_menu->addAction(qtr("Remove Selected")); + action = menu->addAction(qtr("Remove Selected")); action->setIcon(QIcon(":/menu/remove.svg")); @@ -892,15 +914,11 @@ void PlaylistMediaContextMenu::popup(const QModelIndexList & selected, QPoint po m_model->remove(selected); }); - m_menu->popup(pos); + menu->popup(pos); } //================================================================================================= -NetworkMediaContextMenu::NetworkMediaContextMenu(QObject* parent) - : QObject(parent) -{} - void NetworkMediaContextMenu::popup(const QModelIndexList& selected, QPoint pos) { assert(m_ctx); @@ -908,15 +926,15 @@ void NetworkMediaContextMenu::popup(const QModelIndexList& selected, QPoint pos) if (!m_model) return; - m_menu = std::make_unique(m_ctx->getIntf()); + auto menu = newMenu(); QAction* action; - action = m_menu->addAction( qtr("Add and play") ); + action = menu->addAction( qtr("Add and play") ); connect(action, &QAction::triggered, [this, selected]( ) { m_model->addAndPlay(selected); }); - action = m_menu->addAction( qtr("Enqueue") ); + action = menu->addAction( qtr("Enqueue") ); connect(action, &QAction::triggered, [this, selected]( ) { m_model->addToPlaylist(selected); }); @@ -940,7 +958,7 @@ void NetworkMediaContextMenu::popup(const QModelIndexList& selected, QPoint pos) if (canBeIndexed) { bool removeFromML = countIndexed > 0; - action = m_menu->addAction(removeFromML + action = menu->addAction(removeFromML ? qtr("Remove from Media Library") : qtr("Add to Media Library")); @@ -951,13 +969,9 @@ void NetworkMediaContextMenu::popup(const QModelIndexList& selected, QPoint pos) }); } - m_menu->popup(pos); + menu->popup(pos); } -NetworkDeviceContextMenu::NetworkDeviceContextMenu(QObject* parent) - : QObject(parent) -{} - void NetworkDeviceContextMenu::popup(const QModelIndexList& selected, QPoint pos) { assert(m_ctx); @@ -965,20 +979,20 @@ void NetworkDeviceContextMenu::popup(const QModelIndexList& selected, QPoint pos if (!m_model) return; - m_menu = std::make_unique(m_ctx->getIntf()); + auto menu = newMenu(); QAction* action; - action = m_menu->addAction( qtr("Add and play") ); + action = menu->addAction( qtr("Add and play") ); connect(action, &QAction::triggered, [this, selected]( ) { m_model->addAndPlay(selected); }); - action = m_menu->addAction( qtr("Enqueue") ); + action = menu->addAction( qtr("Enqueue") ); connect(action, &QAction::triggered, [this, selected]( ) { m_model->addToPlaylist(selected); }); - m_menu->popup(pos); + menu->popup(pos); } PlaylistContextMenu::PlaylistContextMenu(QObject* parent) diff --git a/modules/gui/qt/menus/qml_menu_wrapper.hpp b/modules/gui/qt/menus/qml_menu_wrapper.hpp index a45de3319e57..d2e76e22c5b9 100644 --- a/modules/gui/qt/menus/qml_menu_wrapper.hpp +++ b/modules/gui/qt/menus/qml_menu_wrapper.hpp @@ -57,22 +57,44 @@ class PlaylistListModel; type m_##name = defaultValue; -class StringListMenu : public QObject +class BasicMenuContainer : public QObject { Q_OBJECT SIMPLE_MENU_PROPERTY(MainCtx *, ctx, nullptr) + Q_PROPERTY(bool visible READ visible NOTIFY visibleChanged FINAL) public: using QObject::QObject; + bool visible() const { return m_visible; } + +signals: + void visibleChanged(); + +protected: + QMenu *newMenu(); + +private: + void setVisible(bool visible); + + bool m_visible = false; + QPointer m_prevMenu; +}; + +class StringListMenu : public BasicMenuContainer +{ + Q_OBJECT + +public: + using BasicMenuContainer::BasicMenuContainer; + Q_INVOKABLE void popup(const QPoint &point, const QVariantList &stringList); signals: void selected(int index, const QString &str); }; - class SortMenu : public QObject { Q_OBJECT @@ -360,18 +382,15 @@ class QmlAudioMenu : public QmlTrackMenu void beforePopup(QMenu * menu) override; }; -class PlaylistListContextMenu : public QObject { +class PlaylistListContextMenu : public BasicMenuContainer { Q_OBJECT - SIMPLE_MENU_PROPERTY(MainCtx *, ctx, nullptr) SIMPLE_MENU_PROPERTY(MLPlaylistListModel *, model, nullptr) public: PlaylistListContextMenu(QObject * parent = nullptr); public slots: void popup(const QModelIndexList & selected, QPoint pos, QVariantMap options = {}); -private: - std::unique_ptr m_menu; }; class QmlAudioContextMenu : public VLCMenuBar @@ -389,44 +408,45 @@ class QmlAudioContextMenu : public VLCMenuBar std::unique_ptr m_menu; }; -class PlaylistMediaContextMenu : public QObject { +class PlaylistMediaContextMenu : public BasicMenuContainer { Q_OBJECT SIMPLE_MENU_PROPERTY(MLPlaylistModel *, model, nullptr) - SIMPLE_MENU_PROPERTY(MainCtx *, ctx, nullptr) public: - PlaylistMediaContextMenu(QObject * parent = nullptr); + using BasicMenuContainer::BasicMenuContainer; public slots: void popup(const QModelIndexList & selected, QPoint pos, QVariantMap options = {}); signals: void showMediaInformation(int index); -private: - std::unique_ptr m_menu; }; -class NetworkMediaContextMenu : public QObject { +class NetworkMediaContextMenu : public BasicMenuContainer { Q_OBJECT SIMPLE_MENU_PROPERTY(NetworkMediaModel*, model, nullptr) - SIMPLE_MENU_PROPERTY(MainCtx *, ctx, nullptr) public: - NetworkMediaContextMenu(QObject* parent = nullptr); + using BasicMenuContainer::BasicMenuContainer; public slots: void popup(const QModelIndexList& selected, QPoint pos ); -private: - std::unique_ptr m_menu; + void tableView_popup(int /*current*/, const QModelIndexList &selected, QPoint pos) + { + popup(selected, pos); + } }; -class NetworkDeviceContextMenu : public QObject { +class NetworkDeviceContextMenu : public BasicMenuContainer { Q_OBJECT SIMPLE_MENU_PROPERTY(NetworkDeviceModel*, model, nullptr) - SIMPLE_MENU_PROPERTY(MainCtx *, ctx, nullptr) public: - NetworkDeviceContextMenu(QObject* parent = nullptr); + using BasicMenuContainer::BasicMenuContainer; + public slots: void popup(const QModelIndexList& selected, QPoint pos ); -private: - std::unique_ptr m_menu; + void tableView_popup(int /*current*/, const QModelIndexList &selected, QPoint pos) + { + popup(selected, pos); + } + }; class PlaylistContextMenu : public QObject { From fc42c7f541e7456b5dcacb827e3f9bbcd9319010 Mon Sep 17 00:00:00 2001 From: Prince Gupta Date: Mon, 3 Feb 2025 20:37:31 +0530 Subject: [PATCH 2/7] qml: update implementation of MLContextMenu useful for changes following this commit --- modules/gui/qt/util/qml/MLContextMenu.qml | 6 ++++++ modules/gui/qt/util/qml/NativeMenu.qml | 9 ++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/modules/gui/qt/util/qml/MLContextMenu.qml b/modules/gui/qt/util/qml/MLContextMenu.qml index 561d783000ef..7582cdf9fe1c 100644 --- a/modules/gui/qt/util/qml/MLContextMenu.qml +++ b/modules/gui/qt/util/qml/MLContextMenu.qml @@ -40,6 +40,12 @@ NativeMenu { signal showMediaInformation(int index) + + // required by TableViewExt + property var tableView_popup: function (index/* reserved for future */, selectedIndexes, globalPos) { + return popup(selectedIndexes, globalPos) + } + // Settings actions: [{ diff --git a/modules/gui/qt/util/qml/NativeMenu.qml b/modules/gui/qt/util/qml/NativeMenu.qml index 3a199f4eb517..7b8ac0b16e9f 100644 --- a/modules/gui/qt/util/qml/NativeMenu.qml +++ b/modules/gui/qt/util/qml/NativeMenu.qml @@ -43,6 +43,10 @@ QtObject { property var actions: [] + property alias visible: menu.visible + + readonly property int currentRequest: _currentRequest + signal requestData(var requestID, var indexes) @@ -58,7 +62,9 @@ QtObject { property point _popupPoint - + // requests data for '_indexes' and shows popup menu + // with 'NativeMenu::actions' based on '_options' + // returns unique request id function popup(_indexes, point, _options) { root._options = _options root._indexes = _indexes @@ -67,6 +73,7 @@ QtObject { const requestID = ++_currentRequest requestData(requestID, _indexes) + return requestID } function setData(id, data) { From 62dc35f62b62637add0b845a8ddbfeb5d885977c Mon Sep 17 00:00:00 2001 From: Prince Gupta Date: Mon, 3 Feb 2025 20:46:41 +0530 Subject: [PATCH 3/7] qml: keep context menu button visible when menu is shown --- .../gui/qt/medialibrary/qml/MusicAlbums.qml | 5 ++- .../qt/medialibrary/qml/MusicAllArtists.qml | 4 +-- .../gui/qt/medialibrary/qml/MusicArtist.qml | 3 +- .../gui/qt/medialibrary/qml/MusicGenres.qml | 6 ++-- .../qml/MusicTrackListDisplay.qml | 5 ++- .../medialibrary/qml/PlaylistMediaDisplay.qml | 10 +++--- .../qt/medialibrary/qml/PlaylistMediaList.qml | 10 +++--- .../qt/medialibrary/qml/UrlListDisplay.qml | 6 ++-- modules/gui/qt/medialibrary/qml/VideoAll.qml | 6 ++-- .../gui/qt/network/qml/BrowseDeviceView.qml | 2 ++ .../gui/qt/network/qml/BrowseTreeDisplay.qml | 6 ++-- .../gui/qt/widgets/qml/TableViewDelegate.qml | 32 ++++++++++++++++--- modules/gui/qt/widgets/qml/TableViewExt.qml | 31 +++++++++++++++--- 13 files changed, 85 insertions(+), 41 deletions(-) diff --git a/modules/gui/qt/medialibrary/qml/MusicAlbums.qml b/modules/gui/qt/medialibrary/qml/MusicAlbums.qml index 80573dbf4209..0dd3e01cfb54 100644 --- a/modules/gui/qt/medialibrary/qml/MusicAlbums.qml +++ b/modules/gui/qt/medialibrary/qml/MusicAlbums.qml @@ -243,12 +243,11 @@ MainViewLoader { dragItem: albumDragItem rowHeight: VLCStyle.tableCoverRow_height + rowContextMenu: contextMenu + sortModel: (availableRowWidth < VLCStyle.colWidth(4)) ? _modelSmall : _modelMedium - onContextMenuButtonClicked: (_,_,globalMousePos) => { - contextMenu.popup(selectionModel.selectedIndexes, globalMousePos) - } onRightClick: (_,_,globalMousePos) => { contextMenu.popup(selectionModel.selectedIndexes, globalMousePos) } diff --git a/modules/gui/qt/medialibrary/qml/MusicAllArtists.qml b/modules/gui/qt/medialibrary/qml/MusicAllArtists.qml index 059f734105fd..70d297b3fa74 100644 --- a/modules/gui/qt/medialibrary/qml/MusicAllArtists.qml +++ b/modules/gui/qt/medialibrary/qml/MusicAllArtists.qml @@ -203,6 +203,7 @@ MainViewLoader { model: artistModel focus: true dragItem: artistsDragItem + rowContextMenu: contextMenu rowHeight: VLCStyle.tableCoverRow_height header: root.header @@ -221,9 +222,6 @@ MainViewLoader { root.requestArtistAlbumView(Qt.MouseFocusReason, model.id) } - onContextMenuButtonClicked: (_,_, globalMousePos) => { - contextMenu.popup(selectionModel.selectedIndexes, globalMousePos) - } onRightClick: (_,_,globalMousePos) => { contextMenu.popup(selectionModel.selectedIndexes, globalMousePos) } diff --git a/modules/gui/qt/medialibrary/qml/MusicArtist.qml b/modules/gui/qt/medialibrary/qml/MusicArtist.qml index 7e3afe61511d..24eea7c24b0c 100644 --- a/modules/gui/qt/medialibrary/qml/MusicArtist.qml +++ b/modules/gui/qt/medialibrary/qml/MusicArtist.qml @@ -550,6 +550,8 @@ FocusScope { dragItem: tableDragItem + rowContextMenu: trackContextMenu + Navigation.parentItem: root Navigation.upAction: function() { @@ -559,7 +561,6 @@ FocusScope { Navigation.cancelAction: root._onNavigationCancel onItemDoubleClicked: MediaLib.addAndPlay(model.id) - onContextMenuButtonClicked: trackContextMenu.popup(tableView_id.selectionModel.selectedIndexes, globalMousePos) onRightClick: trackContextMenu.popup(tableView_id.selectionModel.selectedIndexes, globalMousePos) onDragItemChanged: console.assert(tableView_id.dragItem === tableDragItem) diff --git a/modules/gui/qt/medialibrary/qml/MusicGenres.qml b/modules/gui/qt/medialibrary/qml/MusicGenres.qml index 88f8489329a5..3b6cd8f6b673 100644 --- a/modules/gui/qt/medialibrary/qml/MusicGenres.qml +++ b/modules/gui/qt/medialibrary/qml/MusicGenres.qml @@ -266,14 +266,12 @@ MainViewLoader { header: root.header + rowContextMenu: contextMenu + onItemDoubleClicked: (index, model) => { root.showAlbumView(model.id, model.name, Qt.MouseFocusReason) } - onContextMenuButtonClicked: (_,_,globalMousePos) => { - contextMenu.popup(selectionModel.selectedIndexes, globalMousePos) - } - onRightClick: (_,_,globalMousePos) => { contextMenu.popup(selectionModel.selectedIndexes, globalMousePos) } diff --git a/modules/gui/qt/medialibrary/qml/MusicTrackListDisplay.qml b/modules/gui/qt/medialibrary/qml/MusicTrackListDisplay.qml index 7633c82ab3f8..d5fa571cb54a 100644 --- a/modules/gui/qt/medialibrary/qml/MusicTrackListDisplay.qml +++ b/modules/gui/qt/medialibrary/qml/MusicTrackListDisplay.qml @@ -180,11 +180,10 @@ Widgets.TableViewExt { onDragItemChanged: console.assert(root.dragItem === tableDragItem) + rowContextMenu: contextMenu + onActionForSelection: (selection) => model.addAndPlay(selection) onItemDoubleClicked: (index, model) => MediaLib.addAndPlay(model.id) - onContextMenuButtonClicked: (_,_, globalMousePos) => { - contextMenu.popup(selectionModel.selectedIndexes, globalMousePos) - } onRightClick: (_,_, globalMousePos) => { contextMenu.popup(selectionModel.selectedIndexes, globalMousePos) } diff --git a/modules/gui/qt/medialibrary/qml/PlaylistMediaDisplay.qml b/modules/gui/qt/medialibrary/qml/PlaylistMediaDisplay.qml index b8c02da9e65a..e152ed63654c 100644 --- a/modules/gui/qt/medialibrary/qml/PlaylistMediaDisplay.qml +++ b/modules/gui/qt/medialibrary/qml/PlaylistMediaDisplay.qml @@ -184,6 +184,10 @@ FocusScope { model: root.model ctx: MainCtx + + function tableView_popup(index, selectedIndexes, globalPos) { + popup(selectedIndexes, globalPos) + } } PlaylistMedia @@ -200,6 +204,8 @@ FocusScope { dragItem: root.dragItem + rowContextMenu: contextMenu + isMusic: root.isMusic header: Widgets.ViewHeader { @@ -222,10 +228,6 @@ FocusScope { // Events - onContextMenuButtonClicked: (_,_,globalMousePos) => { - contextMenu.popup(selectionModel.selectedRows(), globalMousePos) - } - onRightClick: (_,_,globalMousePos) => { contextMenu.popup(selectionModel.selectedRows(), globalMousePos) } diff --git a/modules/gui/qt/medialibrary/qml/PlaylistMediaList.qml b/modules/gui/qt/medialibrary/qml/PlaylistMediaList.qml index f08112e359b8..effd779dbeaa 100644 --- a/modules/gui/qt/medialibrary/qml/PlaylistMediaList.qml +++ b/modules/gui/qt/medialibrary/qml/PlaylistMediaList.qml @@ -238,6 +238,10 @@ MainViewLoader { model: root.model ctx: MainCtx + + function tableView_popup(index, selectedIndexes, globalPos) { + popup(selectedIndexes, globalPos) + } } // TBD: Refactor this with MusicGenres ? @@ -414,6 +418,8 @@ MainViewLoader { header: root.header + rowContextMenu: contextMenu + listView.isDropAcceptableFunc: function(drag, index) { root._adjustDragAccepted(drag) return drag.accepted @@ -434,10 +440,6 @@ MainViewLoader { onItemDoubleClicked: (_, model) => showList(model, Qt.MouseFocusReason) - onContextMenuButtonClicked: (_, _, globalMousePos) => { - contextMenu.popup(selectionModel.selectedRows(), globalMousePos) - } - onRightClick: (_, _, globalMousePos) => { contextMenu.popup(selectionModel.selectedRows(), globalMousePos) } diff --git a/modules/gui/qt/medialibrary/qml/UrlListDisplay.qml b/modules/gui/qt/medialibrary/qml/UrlListDisplay.qml index 01a0d8d257a2..b152d98dcd2b 100644 --- a/modules/gui/qt/medialibrary/qml/UrlListDisplay.qml +++ b/modules/gui/qt/medialibrary/qml/UrlListDisplay.qml @@ -83,11 +83,11 @@ Widgets.TableViewExt { rowHeight: VLCStyle.listAlbumCover_height + VLCStyle.margin_xxsmall * 2 + rowContextMenu: contextMenu + onActionForSelection: (selection) => model.addAndPlay( selection ) onItemDoubleClicked: (index, model) => MediaLib.addAndPlay(model.id) - onContextMenuButtonClicked: (_,_,globalMousePos) => { - contextMenu.popup(selectionModel.selectedIndexes, globalMousePos) - } + onRightClick: (_,_,globalMousePos) => { contextMenu.popup(selectionModel.selectedIndexes, globalMousePos) } diff --git a/modules/gui/qt/medialibrary/qml/VideoAll.qml b/modules/gui/qt/medialibrary/qml/VideoAll.qml index 97f565215726..29bb4b883972 100644 --- a/modules/gui/qt/medialibrary/qml/VideoAll.qml +++ b/modules/gui/qt/medialibrary/qml/VideoAll.qml @@ -184,6 +184,8 @@ MainViewLoader { selectionModel: root.selectionModel + rowContextMenu: root.contextMenu + dragItem: root.dragItem header: root.header @@ -210,10 +212,6 @@ MainViewLoader { onItemDoubleClicked: (index, model) => root.onDoubleClick(model) - onContextMenuButtonClicked: (_,_,globalMousePos) => { - root.contextMenu.popup(selectionModel.selectedIndexes, globalMousePos) - } - onRightClick: (_,_,globalMousePos) => { root.contextMenu.popup(selectionModel.selectedIndexes, globalMousePos) } diff --git a/modules/gui/qt/network/qml/BrowseDeviceView.qml b/modules/gui/qt/network/qml/BrowseDeviceView.qml index 3bcf72b9dac7..e6eda2a80e50 100644 --- a/modules/gui/qt/network/qml/BrowseDeviceView.qml +++ b/modules/gui/qt/network/qml/BrowseDeviceView.qml @@ -288,6 +288,8 @@ FocusScope { // Settings + rowContextMenu: null + rowHeight: VLCStyle.tableCoverRow_height displayMarginEnd: root.displayMarginEnd diff --git a/modules/gui/qt/network/qml/BrowseTreeDisplay.qml b/modules/gui/qt/network/qml/BrowseTreeDisplay.qml index c9bbe3fc8c4b..2a210296ef8b 100644 --- a/modules/gui/qt/network/qml/BrowseTreeDisplay.qml +++ b/modules/gui/qt/network/qml/BrowseTreeDisplay.qml @@ -295,11 +295,11 @@ MainViewLoader { } } + rowContextMenu: contextMenu + onActionForSelection: (selection) => _actionAtIndex(selection[0].row) onItemDoubleClicked: (index, model) => _actionAtIndex(index) - onContextMenuButtonClicked: (_,_,globalMousePos) => { - contextMenu.popup(selectionModel.selectedIndexes, globalMousePos) - } + onRightClick: (_,_,globalMousePos) => { contextMenu.popup(selectionModel.selectedIndexes, globalMousePos) } diff --git a/modules/gui/qt/widgets/qml/TableViewDelegate.qml b/modules/gui/qt/widgets/qml/TableViewDelegate.qml index d19821a44281..c12eb5436ede 100644 --- a/modules/gui/qt/widgets/qml/TableViewDelegate.qml +++ b/modules/gui/qt/widgets/qml/TableViewDelegate.qml @@ -35,6 +35,8 @@ T.Control { required property bool selected required property Widgets.DragItem dragItem + required property var contextMenu + readonly property bool topContainsDrag: dropAreaLayout.higherDropArea.containsDrag readonly property bool bottomContainsDrag: dropAreaLayout.lowerDropArea.containsDrag readonly property bool containsDrag: (topContainsDrag || bottomContainsDrag) @@ -46,6 +48,8 @@ T.Control { dropAreaLayout.dragPosition.x, dropAreaLayout.dragPosition.y) + readonly property ItemSelectionModel selectionModel: delegate.ListView.view.selectionModel + // Optional, used to show the drop indicator property alias isDropAcceptable: dropAreaLayout.isDropAcceptable @@ -54,12 +58,23 @@ T.Control { property int _modifiersOnLastPress: Qt.NoModifier - signal contextMenuButtonClicked(Item menuParent, var menuModel, point globalMousePos) + readonly property int _defaultContextMenuRequestID: index + + property int _contextMenuRequestID: -1 + signal rightClick(Item menuParent, var menuModel, point globalMousePos) signal itemDoubleClicked(var index, var model) signal selectAndFocus(int modifiers, int focusReason) + Connections { + target: contextMenu + + function onVisibleChanged() { + if (!contextMenu.visible) _contextMenuRequestID = -1 + } + } + property Component defaultDelegate: TableRowDelegate { id: defaultDelId Widgets.TextAutoScroller { @@ -126,7 +141,7 @@ T.Control { if (dragItem) { if (active) { if (!selected) { - delegate.ListView.view.selectionModel.select(index, ItemSelectionModel.ClearAndSelect) + delegate.selectionModel.select(index, ItemSelectionModel.ClearAndSelect) } dragItem.Drag.active = true @@ -151,7 +166,7 @@ T.Control { if (!(delegate.selected && button === Qt.RightButton)) { const view = delegate.ListView.view - view.selectionModel.updateSelection(point.modifiers, view.currentIndex, index) + delegate.selectionModel.updateSelection(point.modifiers, view.currentIndex, index) view.currentIndex = index } @@ -248,6 +263,8 @@ T.Control { height: parent.height + visible: !!delegate.contextMenu + Widgets.IconToolButton { id: contextButton @@ -263,6 +280,9 @@ T.Control { description: qsTr("Menu") visible: delegate.hovered + || ((delegate.contextMenu?.currentRequest ?? delegate._defaultContextMenuRequestID) + === delegate._contextMenuRequestID + && delegate.contextMenu.visible) // NOTE: QTBUG-100543 // Hover handling in controls is blocking in Qt 6.2, meaning if this @@ -284,7 +304,11 @@ T.Control { delegate.selectAndFocus(Qt.NoModifier, Qt.MouseFocusReason) const pos = contextButton.mapToGlobal(VLCStyle.margin_xsmall, contextButton.height / 2 + VLCStyle.fontHeight_normal) - delegate.contextMenuButtonClicked(this, delegate.rowModel, pos) + const selectionIndexes = delegate.ListView.view.selectionModel.selectedIndexes + + delegate._contextMenuRequestID + = delegate.contextMenu.tableView_popup(delegate.index, selectionIndexes, pos) + ?? delegate._defaultContextMenuRequestID } activeFocusOnTab: false diff --git a/modules/gui/qt/widgets/qml/TableViewExt.qml b/modules/gui/qt/widgets/qml/TableViewExt.qml index 0d46f4455a81..fbc6a5d8faf9 100644 --- a/modules/gui/qt/widgets/qml/TableViewExt.qml +++ b/modules/gui/qt/widgets/qml/TableViewExt.qml @@ -47,6 +47,30 @@ FocusScope { } } + /* + Expects an object with the following properties: + + // Determines if the menu is visible (optional) + bool visible + + // The request ID associated with the currently displayed context menu (optional) + int currentRequest + + // Displays the popup menu at the specified position (required) + // incase the function doesn't return request id TableViewExt will + // try to mimic behavior but it may have some caveats + // + // Parameters: + // current - calling row index + // selectedIndexes - current item selection (all) + // globalPos - the global position where the popup should appear + // + // Returns: + // int - the generated request ID + function tableView_popup(current, selectedIndexes, globalPos) -> int (request ID) + */ + required property var rowContextMenu + // NOTE: We want edge to edge backgrounds in our delegate and header, so we implement our own // margins implementation like in ExpandGridView. The default values should be the same // than ExpandGridView to respect the grid parti pris. @@ -157,7 +181,6 @@ FocusScope { //forwarded from subview signal actionForSelection( var selection ) - signal contextMenuButtonClicked(Item menuParent, var menuModel, point globalMousePos) signal rightClick(Item menuParent, var menuModel, point globalMousePos) signal itemDoubleClicked(var index, var model) @@ -235,7 +258,6 @@ FocusScope { id: view anchors.fill: parent - focus: true headerPositioning: ListView.OverlayHeader @@ -402,14 +424,13 @@ FocusScope { dragItem: root.dragItem + contextMenu: root.rowContextMenu + rowModel: model sortModel: root.sortModel selected: selectionModel.selectedIndexesFlat.includes(index) - onContextMenuButtonClicked: (menuParent, menuModel, globalMousePos) => { - root.contextMenuButtonClicked(menuParent, menuModel, globalMousePos) - } onRightClick: (menuParent, menuModel, globalMousePos) => { root.rightClick(menuParent, menuModel, globalMousePos) } From 8f7d4ad04733dd733e8134011a05809a64038c1e Mon Sep 17 00:00:00 2001 From: Prince Gupta Date: Thu, 13 Feb 2025 19:15:08 +0530 Subject: [PATCH 4/7] qml: add missing required property --- modules/gui/qt/medialibrary/qml/MusicArtist.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/gui/qt/medialibrary/qml/MusicArtist.qml b/modules/gui/qt/medialibrary/qml/MusicArtist.qml index 24eea7c24b0c..525f229dbee5 100644 --- a/modules/gui/qt/medialibrary/qml/MusicArtist.qml +++ b/modules/gui/qt/medialibrary/qml/MusicArtist.qml @@ -193,6 +193,7 @@ FocusScope { id: gridItem required property var model + required property int index y: selectedBorderWidth From 84c4974f5a83b9d999720c5b94ba505c693ed474 Mon Sep 17 00:00:00 2001 From: Prince Gupta Date: Thu, 13 Feb 2025 19:27:58 +0530 Subject: [PATCH 5/7] qml: support context menu click in artist list view --- modules/gui/qt/medialibrary/qml/MusicArtist.qml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/gui/qt/medialibrary/qml/MusicArtist.qml b/modules/gui/qt/medialibrary/qml/MusicArtist.qml index 525f229dbee5..ba312070ba72 100644 --- a/modules/gui/qt/medialibrary/qml/MusicArtist.qml +++ b/modules/gui/qt/medialibrary/qml/MusicArtist.qml @@ -229,6 +229,12 @@ FocusScope { } } + onContextMenuButtonClicked: (_, globalMousePos) => { + albumSelectionModel.updateSelection( Qt.NoModifier , albumsList.currentIndex, index ) + contextMenu.popup(albumSelectionModel.selectedIndexes + , globalMousePos) + } + function play() { if ( model.id !== undefined ) { MediaLib.addAndPlay( model.id ) From 9ab6e688c7a4b30f3f97e908e905386c32e1a707 Mon Sep 17 00:00:00 2001 From: Prince Gupta Date: Thu, 13 Feb 2025 19:15:25 +0530 Subject: [PATCH 6/7] qml: fix initial selection and optimize selection handling in artist list view --- .../gui/qt/medialibrary/qml/MusicArtist.qml | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/modules/gui/qt/medialibrary/qml/MusicArtist.qml b/modules/gui/qt/medialibrary/qml/MusicArtist.qml index ba312070ba72..457c004f81c2 100644 --- a/modules/gui/qt/medialibrary/qml/MusicArtist.qml +++ b/modules/gui/qt/medialibrary/qml/MusicArtist.qml @@ -212,6 +212,11 @@ FocusScope { textAlignHCenter: true dragItem: albumDragItem + // updates to selection is manually handled for optimization purpose + Component.onCompleted: _updateSelected() + + onIndexChanged: _updateSelected() + onPlayClicked: play() onItemDoubleClicked: play() @@ -224,8 +229,15 @@ FocusScope { Connections { target: albumsList.selectionModel - function onSelectionChanged() { - gridItem.selected = albumsList.selectionModel.isSelected(index) + function onSelectionChanged(selected, deselected) { + const idx = albumModel.index(gridItem.index, 0) + const findInSelection = s => s.find(range => range.contains(idx)) !== undefined + + // NOTE: we only get diff of the selection + if (findInSelection(selected)) + gridItem.selected = true + else if (findInSelection(deselected)) + gridItem.selected = false } } @@ -240,6 +252,10 @@ FocusScope { MediaLib.addAndPlay( model.id ) } } + + function _updateSelected() { + selected = albumSelectionModel.isRowSelected(gridItem.index) + } } onActionAtIndex: (index) => { albumModel.addAndPlay( new Array(index) ) } From 848c2c0d9db5b9001b482cc4cba0fb9709475ca3 Mon Sep 17 00:00:00 2001 From: Alexandre Janniaux Date: Tue, 18 Feb 2025 19:25:37 +0100 Subject: [PATCH 7/7] get-rust-target: fix triplet for x86/aarch64 android aarch64-unknown-linux-android is not the correct triplet for compiling rust for android, and "-unknown" should be dropped. The same applies to other targets except armv7, which ends with androideabi instead of android. --- contrib/src/get-rust-target.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/src/get-rust-target.sh b/contrib/src/get-rust-target.sh index 8dbb45cde6b9..dc6adea56eb7 100755 --- a/contrib/src/get-rust-target.sh +++ b/contrib/src/get-rust-target.sh @@ -121,7 +121,7 @@ case $OS in android) case $ARCH in aarch64|i686|x86_64) - return_triplet $TRIPLET + return_triplet "$ARCH-linux-android" ;; esac ;;