[vlc-commits] [Git][videolan/vlc][master] 9 commits: qt: change History from a dictionary structure to a flat list + property dictionary
Steve Lhomme (@robUx4)
gitlab at videolan.org
Mon Oct 16 12:52:39 UTC 2023
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
a02a0727 by Pierre Lamot at 2023-10-16T10:44:43+00:00
qt: change History from a dictionary structure to a flat list + property dictionary
exposing History properties as a single dictionary simplifies how view can
retrieve or alter its properties, by directly writing to the History.viewProp object
Recursive nature of the history path was underused, and we can achieve the same
behavior by having unique names for intermediates view properties
- - - - -
e13f4cda by Pierre Lamot at 2023-10-16T10:44:43+00:00
qml: move loadview function from StackViewExt to PageLoader
the component that we use to load view is PageLoader
- - - - -
56bac5ff by Pierre Lamot at 2023-10-16T10:44:43+00:00
qml: don't force the focus in subviews when the focus isn't a strong focus reason
- - - - -
e36f887b by Pierre Lamot at 2023-10-16T10:44:43+00:00
qml: update PageLoader loadView implementation
* page model is now a property of PageLoader
* page are loaded recursively and imperatively
* function parameters reflects updated History implementation
* page name is exposed in place of the former view property
- - - - -
ed08a23b by Pierre Lamot at 2023-10-16T10:44:43+00:00
qml: prefer altering History.viewProp rather than updating the history path
- - - - -
4222eedf by Pierre Lamot at 2023-10-16T10:44:43+00:00
qml: update navigation in Service and Browse sections
- - - - -
7fbe9dfe by Pierre Lamot at 2023-10-16T10:44:43+00:00
qml: use pagePrefix to build sub-page path
- - - - -
3ccda38f by Pierre Lamot at 2023-10-16T10:44:43+00:00
qml: bind focus color state to visualFocus
- - - - -
317de4df by Pierre Lamot at 2023-10-16T10:44:43+00:00
qt: remove temporary property viewPropLegacy in History
this property was here for compatibility before updating the views
- - - - -
23 changed files:
- modules/gui/qt/maininterface/qml/MainDisplay.qml
- modules/gui/qt/maininterface/qml/MainInterface.qml
- modules/gui/qt/medialibrary/qml/MusicAlbumsDisplay.qml
- modules/gui/qt/medialibrary/qml/MusicArtistsDisplay.qml
- modules/gui/qt/medialibrary/qml/MusicDisplay.qml
- modules/gui/qt/medialibrary/qml/MusicGenresDisplay.qml
- modules/gui/qt/medialibrary/qml/MusicPlaylistsDisplay.qml
- modules/gui/qt/medialibrary/qml/VideoAllDisplay.qml
- modules/gui/qt/medialibrary/qml/VideoDisplay.qml
- modules/gui/qt/medialibrary/qml/VideoPlaylistsDisplay.qml
- modules/gui/qt/network/qml/BrowseDisplay.qml
- modules/gui/qt/network/qml/BrowseHomeDisplay.qml
- modules/gui/qt/network/qml/BrowseTreeDisplay.qml
- modules/gui/qt/network/qml/DiscoverDisplay.qml
- modules/gui/qt/network/qml/ServicesHomeDisplay.qml
- modules/gui/qt/network/qml/ServicesSources.qml
- modules/gui/qt/util/navigation_history.cpp
- modules/gui/qt/util/navigation_history.hpp
- modules/gui/qt/widgets/qml/BannerTabButton.qml
- modules/gui/qt/widgets/qml/GridItem.qml
- modules/gui/qt/widgets/qml/LocalTabBar.qml
- modules/gui/qt/widgets/qml/PageLoader.qml
- modules/gui/qt/widgets/qml/StackViewExt.qml
Changes:
=====================================
modules/gui/qt/maininterface/qml/MainDisplay.qml
=====================================
@@ -36,12 +36,6 @@ import "qrc:///dialogs/" as DG
FocusScope {
id: g_mainDisplay
- //name and properties of the tab to be initially loaded
- property var view: ({
- "name": "",
- "properties": {}
- })
-
// Properties
property bool hasMiniPlayer: miniPlayer.visible
@@ -49,6 +43,9 @@ FocusScope {
// NOTE: The main view must be above the indexing bar and the mini player.
property real displayMargin: (height - miniPlayer.y) + (loaderProgress.active ? loaderProgress.height : 0)
+ //MainDisplay behave as a PageLoader
+ property alias pagePrefix: stackView.pagePrefix
+
readonly property int positionSliderY: {
var size = miniPlayer.y + miniPlayer.sliderY
@@ -61,22 +58,16 @@ FocusScope {
property bool _showMiniPlayer: false
property var _oldViewProperties: ({}) // saves last state of the views
- onViewChanged: {
- _oldViewProperties[view.name] = view.properties
- loadView()
- }
-
- Component.onCompleted: {
- loadView()
- }
+ // functions
- function loadView() {
- const found = stackView.loadView(g_mainDisplay.pageModel, g_mainDisplay.view.name, g_mainDisplay.view.properties)
+ //MainDisplay behave as a PageLoader
+ function loadView(path, properties, focusReason) {
+ const found = stackView.loadView(path, properties, focusReason)
+ if (!found)
+ return
const item = stackView.currentItem
- item.Navigation.parentItem = stackView
-
sourcesBanner.localMenuDelegate = Qt.binding(function () {
return !!item.localMenuDelegate ? item.localMenuDelegate : null
})
@@ -95,13 +86,6 @@ FocusScope {
MainCtx.sort.model = Qt.binding(function () { return item.sortModel })
MainCtx.sort.available = Qt.binding(function () { return Array.isArray(item.sortModel) && item.sortModel.length > 0 })
- // Restore sourcesBanner state
- sourcesBanner.selectedIndex = pageModel.filter(function (e) {
- return e.listed
- }).findIndex(function (e) {
- return e.name === g_mainDisplay.view.name
- })
-
if (Player.hasVideoOutput && MainCtx.hasEmbededVideo)
_showMiniPlayer = true
}
@@ -242,7 +226,7 @@ FocusScope {
if (_oldViewProperties[name] === undefined)
History.push(["mc", name])
else
- History.push(["mc", name, _oldViewProperties[name]])
+ History.push(["mc", name], _oldViewProperties[name])
}
Navigation.parentItem: medialibId
@@ -254,7 +238,7 @@ FocusScope {
Layout.fillHeight: true
z: 0
- Widgets.StackViewExt {
+ Widgets.PageLoader {
id: stackView
focus: true
@@ -271,6 +255,8 @@ FocusScope {
: parent.right
}
+ pageModel: g_mainDisplay.pageModel
+
leftPadding: VLCStyle.applicationHorizontalMargin
rightPadding: (MainCtx.playlistDocked && MainCtx.playlistVisible)
=====================================
modules/gui/qt/maininterface/qml/MainInterface.qml
=====================================
@@ -31,6 +31,7 @@ import "qrc:///util/" as Util
import "qrc:///playlist/" as PL
Item {
+ id: root
property bool _interfaceReady: false
property bool _playlistReady: false
@@ -49,15 +50,16 @@ Item {
//set the initial view
const loadPlayer = !MainPlaylistController.empty;
- if (MainCtx.mediaLibraryAvailable)
- History.push(["mc", "video"],
- Qt.OtherFocusReason, loadPlayer ? History.Stay : History.Go)
- else
- History.push(["mc", "home"],
- Qt.OtherFocusReason, loadPlayer ? History.Stay : History.Go)
-
if (loadPlayer)
+ {
+ if (MainCtx.mediaLibraryAvailable)
+ History.update(["mc", "video"])
+ else
+ History.update(["mc", "home"])
History.push(["player"])
+ }
+ else
+ _pushHome()
}
function _pushHome() {
@@ -67,20 +69,13 @@ Item {
History.push(["mc", "home"])
}
- function loadCurrentHistoryView() {
- const current = History.current
- if ( !current || !current.name || !current.properties ) {
- console.warn("unable to load requested view, undefined")
- return
- }
+ function loadCurrentHistoryView(focusReason) {
contextSaver.save(_oldHistoryPath)
- stackView.loadView(_pageModel, current.name, current.properties)
+ stackView.loadView(History.viewPath, History.viewProp, focusReason)
contextSaver.restore(History.viewPath)
_oldHistoryPath = History.viewPath
-
- MainCtx.mediaLibraryVisible = !History.match(History.viewPath, ["player"])
}
Util.ModelSortSettingHandler {
@@ -162,7 +157,10 @@ Item {
Connections {
target: History
- onCurrentChanged: loadCurrentHistoryView()
+ onNavigate: (focusReason) => {
+ loadCurrentHistoryView(focusReason)
+ MainCtx.mediaLibraryVisible = !History.match(History.viewPath, ["player"])
+ }
}
Connections {
@@ -239,12 +237,14 @@ Item {
}
}
- Widgets.StackViewExt {
+ Widgets.PageLoader {
id: stackView
anchors.fill: parent
focus: true
clip: _extendedFrameVisible
+ pageModel: _pageModel
+
Connections {
target: Player
onPlayingStateChanged: {
=====================================
modules/gui/qt/medialibrary/qml/MusicAlbumsDisplay.qml
=====================================
@@ -26,11 +26,9 @@ import "qrc:///widgets/" as Widgets
MusicAlbums {
id: root
- onCurrentIndexChanged: {
- History.update(["mc","music", "albums", {"initialIndex": currentIndex}])
- }
-
searchPattern: MainCtx.search.pattern
sortCriteria: MainCtx.sort.criteria
sortOrder: MainCtx.sort.order
+
+ onCurrentIndexChanged: History.viewProp.initialIndex = currentIndex
}
=====================================
modules/gui/qt/medialibrary/qml/MusicArtistsDisplay.qml
=====================================
@@ -34,40 +34,28 @@ Widgets.PageLoader {
pageModel: [{
name: "all",
+ default: true,
component: allArtistsComponent
}, {
name: "albums",
component: artistAlbumsComponent
}]
- loadDefaultView: function () {
- History.update(["mc", "music", "artists", "all"])
- loadPage("all")
- }
-
- function _updateArtistsAllHistory(currentIndex) {
- History.update(["mc", "music", "artists", "all", { "initialIndex": currentIndex }])
- }
-
- function _updateArtistsAlbumsHistory(currentIndex, initialAlbumIndex) {
- History.update(["mc","music", "artists", "albums", {
- "initialIndex": currentIndex,
- "initialAlbumIndex": initialAlbumIndex,
- }])
- }
Component {
id: allArtistsComponent
MusicAllArtists {
- onCurrentIndexChanged: _updateArtistsAllHistory(currentIndex)
searchPattern: MainCtx.search.pattern
sortOrder: MainCtx.sort.order
sortCriteria: MainCtx.sort.criteria
- onRequestArtistAlbumView: History.push(["mc", "music", "artists", "albums",
- { initialIndex: currentIndex }], reason)
+ onCurrentIndexChanged: History.viewProp.initialIndex = currentIndex
+
+ onRequestArtistAlbumView: (reason) => {
+ History.push([...root.pagePrefix, "albums"], { initialIndex: currentIndex }, reason)
+ }
}
}
@@ -75,15 +63,12 @@ Widgets.PageLoader {
id: artistAlbumsComponent
MusicArtistsAlbums {
-
- Navigation.parentItem: root
-
searchPattern: MainCtx.search.pattern
sortOrder: MainCtx.sort.order
sortCriteria: MainCtx.sort.criteria
- onCurrentIndexChanged: _updateArtistsAlbumsHistory(currentIndex, currentAlbumIndex)
- onCurrentAlbumIndexChanged: _updateArtistsAlbumsHistory(currentIndex, currentAlbumIndex)
+ onCurrentIndexChanged: History.viewProp.initialIndex = currentIndex
+ onCurrentAlbumIndexChanged: History.viewProp.initialAlbumIndex = currentAlbumIndex
}
}
}
=====================================
modules/gui/qt/medialibrary/qml/MusicDisplay.qml
=====================================
@@ -35,6 +35,7 @@ Widgets.PageLoader {
pageModel: [{
displayText: I18n.qtr("Artists"),
name: "artists",
+ default: true,
url: "qrc:///medialibrary/MusicArtistsDisplay.qml"
}, {
displayText: I18n.qtr("Albums"),
@@ -55,13 +56,8 @@ Widgets.PageLoader {
}
]
- loadDefaultView: function () {
- History.update(["mc", "music", "artists"])
- loadPage("artists")
- }
-
function loadIndex(index) {
- History.push(["mc", "music", root.pageModel[index].name])
+ History.push([...root.pagePrefix, root.pageModel[index].name])
}
property ListModel tabModel: ListModel {
@@ -75,14 +71,11 @@ Widgets.PageLoader {
}
}
- property Component localMenuDelegate: Widgets.LocalTabBar {
- currentView: root.view
+ localMenuDelegate: Widgets.LocalTabBar {
+ currentView: root.pageName
model: tabModel
onClicked: {
- if (root.pageModel[index].name === currentView.name)
- return
-
root.loadIndex(index)
}
}
=====================================
modules/gui/qt/medialibrary/qml/MusicGenresDisplay.qml
=====================================
@@ -30,42 +30,26 @@ Widgets.PageLoader {
pageModel: [{
name: "all",
+ default: true,
component: genresComponent
}, {
name: "albums",
component: albumGenreComponent
}]
- loadDefaultView: function () {
- History.update(["mc", "music", "genres", "all"])
- loadPage("all")
- }
-
-
- function _updateGenresAllHistory(currentIndex) {
- History.update(["mc", "music", "genres", "all", { "initialIndex": currentIndex }])
- }
-
- function _updateGenresAlbumsHistory(currentIndex, parentId, genreName) {
- History.update(["mc","music", "genres", "albums", {
- "initialIndex": currentIndex,
- "parentId": parentId,
- "genreName": genreName,
- }])
- }
-
Component {
id: genresComponent
/* List View */
MusicGenres {
- onCurrentIndexChanged: _updateGenresAllHistory(currentIndex)
+ onCurrentIndexChanged: History.viewProp.initialIndex = currentIndex
searchPattern: MainCtx.search.pattern
sortOrder: MainCtx.sort.order
sortCriteria: MainCtx.sort.criteria
- onShowAlbumView: History.push(["mc", "music", "genres", "albums",
- { parentId: id, genreName: name }], reason)
+ onShowAlbumView: (id, name, reason) => {
+ History.push([...root.pagePrefix, "albums"], { parentId: id, genreName: name }, reason)
+ }
}
}
@@ -93,9 +77,7 @@ Widgets.PageLoader {
sortOrder: MainCtx.sort.order
sortCriteria: MainCtx.sort.criteria
- onParentIdChanged: _updateGenresAlbumsHistory(currentIndex, parentId, genreName)
- onGenreNameChanged: _updateGenresAlbumsHistory(currentIndex, parentId, genreName)
- onCurrentIndexChanged: _updateGenresAlbumsHistory(currentIndex, parentId, genreName)
+ onCurrentIndexChanged: History.viewProp.initialIndex = currentIndex
}
}
}
=====================================
modules/gui/qt/medialibrary/qml/MusicPlaylistsDisplay.qml
=====================================
@@ -36,34 +36,13 @@ Widgets.PageLoader {
pageModel: [{
name: "all",
+ default: true,
component: componentAll
}, {
name: "list",
component: componentList
}]
- loadDefaultView: function () {
- History.update(["mc", "music", "playlists", "all"])
- loadPage("all")
- }
-
- //---------------------------------------------------------------------------------------------
- // Functions
- //---------------------------------------------------------------------------------------------
- // Private
-
- function _updateHistoryList(index) {
- History.update(["mc", "music", "playlists", "all", { "initialIndex": index }]);
- }
-
- function _updateHistoryPlaylist(playlist) {
- History.update(["mc", "music", "playlists", "list", {
- "initialIndex": playlist.currentIndex,
- "parentId" : playlist.parentId,
- "name" : playlist.name
- }]);
- }
-
//---------------------------------------------------------------------------------------------
// Childs
//---------------------------------------------------------------------------------------------
@@ -74,16 +53,15 @@ Widgets.PageLoader {
PlaylistMediaList {
isMusic: true
- onCurrentIndexChanged: _updateHistoryList(currentIndex)
-
- onShowList: (model, reason) => {
- History.push(["mc", "music", "playlists", "list",
- { parentId: model.id, name: model.name }], reason)
- }
-
searchPattern: MainCtx.search.pattern
sortOrder: MainCtx.sort.order
sortCriteria: MainCtx.sort.criteria
+
+ onCurrentIndexChanged: History.viewProp.initialIndex = currentIndex
+
+ onShowList: (model, reason) => {
+ History.push([...root.pagePrefix, "list"], { parentId: model.id, name: model.name }, reason)
+ }
}
}
@@ -99,9 +77,7 @@ Widgets.PageLoader {
sortOrder: MainCtx.sort.order
sortCriteria: MainCtx.sort.criteria
- onCurrentIndexChanged: _updateHistoryPlaylist(playlist)
- onParentIdChanged : _updateHistoryPlaylist(playlist)
- onNameChanged : _updateHistoryPlaylist(playlist)
+ onCurrentIndexChanged: History.viewProp.initialIndex = currentIndex
}
}
}
=====================================
modules/gui/qt/medialibrary/qml/VideoAllDisplay.qml
=====================================
@@ -38,6 +38,7 @@ Widgets.PageLoader {
pageModel: [{
name: "base",
+ default: true,
component: componentBase
}, {
name: "group",
@@ -47,29 +48,11 @@ Widgets.PageLoader {
component: componentRecentVideos
}]
- loadDefaultView: function () {
- History.update(["mc", "video", "all", "base"])
- loadPage("base")
- }
-
// Events
onCurrentItemChanged: {
sortMenu = currentItem.sortMenu
}
- // Functions private
-
- function _updateHistoryAll(index) {
- History.update(["mc", "video", "all", "base", { "initialIndex": index }])
- }
-
- function _updateHistoryGroup(group) {
- History.update(["mc", "video", "all", "group", {
- "initialIndex": group.currentIndex,
- "parentId" : group.parentId,
- "title" : group.title
- }])
- }
// Children
@@ -80,12 +63,10 @@ Widgets.PageLoader {
// Events
onShowList: (model, reason) => {
- History.push(["mc", "video", "all", "group",
- { parentId: model.id, title: model.title }], reason)
+ History.push([...root.pagePrefix, "group"], { parentId: model.id, title: model.title }, reason)
}
-
- onCurrentIndexChanged: root._updateHistoryAll(currentIndex)
+ onCurrentIndexChanged: History.viewProp.initialIndex = currentIndex
}
}
@@ -95,9 +76,7 @@ Widgets.PageLoader {
MediaGroupDisplay {
id: group
- onCurrentIndexChanged: root._updateHistoryGroup(group)
- onParentIdChanged : root._updateHistoryGroup(group)
- onTitleChanged : root._updateHistoryGroup(group)
+ onCurrentIndexChanged: History.viewProp.initialIndex = currentIndex
function isInfoExpandPanelAvailable(/* modelIndexData */) {
return true
=====================================
modules/gui/qt/medialibrary/qml/VideoDisplay.qml
=====================================
@@ -46,17 +46,12 @@ Widgets.PageLoader {
}
}
- property Component localMenuDelegate: Widgets.LocalTabBar {
- currentView: root.view
+ localMenuDelegate: Widgets.LocalTabBar {
+ currentView: root.pageName
model: tabModel
- onClicked: {
- if (root.pageModel[index].name === currentView.name)
- return
-
- root.loadIndex(index)
- }
+ onClicked: (index) => History.push([...root.pagePrefix, root.pageModel[index].name])
}
//---------------------------------------------------------------------------------------------
@@ -65,6 +60,7 @@ Widgets.PageLoader {
pageModel: [{
name: "all",
+ default: true,
displayText: I18n.qtr("All"),
url: "qrc:///medialibrary/VideoAllDisplay.qml"
},{
@@ -74,11 +70,6 @@ Widgets.PageLoader {
}
]
- loadDefaultView: function () {
- History.update(["mc", "video", "all"])
- loadPage("all")
- }
-
Accessible.role: Accessible.Client
Accessible.name: I18n.qtr("Video view")
@@ -86,12 +77,4 @@ Widgets.PageLoader {
// NOTE: We need bindings because the VideoAll model can change over time.
sortMenu = Qt.binding(function () { return currentItem.sortMenu; })
}
-
- //---------------------------------------------------------------------------------------------
- // Functions
- //---------------------------------------------------------------------------------------------
-
- function loadIndex(index) {
- History.push(["mc", "video", root.pageModel[index].name]);
- }
}
=====================================
modules/gui/qt/medialibrary/qml/VideoPlaylistsDisplay.qml
=====================================
@@ -36,34 +36,13 @@ Widgets.PageLoader {
pageModel: [{
name: "all",
+ default: true,
component: componentAll
}, {
name: "list",
component: componentList
}]
- loadDefaultView: function () {
- History.update(["mc", "video", "playlists", "all"])
- loadPage("all")
- }
-
- //---------------------------------------------------------------------------------------------
- // Functions
- //---------------------------------------------------------------------------------------------
- // Private
-
- function _updateHistoryList(index) {
- History.update(["mc", "video", "playlists", "all", { "initialIndex": index }]);
- }
-
- function _updateHistoryPlaylist(playlist) {
- History.update(["mc", "video", "playlists", "list", {
- "currentIndex": playlist.currentIndex,
- "parentId" : playlist.parentId,
- "name" : playlist.name
- }]);
- }
-
//---------------------------------------------------------------------------------------------
// Childs
//---------------------------------------------------------------------------------------------
@@ -79,11 +58,10 @@ Widgets.PageLoader {
sortOrder: MainCtx.sort.order
sortCriteria: MainCtx.sort.criteria
- onCurrentIndexChanged: _updateHistoryList(currentIndex)
+ onCurrentIndexChanged: History.viewProp.initialIndex = currentIndex
onShowList: (model, reason) => {
- History.push(["mc", "video", "playlists", "list",
- { parentId: model.id, name: model.name }], reason);
+ History.push([...root.pagePrefix, "list"], { parentId: model.id, name: model.name }, reason)
}
}
}
@@ -100,9 +78,7 @@ Widgets.PageLoader {
sortOrder: MainCtx.sort.order
sortCriteria: MainCtx.sort.criteria
- onCurrentIndexChanged: _updateHistoryPlaylist(playlist)
- onParentIdChanged : _updateHistoryPlaylist(playlist)
- onNameChanged : _updateHistoryPlaylist(playlist)
+ onCurrentIndexChanged: History.viewProp.initialIndex = currentIndex
}
}
}
=====================================
modules/gui/qt/network/qml/BrowseDisplay.qml
=====================================
@@ -33,7 +33,8 @@ Widgets.PageLoader {
pageModel: [{
name: "home",
- url: "qrc:///network/BrowseHomeDisplay.qml"
+ default: true,
+ component: browseHome
}, {
name: "folders",
component: browseFolders,
@@ -46,37 +47,49 @@ Widgets.PageLoader {
guard: function (prop) { return !!prop.tree }
}]
- loadDefaultView: function() {
- History.update(["mc", "network", "home"])
- loadPage("home")
- }
-
- localMenuDelegate: (view.name !== "home") ? componentBar : null
+ localMenuDelegate: (pageName !== "home") ? componentBar : null
Accessible.role: Accessible.Client
Accessible.name: I18n.qtr("Browse view")
- // Connections
- Connections {
- target: (Helpers.isValidInstanceOf(currentItem, BrowseHomeDisplay)) ? currentItem
- : null
-
- onSeeAll: {
- if (sd_source === -1)
- History.push(["mc", "network", "folders", { title: title }], reason)
- else
- History.push(["mc", "network", "device", { title: title, sd_source: sd_source }],
- reason)
- }
+ //functions
+
+ function _showBrowseNode(tree, reason) {
+ History.push([...root.pagePrefix, "browse"], { tree: tree }, reason)
}
- Connections {
- target: root.currentItem
+ function _showHome(reason) {
+ History.push([...root.pagePrefix, "home"], reason)
+ }
+
+
+ function _showBrowseFolder(title, reason) {
+ History.push([...root.pagePrefix, "folders"], { title: title }, reason)
+ }
- onBrowse: History.push(["mc", "network", "browse", { tree: tree }], reason)
+ function _showBrowseDevices(title, sd_source, reason) {
+ History.push([...root.pagePrefix, "device"], { title: title, sd_source: sd_source }, reason)
}
// Children
+ Component {
+ id: browseHome
+
+ BrowseHomeDisplay {
+ onSeeAllDevices: (title, sd_source, reason) => {
+ root._showBrowseDevices(title, sd_source, reason)
+ }
+
+ onSeeAllFolders:(title, reason) => {
+ root._showBrowseFolder(title, reason)
+ }
+
+ onBrowse: (tree, reason) => {
+ root._showBrowseNode(tree, reason)
+ }
+ }
+ }
+
Component {
id: browseFolders
@@ -94,6 +107,10 @@ Widgets.PageLoader {
sortOrder: MainCtx.sort.order
searchPattern: MainCtx.search.pattern
}
+
+ onBrowse: (tree, reason) => { root._showBrowseNode(tree, reason) }
+
+ onCurrentIndexChanged: History.viewProp.initialIndex = currentIndex
}
}
@@ -103,7 +120,7 @@ Widgets.PageLoader {
BrowseDeviceView {
id: viewDevice
- property var sd_source
+ /*required*/ property var sd_source
property var sortModel: [
{ text: I18n.qtr("Alphabetic"), criteria: "name" },
@@ -122,6 +139,12 @@ Widgets.PageLoader {
sortOrder: MainCtx.sort.order
searchPattern: MainCtx.search.pattern
}
+
+ onBrowse: (tree, reason) => {
+ root._showBrowseNode(tree, reason)
+ }
+
+ onCurrentIndexChanged: History.viewProp.initialIndex = currentIndex
}
}
@@ -129,6 +152,9 @@ Widgets.PageLoader {
id: browseComponent
BrowseTreeDisplay {
+
+ property alias tree: mediaModel.tree
+
model: NetworkMediaModel {
id: mediaModel
@@ -146,6 +172,12 @@ Widgets.PageLoader {
Navigation.cancelAction: function() {
History.previous(Qt.BacktabFocusReason)
}
+
+ onBrowse: (tree, reason) => {
+ root._showBrowseNode(tree, reason)
+ }
+
+ onCurrentIndexChanged: History.viewProp.initialIndex = currentIndex
}
}
@@ -153,11 +185,11 @@ Widgets.PageLoader {
id: componentBar
NetworkAddressbar {
- path: view.name === "browse" ? root.currentItem.model.path : []
+ path: root.pageName === "browse" ? root.currentItem.model.path : []
- onHomeButtonClicked: History.push(["mc", "network", "home"], reason)
+ onHomeButtonClicked: root._showHome(reason)
- onBrowse: History.push(["mc", "network", "browse", { "tree": tree }], reason)
+ onBrowse: (tree, reason) => { root._showBrowseNode(tree, reason) }
}
}
}
=====================================
modules/gui/qt/network/qml/BrowseHomeDisplay.qml
=====================================
@@ -59,7 +59,8 @@ FocusScope {
// Signals
- signal seeAll(var title, var sd_source, int reason)
+ signal seeAllDevices(var title, var sd_source, int reason)
+ signal seeAllFolders(var title, int reason)
signal browse(var tree, int reason)
@@ -171,7 +172,7 @@ FocusScope {
onBrowse: root.browse(tree, reason)
- onSeeAll: root.seeAll(title, -1, reason)
+ onSeeAll: root.seeAllFolders(title, reason)
onActiveFocusChanged: _centerFlickableOnItem(foldersSection)
onCurrentIndexChanged: _centerFlickableOnItem(foldersSection)
@@ -221,7 +222,7 @@ FocusScope {
onBrowse: root.browse(tree, reason)
- onSeeAll: root.seeAll(title, model.sd_source, reason)
+ onSeeAll: root.seeAllDevices(title, model.sd_source, reason)
onActiveFocusChanged: _centerFlickableOnItem(deviceSection)
onCurrentIndexChanged: _centerFlickableOnItem(deviceSection)
@@ -265,7 +266,7 @@ FocusScope {
onBrowse: root.browse(tree, reason)
- onSeeAll: root.seeAll(title, model.sd_source, reason)
+ onSeeAll: root.seeAllDevices(title, model.sd_source, reason)
onActiveFocusChanged: _centerFlickableOnItem(lanSection)
onCurrentIndexChanged: _centerFlickableOnItem(lanSection)
=====================================
modules/gui/qt/network/qml/BrowseTreeDisplay.qml
=====================================
@@ -32,7 +32,6 @@ MainInterface.MainViewLoader {
// Properties
property var contextMenu
- property var tree
readonly property var currentIndex: _currentView.currentIndex
@@ -66,8 +65,6 @@ MainInterface.MainViewLoader {
History.previous(Qt.BacktabFocusReason)
}
- onTreeChanged: model.tree = tree
-
function playSelected() {
model.addAndPlay(selectionModel.selectedIndexes)
}
=====================================
modules/gui/qt/network/qml/DiscoverDisplay.qml
=====================================
@@ -31,6 +31,7 @@ Widgets.PageLoader {
pageModel: [{
displayText: I18n.qtr("Services"),
+ default: true,
name: "services",
url: "qrc:///network/ServicesHomeDisplay.qml"
}, {
@@ -40,18 +41,13 @@ Widgets.PageLoader {
}
]
- loadDefaultView: function () {
- History.update(["mc", "discover", "services"])
- loadPage("services")
- }
-
localMenuDelegate: menuDelegate
Accessible.role: Accessible.Client
Accessible.name: I18n.qtr("Discover view")
function loadIndex(index) {
- History.push(["mc", "discover", root.pageModel[index].name])
+ History.push([...root.pagePrefix, root.pageModel[index].name])
}
@@ -70,11 +66,11 @@ Widgets.PageLoader {
id: menuDelegate
Widgets.LocalTabBar {
- currentView: root.view
+ currentView: root.pageName
model: tabModel
onClicked: {
- if (root.pageModel[index].name === currentView.name)
+ if (root.pageModel[index].name === root.pageName)
return
root.loadIndex(index)
=====================================
modules/gui/qt/network/qml/ServicesHomeDisplay.qml
=====================================
@@ -32,7 +32,8 @@ Widgets.PageLoader {
pageModel: [{
name: "all",
- url: "qrc:///network/ServicesSources.qml"
+ default: true,
+ component: serviceSourceComponent
}, {
name: "services_manage",
url: "qrc:///network/ServicesManage.qml"
@@ -45,15 +46,39 @@ Widgets.PageLoader {
guard: function (prop) { return !!prop.tree }
}]
- loadDefaultView: function() {
- History.update(["mc", "discover", "services", "all"])
- loadPage("all")
+
+ function _showServiceHome(reason) {
+ History.push([...root.pagePrefix, "services"], reason)
+ }
+
+ function _showServiceManage(reason) {
+ History.push([...root.pagePrefix, "services_manage"], reason)
+ }
+
+ function _showServiceRoot(source_name, reason) {
+ History.push([...root.pagePrefix, "source_root"], { source_name: source_name }, reason)
+ }
+
+ function _showServiceNode(tree, source_name, reason) {
+ History.push(
+ [...root.pagePrefix, "source_browse"],
+ {
+ tree: tree,
+ source_name: source_name
+ },
+ reason)
}
- function setCurrentItemFocus(reason) {
- stackView.currentItem.setCurrentItemFocus(reason);
+ Component {
+ id: serviceSourceComponent
+
+ ServicesSources {
+ onBrowseServiceManage: (reason) => root._showServiceManage(reason)
+ onBrowseSourceRoot: (name, reason) => root. _showServiceRoot(name, reason)
+ }
}
+
Component {
id: sourceRootComponent
@@ -63,15 +88,17 @@ Widgets.PageLoader {
property Component localMenuDelegate: NetworkAddressbar {
path: [{display: deviceModel.name, tree: {}}]
- onHomeButtonClicked: History.push(["mc", "discover", "services"], reason)
+ onHomeButtonClicked: _showServiceHome(reason)
}
model: deviceModel
contextMenu: contextMenu
- onBrowse: History.push(["mc", "discover", "services", "source_browse",
- { tree: tree, "root_name": deviceModel.name,
- "source_name": source_name }], reason)
+ onBrowse: (tree, reason) => {
+ root._showServiceNode(tree, deviceModel.source_name, reason)
+ }
+
+ onCurrentIndexChanged: History.viewProp.initialIndex = currentIndex
NetworkDeviceModel {
id: deviceModel
@@ -92,7 +119,7 @@ Widgets.PageLoader {
id: sourceBrowseComponent
BrowseTreeDisplay {
- property string root_name
+ property alias tree: mediaModel.tree
property string source_name
property Component localMenuDelegate: NetworkAddressbar {
@@ -102,20 +129,19 @@ Widgets.PageLoader {
return _path
}
- onHomeButtonClicked: History.push(["mc", "discover", "services"], reason)
+ onHomeButtonClicked: root._showServiceHome(reason)
- onBrowse: {
- if (!!tree.isRoot)
- History.push(["mc", "discover", "services", "source_root",
- { source_name: tree.source_name }], reason)
+ onBrowse: (tree, reason) => {
+ if (tree.isRoot)
+ root._showServiceRoot(source_name, reason)
else
- History.push(["mc", "discover", "services", "source_browse",
- { tree: tree, "root": root_name }], reason)
+ root._showServiceNode(tree, source_name, reason)
}
}
- onBrowse: History.push(["mc", "discover", "services", "source_browse",
- { tree: tree, "root": root_name }], reason)
+ onBrowse: root._showServiceNode(tree, source_name, reason)
+
+ onCurrentIndexChanged: History.viewProp.initialIndex = currentIndex
model: NetworkMediaModel {
id: mediaModel
=====================================
modules/gui/qt/network/qml/ServicesSources.qml
=====================================
@@ -29,9 +29,18 @@ import "qrc:///style/"
MainInterface.MainGridView {
id: root
+ //properties
+
readonly property bool hasGridListMode: false
readonly property bool isSearchable: true
+ //signals
+
+ signal browseServiceManage(int reason)
+ signal browseSourceRoot(string sourceName, int reason)
+
+ //settings
+
selectionDelegateModel: selectionModel
model: sourcesModel
topMargin: VLCStyle.margin_large
@@ -82,11 +91,9 @@ MainInterface.MainGridView {
onItemDoubleClicked: {
if (is_dummy)
- History.push(["mc", "discover", "services", "services_manage"],
- Qt.MouseFocusReason)
+ root.browseServiceManage(Qt.MouseFocusReason)
else
- History.push(["mc", "discover", "services", "source_root",
- { source_name: model.name }], Qt.MouseFocusReason)
+ root.browseSourceRoot(model.name, Qt.TabFocusReason)
}
onItemClicked : {
@@ -100,10 +107,9 @@ MainInterface.MainGridView {
const itemData = sourcesModel.getDataAt(index);
if (itemData.type === NetworkSourcesModel.TYPE_DUMMY)
- History.push(["mc", "discover", "services", "services_manage"], Qt.TabFocusReason)
+ browseServiceManage(Qt.TabFocusReason)
else
- History.push(["mc", "discover", "services", "source_root",
- { source_name: itemData.name }], Qt.TabFocusReason)
+ browseSourceRoot(itemData.name, Qt.TabFocusReason)
}
Navigation.cancelAction: function() {
=====================================
modules/gui/qt/util/navigation_history.cpp
=====================================
@@ -3,96 +3,46 @@
#include "network/networkmediamodel.hpp"
#include "medialibrary/mlqmltypes.hpp"
-
NavigationHistory::NavigationHistory(QObject *parent)
- : QObject(parent),
- m_reason(Qt::OtherFocusReason)
+ : QObject(parent)
{
}
-QVariant NavigationHistory::getCurrent()
-{
- assert(m_history.isEmpty() == false);
-
- return m_history.back();
-}
-
bool NavigationHistory::isPreviousEmpty()
{
- return m_history.count() <= 1;
+ return m_history.size() <= 1;
}
-void NavigationHistory::push(QVariantMap item, Qt::FocusReason reason, PostAction postAction)
+void NavigationHistory::push(QStringList path, const QVariantMap& properties, Qt::FocusReason focusReason)
{
- m_history.push_back(item);
- emit previousEmptyChanged(false);
- if (postAction == PostAction::Go)
- {
- updateViewPath();
+ auto prop = std::make_unique<QQmlPropertyMap>();
+ for (auto it = properties.keyValueBegin(); it != properties.keyValueEnd(); ++it)
+ prop->insert((*it).first, (*it).second);
- m_reason = reason;
+ m_history.emplace_back(path, std::move(prop));
- emit currentChanged(m_history.back());
- }
-}
+ updateCurrent();
-static void pushListRec(QVariantMap& itemMap, QVariantList::const_iterator it, QVariantList::const_iterator end )
-{
- if (it == end)
- return;
- if(it->canConvert<QString>())
- {
- QVariantMap subViewMap;
- subViewMap["name"] = it->toString();
- QVariantMap subViewProperties;
- pushListRec(subViewProperties, ++it, end);
- subViewMap["properties"] = subViewProperties;
- itemMap["view"] = subViewMap;
- }
- else if ( it->canConvert<QVariantMap>() )
- {
- QVariantMap varMap = it->toMap();
- for (auto kv = varMap.constBegin(); kv != varMap.constEnd(); ++kv )
- itemMap[kv.key()] = kv.value();
- pushListRec(itemMap, ++it, end);
- }
+ if (m_history.size() == 2)
+ emit previousEmptyChanged(false);
+
+ emit navigate(focusReason);
}
-static void addLeafRec(QVariant &item, const QVariantMap &leaf)
+void NavigationHistory::push(QStringList path, Qt::FocusReason focusReason)
{
- auto itemMap = item.toMap();
- if (itemMap.contains("view"))
- {
- QVariant viewProps = itemMap.value("view");
- addLeafRec(viewProps, leaf);
- itemMap["view"] = viewProps;
- }
- else if (itemMap.contains("properties"))
- {
- QVariant propsVar = itemMap.value("properties");
- const auto propsMap = propsVar.toMap();
- if (propsMap.empty())
- {
- itemMap["properties"] = leaf;
- }
- else
- {
- addLeafRec(propsVar, leaf);
- itemMap["properties"] = propsVar;
- }
- }
- else
- {
- // invalid node?
- return;
- }
+ m_history.emplace_back(path, std::make_unique<QQmlPropertyMap>());
- //overwrite item QVariant
- item = itemMap;
-}
+ updateCurrent();
+
+ if (m_history.size() == 2)
+ emit previousEmptyChanged(false);
+ emit navigate(focusReason);
+
+}
-static bool isNodeValid(QVariant& value)
+static bool isNodeValid(const QVariant& value)
{
if (value.canConvert(QVariant::StringList)
|| value.canConvert(QVariant::StringList)
@@ -107,7 +57,8 @@ static bool isNodeValid(QVariant& value)
else if ( value.canConvert(QVariant::List) )
{
QVariantList valueList = value.toList();
- for (QVariant& v : valueList) {
+ for (QVariant& v : valueList)
+ {
if (!isNodeValid(v))
return false;
}
@@ -117,18 +68,17 @@ static bool isNodeValid(QVariant& value)
{
NetworkTreeItem item = value.value<NetworkTreeItem>();
if ( ! item.isValid() )
- {
return false;
- }
+
return true;
}
else if ( value.canConvert(QVariant::Map) )
{
QVariantMap valueList = value.toMap();
- for (QVariant& v : valueList.values()) {
- if (!isNodeValid(v)) {
+ for (QVariant& v : valueList.values())
+ {
+ if (!isNodeValid(v))
return false;
- }
}
return true;
}
@@ -137,91 +87,81 @@ static bool isNodeValid(QVariant& value)
return false;
}
-static QStringList getViewPath(QVariantMap map)
+static bool isNodeValid(const QQmlPropertyMap& value)
{
- QStringList r;
- if (map.contains("view"))
- return getViewPath(map.value("view").toMap());
- else if (map.contains("name"))
+ for (auto it: value.keys())
{
- r = QStringList( map.value("name").toString() );
- r.append(std::move(getViewPath(map.value("properties").toMap())));
+ if (!isNodeValid(value[it]))
+ return false;
}
- return r;
+ return true;
}
-void NavigationHistory::push(QVariantList itemList, Qt::FocusReason reason,
- NavigationHistory::PostAction postAction)
-{
- QVariantMap itemMap;
- pushListRec(itemMap, itemList.cbegin(), itemList.cend());
- if (!itemMap.contains("view"))
- return;
- QVariant rootView = itemMap["view"];
- if (!rootView.canConvert(QVariant::Map))
- return;
- push(rootView.toMap(), reason, postAction);
-}
-void NavigationHistory::update(QVariantMap item)
+void NavigationHistory::update(QStringList path)
{
- assert(m_history.size() >= 1);
- m_history.back() = item;
- updateViewPath();
+ if (m_history.size() == 0)
+ {
+ m_history.emplace_back(path, std::make_unique<QQmlPropertyMap>());
+ }
+ else
+ {
+ auto& last = *m_history.rbegin();
+ last.first = path;
+ }
+ updateCurrent();
}
-void NavigationHistory::update(QVariantList itemList)
+void NavigationHistory::update(QStringList path, const QVariantMap& properties)
{
- QVariantMap itemMap;
- pushListRec(itemMap, itemList.cbegin(), itemList.cend());
- if (!itemMap.contains("view"))
- return;
- QVariant rootView = itemMap["view"];
- if (!rootView.canConvert(QVariant::Map))
- return;
- update(rootView.toMap());
+ if (m_history.size() == 0)
+ {
+ auto prop = std::make_unique<QQmlPropertyMap>();
+ for (auto it = properties.keyValueBegin(); it != properties.keyValueEnd(); ++it)
+ {
+ prop->insert((*it).first, (*it).second);
+ }
+ m_history.emplace_back(path, std::move(prop));
+ }
+ else
+ {
+ auto& last = *m_history.rbegin();
+ last.first = path;
+ }
+ updateCurrent();
}
-void NavigationHistory::addLeaf(QVariantMap itemMap)
-{
- assert(m_history.size() >= 1);
- addLeafRec(m_history.back(), itemMap);
- updateViewPath();
-}
-void NavigationHistory::previous(Qt::FocusReason reason, PostAction postAction)
+void NavigationHistory::previous(Qt::FocusReason reason)
{
- if (m_history.count() == 1)
+ if (m_history.size() == 1)
return;
m_history.pop_back();
- while (!isNodeValid(m_history.back())) {
+
+ while (!isNodeValid(*m_history.back().second)) {
m_history.pop_back();
- if (m_history.count() == 1)
+ if (m_history.size() == 1)
break;
}
- if (m_history.count() == 1)
+ if (m_history.size() == 1)
emit previousEmptyChanged(true);
- if (postAction == PostAction::Go) {
- updateViewPath();
-
- m_reason = reason;
-
- emit currentChanged( m_history.back() );
- }
+ updateCurrent();
+ emit navigate(reason);
}
-void NavigationHistory::updateViewPath()
+void NavigationHistory::updateCurrent()
{
- const auto viewPath = getViewPath(getCurrent().toMap());
- if (viewPath == m_viewPath)
- return;
+ assert(m_history.size() >= 1);
+ const auto it = m_history.rbegin();
- m_viewPath = viewPath;
- emit viewPathChanged( m_viewPath );
+ m_viewPath = it->first;
+ m_viewProperties = it->second.get();
+ emit viewPathChanged(m_viewPath);
+ emit viewPropChanged(m_viewProperties);
}
QStringList NavigationHistory::viewPath() const
@@ -229,13 +169,9 @@ QStringList NavigationHistory::viewPath() const
return m_viewPath;
}
-Qt::FocusReason NavigationHistory::takeFocusReason()
+QQmlPropertyMap* NavigationHistory::viewProp() const
{
- Qt::FocusReason reason = m_reason;
-
- m_reason = Qt::OtherFocusReason;
-
- return reason;
+ return m_viewProperties;
}
Q_INVOKABLE bool NavigationHistory::match(const QStringList& path, const QStringList& pattern)
=====================================
modules/gui/qt/util/navigation_history.hpp
=====================================
@@ -1,6 +1,8 @@
#ifndef NAVIGATION_HISTORY_HPP
#define NAVIGATION_HISTORY_HPP
+#include <memory>
+
#include <QObject>
#include <QtQml/QQmlPropertyMap>
@@ -8,9 +10,17 @@ class NavigationHistory : public QObject
{
Q_OBJECT
public:
- Q_PROPERTY(QVariant current READ getCurrent NOTIFY currentChanged FINAL)
Q_PROPERTY(bool previousEmpty READ isPreviousEmpty NOTIFY previousEmptyChanged FINAL)
+ /**
+ * current path
+ */
Q_PROPERTY(QStringList viewPath READ viewPath NOTIFY viewPathChanged FINAL)
+ /**
+ * properties of the current view,
+ * * properties that are pushed will be accessible thru this property
+ * * views may store values in this property, they will be restored when navigating back
+ */
+ Q_PROPERTY(QQmlPropertyMap* viewProp READ viewProp NOTIFY viewPropChanged FINAL)
enum class PostAction{
Stay,
@@ -24,90 +34,57 @@ public:
QVariant getCurrent();
bool isPreviousEmpty();
QStringList viewPath() const;
-
- // NOTE: The first item to call this takes ownership over the focus reason.
- Q_INVOKABLE Qt::FocusReason takeFocusReason();
+ QQmlPropertyMap* viewProp() const;
Q_INVOKABLE bool match(const QStringList& path, const QStringList& pattern);
Q_INVOKABLE bool exactMatch(const QStringList& path, const QStringList& pattern);
signals:
- void currentChanged(QVariant current);
+ void navigate(Qt::FocusReason);
void previousEmptyChanged(bool empty);
void viewPathChanged(const QStringList& viewPath);
+ void viewPropChanged(QQmlPropertyMap*);
public slots:
/**
- * Push a
*
- * \code
- * push({
- * name: "foo", //push the view foo
- * properties: {
- * view: { //the sub view "bar"
- * name: "bar",
- * properties: {
- * baz: "plop" //the property baz will be set in the view "bar"
- * }
- * }
- * }
- * }, History.Go)
- * \endcode
- */
- Q_INVOKABLE void push( QVariantMap, Qt::FocusReason = Qt::OtherFocusReason,
- PostAction = PostAction::Go );
-
- /**
- * provide a short version of the history push({k:v}), which implicitly create a dictonnary tree from the input list
- *
- * List items are interpreted as
- * * strings will push a dict with "view" key to the value of the string and
- * a "viewProperties" dict configured with the tail of the list
+ * navigate to a new page
*
- * * dict: values will be added to the current viewProperty
+ * @param path: path of the page to load
+ * @param properties: values that will be set to the current viewProp
*
* example:
* \code
* //push the view foo, then bar, set baz to plop in the view "bar"
- * push(["foo", "bar", {baz: "plop"} ], History.Go)
+ * push(["foo", "bar"], {baz: "plop"})
* \endcode
*/
- Q_INVOKABLE void push(QVariantList itemList, Qt::FocusReason = Qt::OtherFocusReason,
- PostAction = PostAction::Go );
+ Q_INVOKABLE void push(QStringList path, const QVariantMap& properties, Qt::FocusReason focusReason = Qt::OtherFocusReason);
+ Q_INVOKABLE void push(QStringList path, Qt::FocusReason focusReason = Qt::OtherFocusReason);
- /**
- * @brief same as @a push(QVariantMap) but modify the last (current) item instead of insterting a new one
- *
- * @see push
- */
- Q_INVOKABLE void update(QVariantMap itemList);
/**
- * @brief same as @a push(QVariantList) but modify the last (current) item instead of insterting a new one
+ * @brief modify the current history path
*
- * @see push
+ * @note:
+ * * invoking update won't cause page to be reloaded, this mainly affects history
+ * * invoking update when there is no path will create a node (the initial history node)
*/
- Q_INVOKABLE void update(QVariantList itemList);
+ Q_INVOKABLE void update(QStringList path);
- /**
- * @brief same as @a push(QVariantList) but modify the last (current) item's tail instead of insterting a new one
- *
- * @see push
- */
- Q_INVOKABLE void addLeaf(QVariantMap itemMap);
+ Q_INVOKABLE void update(QStringList path, const QVariantMap& properties);
- // Go to previous page
- void previous( Qt::FocusReason = Qt::OtherFocusReason, PostAction = PostAction::Go );
+ /// Go to previous page
+ void previous(Qt::FocusReason = Qt::OtherFocusReason);
private:
- void updateViewPath();
+ void updateCurrent();
- QVariantList m_history;
+ std::vector<std::pair<QStringList, std::unique_ptr<QQmlPropertyMap>>> m_history;
QStringList m_viewPath;
-
- Qt::FocusReason m_reason;
+ QQmlPropertyMap* m_viewProperties = nullptr;
};
#endif // NAVIGATION_HISTORY_HPP
=====================================
modules/gui/qt/widgets/qml/BannerTabButton.qml
=====================================
@@ -77,7 +77,7 @@ T.TabButton {
id: theme
colorSet: ColorContext.TabButton
- focused: control.activeFocus
+ focused: control.visualFocus
hovered: control.hovered
pressed: control.down
enabled: control.enabled
=====================================
modules/gui/qt/widgets/qml/GridItem.qml
=====================================
@@ -158,7 +158,7 @@ T.ItemDelegate {
id: theme
colorSet: ColorContext.Item
- focused: root.activeFocus
+ focused: root.visualFocus
hovered: root.hovered
}
=====================================
modules/gui/qt/widgets/qml/LocalTabBar.qml
=====================================
@@ -32,7 +32,7 @@ NavigableRow {
delegate: BannerTabButton {
text: model.displayText
- selected: model.name === row.currentView.name
+ selected: model.name === row.currentView
showCurrentIndicator: false
height: VLCStyle.localToolbar_height
onClicked: row.clicked(index)
=====================================
modules/gui/qt/widgets/qml/PageLoader.qml
=====================================
@@ -18,20 +18,21 @@
import QtQuick 2.12
import org.videolan.vlc 0.1
+import "qrc:///util/Helpers.js" as Helpers
+
StackViewExt {
id: root
// Properties
- property var view: null
+ //name of the loaded page
+ property string pageName: ""
- property var pageModel: []
+ //path of the current page loader
+ property var pagePrefix: []
- // loadDefaultView - function ()
- // a function that loads the default page,
- // must be implemented by the user of the class
- // one may use `loadPage(string pageName)` to load the page from 'pageModel'
- property var loadDefaultView: null
+ //list of available pages
+ property var pageModel: []
//indicates whether the subview support grid/list mode
readonly property bool hasGridListMode: (currentItem
@@ -50,66 +51,118 @@ StackViewExt {
&& currentItem.localMenuDelegate
&& (currentItem.localMenuDelegate instanceof Component)) ? currentItem.localMenuDelegate : null
- // Private
-
- property bool _ready: false
-
-
- // Signals
-
- signal pageChanged(string page)
-
- // Events
-
- Component.onCompleted: {
- _ready = true
-
- _loadView()
- }
-
- onViewChanged: _loadView()
// Functions
- function _loadView() {
- // NOTE: We wait for the item to be fully loaded to avoid size glitches.
- if (_ready === false)
- return
-
- if (view === null) {
- if (!loadDefaultView)
- console.error("both 'view' and 'loadDefaultView' is null, history -", JSON.stringify(History.current))
- else
- loadDefaultView()
- return
+ /**
+ * @arg {string[]} path - the (sub) path to load
+ * @arg {Object.<string, Object>} properties - the properties to apply to the loaded view
+ * @arg {number} focusReason - the initial focus reason
+ */
+ function loadView(path, properties, focusReason)
+ {
+ if (currentItem && typeof currentItem.dismiss === "function")
+ currentItem.dismiss()
+
+ if (path.length === 0) {
+ path = _getDefaultPage()
+ if (path.length === 0) {
+ console.assert("trying to load an empty view path")
+ return false
+ }
}
- if (view.name === "") {
- console.error("view is not defined")
- return
- }
- if (pageModel.length === 0) {
- console.error("pageModel is not defined")
- return
- }
+ const head = path[0]
- const reason = History.takeFocusReason()
+ //We always reload if the last node even if this is the same page, as initial properties may differ
+ //for the intermediary pages, we can just forward the request down the tree
+ if (pageName === head && path.length > 1) {
+ return _reloadPage(path, properties, focusReason)
+ }
- const found = root.loadView(root.pageModel, view.name, view.properties)
+ let found = false
+ for (let tab = 0; tab < pageModel.length; tab++ ) {
+
+ const model = pageModel[tab]
+ if (model.name === head) {
+ if (model.guard !== undefined && typeof model.guard === "function" && !model.guard(properties)) {
+ continue //we're not allowed to load this page
+ }
+
+ //we can't use push(url, properties) as Qt interprets viewProperties
+ //as a second component to load
+ let component = undefined
+ if (model.component) {
+ component = model.component
+ } else if ( model.url ) {
+ component = Qt.createComponent(model.url)
+ } else {
+ console.warn( "you should define either component or url of the view to load" )
+ return false
+ }
+
+ if (component.status === Component.Ready ) {
+
+ let pageProp = {
+ pagePrefix:[...pagePrefix, head]
+ }
+ for (const key of properties.keys()) {
+ pageProp[key] = properties[key]
+ }
+
+ root.replace(null, component, pageProp)
+ found = true
+ break;
+ } else {
+ console.warn("component is not ready: " + component.errorString())
+ }
+ }
+ }
if (!found) {
- console.error("failed to load", JSON.stringify(History.current))
- return
+ console.warn("unable to load view " + head)
+ return false
}
+ pageName = head
currentItem.Navigation.parentItem = root
+ //pages like MainDisplay are not page PageLoader, so just check for the loadView function
+ if (typeof currentItem.loadView === "function") {
+ currentItem.loadView(path.slice(1), properties, focusReason)
+ } else {
+ setCurrentItemFocus(focusReason)
+ }
- if (reason !== Qt.OtherFocusReason)
- setCurrentItemFocus(reason)
+ return true
+ }
- currentItemChanged(currentItem)
+ function _getDefaultPage() {
+ for (let tab = 0; tab < pageModel.length; tab++ ) {
+ if (pageModel[tab].default) {
+ return [pageModel[tab].name]
+ }
+ }
+ console.assert("no default page set")
+ return []
}
- function loadPage(page) {
- view = {"name": page, "properties": {}}
+ function _reloadPage(path, properties, focusReason)
+ {
+ if (!currentItem) {
+ console.warn("try to update subpage, but page isn't loaded")
+ return false
+ }
+
+ for (const key of properties.keys()) {
+ if (currentItem.hasOwnProperty(key))
+ currentItem[key] = properties[key]
+ }
+
+ if (typeof currentItem.loadView === "function") {
+ currentItem.loadView(path.slice(1), properties, focusReason)
+ } else if (path.length > 1) {
+ console.warn("unable to load subpath", path.slice(1))
+ return false
+ }
+ return true
}
}
=====================================
modules/gui/qt/widgets/qml/StackViewExt.qml
=====================================
@@ -26,9 +26,17 @@ import "qrc:///style/"
StackView {
id: root
- // Private
+ // Functions
- property string _currentView: ""
+ function setCurrentItemFocus(reason) {
+ if (reason === Qt.OtherFocusReason)
+ return
+ focus = true
+ focusReason = reason
+ if (typeof currentItem.setCurrentItemFocus === "function")
+ currentItem.setCurrentItemFocus(reason)
+
+ }
// Settings
@@ -61,74 +69,4 @@ StackView {
})
}
}
-
- // Functions
-
- /**
- * viewModel: model with the definition of the available view
- * elements should contains at least :
- * name: name of the view
- * url or component: the url of the Component or the component to load
- * view: string (name of the view to load)
- * viewProperties: map of the propertes to apply to the view
- */
- function loadView(viewModel, view, viewProperties)
- {
- if (root.currentItem && root.currentItem.hasOwnProperty("dismiss"))
- root.currentItem.dismiss()
-
- if (view === _currentView) {
- if (Object.keys(viewProperties).length === 0 && root.currentItem.hasOwnProperty("loadDefaultView") ) {
- root.currentItem.loadDefaultView()
- } else {
- for ( let viewProp in viewProperties ) {
- if ( root.currentItem.hasOwnProperty(viewProp) ) {
- root.currentItem[viewProp] = viewProperties[viewProp]
- }
- }
- }
- return true
- }
-
- let found = false
- for (let tab = 0; tab < viewModel.length; tab++ )
- {
- const model = viewModel[tab]
- if (model.name === view) {
- if (model.guard !== undefined && typeof model.guard === "function" && !model.guard(viewProperties)) {
- continue //we're not allowed to load this page
- }
-
- //we can't use push(url, properties) as Qt interprets viewProperties
- //as a second component to load
- let component = undefined
- if (model.component) {
- component = model.component
- } else if ( model.url ) {
- component = Qt.createComponent(model.url)
- } else {
- console.warn( "you should define either component or url of the view to load" )
- return false
- }
-
- if (component.status === Component.Ready ) {
- //note doesn't work with qt 5.9
- root.replace(null, component, viewProperties)
- found = true
- break;
- } else {
- console.warn("component is not ready: " + component.errorString())
- }
- }
- }
- if (!found)
- console.warn("unable to load view " + view)
- else
- _currentView = view
- return found
- }
-
- function setCurrentItemFocus(reason) {
- currentItem.setCurrentItemFocus(reason);
- }
}
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/8b1f9fb457805168d1faa618cdac19cdcc0dfbca...317de4dfab14a0e1264a338602ad73ccca31867b
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/8b1f9fb457805168d1faa618cdac19cdcc0dfbca...317de4dfab14a0e1264a338602ad73ccca31867b
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list