[vlc-commits] [Git][videolan/vlc][master] 9 commits: qml/VideoAll(s): Update navigation behavior
Jean-Baptiste Kempf (@jbk)
gitlab at videolan.org
Fri Nov 19 13:03:53 UTC 2021
Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC
Commits:
8353b657 by Benjamin Arnaud at 2021-11-19T11:20:20+00:00
qml/VideoAll(s): Update navigation behavior
- - - - -
b8ce8d11 by Benjamin Arnaud at 2021-11-19T11:20:20+00:00
qml/KeyNavigableListView: Update scrolling button(s) implementation
- - - - -
21775727 by Benjamin Arnaud at 2021-11-19T11:20:20+00:00
qml/ExpandGridView: Refactor implementation
- - - - -
7a3db792 by Benjamin Arnaud at 2021-11-19T11:20:20+00:00
qml/ExpandGridView: Add the 'contentMargin' property
- - - - -
a33d7eec by Benjamin Arnaud at 2021-11-19T11:20:20+00:00
qml/VideoAll: Add the 'contentMargin' property
- - - - -
be357dd8 by Benjamin Arnaud at 2021-11-19T11:20:20+00:00
qml/VideoDisplayRecentVideos: Update dimensions, margin and spacing
fix #26138
- - - - -
62466cc0 by Benjamin Arnaud at 2021-11-19T11:20:20+00:00
qml/VideoAllDisplay: Update the header margin(s)
- - - - -
c3c10cec by Benjamin Arnaud at 2021-11-19T11:20:20+00:00
qml/MediaGroupDisplay: Update header padding(s)
- - - - -
b18e2bf7 by Benjamin Arnaud at 2021-11-19T11:20:20+00:00
qml/VLCStyle: Remove unused 'gridCover' properties
- - - - -
7 changed files:
- modules/gui/qt/medialibrary/qml/MediaGroupDisplay.qml
- modules/gui/qt/medialibrary/qml/VideoAll.qml
- modules/gui/qt/medialibrary/qml/VideoAllDisplay.qml
- modules/gui/qt/medialibrary/qml/VideoDisplayRecentVideos.qml
- modules/gui/qt/style/VLCStyle.qml
- modules/gui/qt/widgets/qml/ExpandGridView.qml
- modules/gui/qt/widgets/qml/KeyNavigableListView.qml
Changes:
=====================================
modules/gui/qt/medialibrary/qml/MediaGroupDisplay.qml
=====================================
@@ -59,13 +59,17 @@ VideoAll {
}
header: Column {
+ width: root.width
+
topPadding: VLCStyle.margin_normal
+ bottomPadding: VLCStyle.margin_normal
Widgets.SubtitleLabel {
- width: root.width
+ anchors.left: parent.left
+ anchors.right: parent.right
- leftPadding : VLCStyle.margin_xlarge
- bottomPadding: VLCStyle.margin_xsmall
+ // NOTE: We want this to be properly aligned with the grid items.
+ anchors.leftMargin: contentMargin + VLCStyle.margin_normal
text: root.name
}
=====================================
modules/gui/qt/medialibrary/qml/VideoAll.qml
=====================================
@@ -34,6 +34,10 @@ FocusScope {
// Properties
+ readonly property int contentMargin: (mainInterface.gridView
+ &&
+ _currentView) ? _currentView.contentMargin : 0
+
// NOTE: Specify an optionnal header for the view.
property Component header: undefined
@@ -100,10 +104,10 @@ FocusScope {
if (initialIndex >= model.count)
initialIndex = 0
- modelSelect.select(model.index(initialIndex, 0), ItemSelectionModel.ClearAndSelect);
+ modelSelect.select(model.index(initialIndex, 0), ItemSelectionModel.ClearAndSelect)
if (_currentView)
- _currentView.positionViewAtIndex(initialIndex, ItemView.Contain);
+ _currentView.positionViewAtIndex(initialIndex, ItemView.Contain)
}
// Private
@@ -114,9 +118,18 @@ FocusScope {
medialib.addAndPlay(model.getIdsForIndexes(modelSelect.selectedIndexes));
}
+ // Events
+
+ function _onNavigationUp() {
+ if (headerItem && headerItem.focus)
+ headerItem.setCurrentItemFocus(Qt.TabFocusReason);
+ else
+ Navigation.defaultNavigationUp();
+ }
+
function _onNavigationCancel() {
if (_currentView.currentIndex <= 0) {
- Navigation.defaultNavigationCancel()
+ Navigation.defaultNavigationCancel();
} else {
_currentView.currentIndex = 0;
@@ -200,7 +213,8 @@ FocusScope {
activeFocusOnTab: true
Navigation.parentItem: root
- Navigation.upItem: (headerItem) ? headerItem.focusItem : null
+
+ Navigation.upAction: _onNavigationUp
//cancelAction takes a *function* pass it directly
Navigation.cancelAction: root._onNavigationCancel
@@ -322,7 +336,8 @@ FocusScope {
activeFocusOnTab: true
Navigation.parentItem: root
- Navigation.upItem: (headerItem) ? headerItem.focusItem : null
+
+ Navigation.upAction: _onNavigationUp
//cancelAction takes a *function* pass it directly
Navigation.cancelAction: root._onNavigationCancel
=====================================
modules/gui/qt/medialibrary/qml/VideoAllDisplay.qml
=====================================
@@ -41,10 +41,8 @@ VideoAll {
// Functions
function setCurrentItemFocus(reason) {
- var loader = headerItem.loader;
-
- if (loader.visible)
- loader.item.forceActiveFocus(reason);
+ if (modelRecent.count)
+ headerItem.setCurrentItemFocus(reason);
else
_currentView.setCurrentItemFocus(reason);
}
@@ -65,17 +63,29 @@ VideoAll {
width: root.width
topPadding: VLCStyle.margin_normal
-
- spacing: VLCStyle.margin_normal
+ bottomPadding: VLCStyle.margin_normal
// NOTE: We want the header to be visible when we have at least one media visible.
// Otherwise it overlaps the default caption.
visible: (model.count)
+ // NOTE: Making sure this item will be focussed by VideoAll::_onNavigationUp().
+ focus: true
+
+ function setCurrentItemFocus(reason) {
+ var item = loader.item;
+
+ if (item)
+ item.setCurrentItemFocus(reason);
+ }
+
Loader {
id: loader
- width: parent.width
+ anchors.left : parent.left
+ anchors.right: parent.right
+
+ anchors.margins: root.contentMargin
height: (status === Loader.Ready) ? item.implicitHeight : 0
@@ -88,6 +98,9 @@ VideoAll {
width: parent.width
+ // NOTE: We want grid items to be visible on the sides.
+ displayMargins: root.contentMargin
+
model: modelRecent
focus: true
@@ -101,10 +114,11 @@ VideoAll {
}
Widgets.SubtitleLabel {
- width: root.width
+ anchors.left: loader.left
+ anchors.right: loader.right
- leftPadding : VLCStyle.margin_xlarge
- bottomPadding: VLCStyle.margin_xsmall
+ // NOTE: We want this to be properly aligned with the grid items.
+ anchors.leftMargin: VLCStyle.margin_normal
text: i18n.qtr("Videos")
}
=====================================
modules/gui/qt/medialibrary/qml/VideoDisplayRecentVideos.qml
=====================================
@@ -32,15 +32,16 @@ FocusScope {
// Properties
- property int leftPadding: VLCStyle.margin_xlarge
- property int rightPadding: VLCStyle.margin_xlarge
-
property Item focusItem: recentVideosListView
property int currentIndex: -1
property var model: undefined;
+ // Properties
+
+ property int displayMargins: 0
+
// Settings
implicitHeight: recentVideosColumn.height
@@ -56,6 +57,12 @@ FocusScope {
root.currentIndex = 0
}
+ // Functions
+
+ function setCurrentItemFocus(reason) {
+ recentVideosListView.setCurrentItemFocus(reason);
+ }
+
function _actionAtIndex(index, model, selectionModel) {
g_mainDisplay.showPlayer()
medialib.addAndPlay( model.getIdsForIndexes( selectionModel.selectedIndexes ), [":restore-playback-pos=2"] )
@@ -77,8 +84,13 @@ FocusScope {
Widgets.SubtitleLabel {
id: continueWatchingLabel
- leftPadding: VLCStyle.margin_xlarge
- width: parent.width
+
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ // NOTE: We want this to be properly aligned with the grid items.
+ anchors.leftMargin: VLCStyle.margin_normal
+
text: i18n.qtr("Continue Watching")
}
@@ -86,18 +98,30 @@ FocusScope {
id: recentVideosListView
width: parent.width
- implicitHeight: VLCStyle.gridItem_video_height_large + VLCStyle.gridItemSelectedBorder + VLCStyle.margin_xlarge
+
+ implicitHeight: VLCStyle.gridItem_video_height + VLCStyle.gridItemSelectedBorder
+ +
+ VLCStyle.margin_xlarge
+
spacing: VLCStyle.column_margin_width
+
+ // NOTE: Sometimes, we want items to be visible on the sides.
+ displayMarginBeginning: root.displayMargins
+ displayMarginEnd: root.displayMargins
+
+ // NOTE: We want navigation buttons to be centered on the item cover.
+ buttonMargin: VLCStyle.margin_xsmall + VLCStyle.gridCover_video_height / 2 - buttonLeft.height / 2
+
orientation: ListView.Horizontal
focus: true
- Navigation.parentItem: root
-
model: root.model
+ Navigation.parentItem: root
+
header: Item {
- width: VLCStyle.margin_xlarge
+ width: VLCStyle.margin_normal
}
delegate: VideoGridItem {
@@ -105,8 +129,8 @@ FocusScope {
x: selectedBorderWidth
y: selectedBorderWidth
- pictureWidth: VLCStyle.gridCover_video_width_large
- pictureHeight: VLCStyle.gridCover_video_height_large
+ pictureWidth: VLCStyle.gridCover_video_width
+ pictureHeight: VLCStyle.gridCover_video_height
focus: true
@@ -142,7 +166,7 @@ FocusScope {
}
footer: Item {
- width: VLCStyle.margin_xlarge
+ width: VLCStyle.margin_normal
}
onSelectionUpdated: recentVideoSelection.updateSelection( keyModifiers, oldIndex, newIndex )
@@ -154,8 +178,8 @@ FocusScope {
Widgets.GridShadows {
id: shadows
- coverWidth: VLCStyle.gridCover_video_width_large
- coverHeight: VLCStyle.gridCover_video_height_large
+ coverWidth: VLCStyle.gridCover_video_width
+ coverHeight: VLCStyle.gridCover_video_height
}
}
}
=====================================
modules/gui/qt/style/VLCStyle.qml
=====================================
@@ -164,9 +164,6 @@ QtObject {
readonly property int gridCover_video_height: ( gridCover_video_width * 10.0 ) / 16
readonly property int gridCover_video_border: dp(4, scale)
- readonly property int gridCover_video_width_large: dp(406, scale)
- readonly property int gridCover_video_height_large: ( gridCover_video_width_large * 10.0 ) / 16
-
readonly property int gridCover_radius: dp(4, scale)
readonly property int expandCover_music_height: dp(171, scale)
@@ -186,10 +183,6 @@ QtObject {
readonly property int gridItem_video_width: VLCStyle.gridCover_video_width
readonly property int gridItem_video_height: VLCStyle.gridCover_video_height + VLCStyle.margin_xxsmall + VLCStyle.fontHeight_normal + VLCStyle.fontHeight_normal
- readonly property int gridItem_video_width_large: VLCStyle.gridCover_video_width_large
- readonly property int gridItem_video_height_large: VLCStyle.gridCover_video_height_large + VLCStyle.margin_xxsmall + VLCStyle.fontHeight_large +
- VLCStyle.margin_xxsmall + VLCStyle.fontHeight_normal
-
readonly property int gridItemSelectedBorder: dp(8, scale)
readonly property int gridItem_newIndicator: dp(8, scale)
=====================================
modules/gui/qt/widgets/qml/ExpandGridView.qml
=====================================
@@ -25,6 +25,8 @@ import "qrc:///util/Helpers.js" as Helpers
FocusScope {
id: root
+ // Properties
+
/// cell Width
property int cellWidth: 100
// cell Height
@@ -36,25 +38,31 @@ FocusScope {
property int leftMargin: VLCStyle.margin_normal
property int rightMargin: VLCStyle.margin_normal
+ // NOTE: The grid margin for the item(s) horizontal positioning.
+ readonly property int contentMargin: (_contentWidth - _nbItemPerRow * _effectiveCellWidth
+ +
+ horizontalSpacing) / 2
+
property int rowX: 0
property int horizontalSpacing: VLCStyle.column_margin_width
property int verticalSpacing: VLCStyle.column_margin_width
property int displayMarginEnd: 0
- onDisplayMarginEndChanged: flickable.layout(false)
readonly property int _effectiveCellWidth: cellWidth + horizontalSpacing
readonly property int _effectiveCellHeight: cellHeight + verticalSpacing
+ readonly property int _contentWidth: width - rightMargin - leftMargin
+
+ readonly property int _nbItemPerRow: Math.max(Math.floor((_contentWidth + horizontalSpacing)
+ /
+ _effectiveCellWidth), 1)
+
property var delegateModel
property var model
property int currentIndex: 0
- property alias contentHeight: flickable.contentHeight
- property alias contentWidth: flickable.contentWidth
- property alias contentX: flickable.contentX
- property alias gridScrollBar: flickableScrollBar
property bool isAnimating: animateRetractItem.running || animateExpandItem.running
property int _count: 0
@@ -70,37 +78,200 @@ FocusScope {
property int _currentFocusReason: Qt.OtherFocusReason
- on_ExpandItemVerticalSpaceChanged: {
- if (expandItem) {
- expandItem.visible = root._expandItemVerticalSpace - root.verticalSpacing > 0
- expandItem.height = Math.max(root._expandItemVerticalSpace - root.verticalSpacing, 0)
- }
- flickable.layout(true)
- }
-
//delegate to display the extended item
property Component delegate: Item{}
property Component expandDelegate: Item{}
- property alias expandItem: expandItemLoader.item
property Component headerDelegate: Item{}
+
+ property var _idChildrenList: []
+ property var _unusedItemList: []
+ property var _currentRange: [0,0]
+
+ // Aliases
+
+ property alias contentHeight: flickable.contentHeight
+ property alias contentWidth: flickable.contentWidth
+ property alias contentX: flickable.contentX
+ property alias gridScrollBar: flickableScrollBar
+
+ property alias expandItem: expandItemLoader.item
+
property alias headerHeight: headerItemLoader.implicitHeight
property alias headerItem: headerItemLoader.item
property alias footerItem: footerItemLoader.item
property alias footerDelegate: footerItemLoader.sourceComponent
+ // Signals
+
//signals emitted when selected items is updated from keyboard
signal selectionUpdated( int keyModifiers, int oldIndex,int newIndex )
signal selectAll()
signal actionAtIndex(int index)
- property var _idChildrenList: []
- property var _unusedItemList: []
- property var _currentRange: [0,0]
+ // Settings
Accessible.role: Accessible.Table
+ // Events
+
+ Component.onCompleted: flickable.layout(true)
+
+ onHeightChanged: flickable.layout(false)
+
+ // NOTE: Update on contentMargin change rather than width since the margin defines the x
+ // position and depends on the width.
+ onContentMarginChanged: flickable.layout(true)
+
+ onDisplayMarginEndChanged: flickable.layout(false)
+
+ onModelChanged: _onModelCountChanged()
+
+ onCurrentIndexChanged: {
+ if (expandIndex !== -1)
+ retract()
+ positionViewAtIndex(currentIndex, ItemView.Contain)
+ }
+
+ on_ExpandItemVerticalSpaceChanged: {
+ if (expandItem) {
+ expandItem.visible = _expandItemVerticalSpace - verticalSpacing > 0
+ expandItem.height = Math.max(_expandItemVerticalSpace - verticalSpacing, 0)
+ }
+ flickable.layout(true)
+ }
+
+ // Keys
+
+ Keys.onPressed: {
+ var newIndex = -1
+ if (KeyHelper.matchRight(event)) {
+ if ((currentIndex + 1) % _nbItemPerRow !== 0) {//are we not at the end of line
+ newIndex = Math.min(_count - 1, currentIndex + 1)
+ }
+ } else if (KeyHelper.matchLeft(event)) {
+ if (currentIndex % _nbItemPerRow !== 0) {//are we not at the begining of line
+ newIndex = Math.max(0, currentIndex - 1)
+ }
+ } else if (KeyHelper.matchDown(event)) {
+ // we are not on the last line
+ if (Math.floor(currentIndex / _nbItemPerRow) !== Math.floor(_count / _nbItemPerRow)) {
+ newIndex = Math.min(_count - 1, currentIndex + _nbItemPerRow)
+ }
+ } else if (KeyHelper.matchPageDown(event)) {
+ newIndex = Math.min(_count - 1, currentIndex + _nbItemPerRow * 5)
+ } else if (KeyHelper.matchUp(event)) {
+ if (Math.floor(currentIndex / _nbItemPerRow) !== 0) { //we are not on the first line
+ newIndex = Math.max(0, currentIndex - _nbItemPerRow)
+ }
+ } else if (KeyHelper.matchPageUp(event)) {
+ newIndex = Math.max(0, currentIndex - _nbItemPerRow * 5)
+ } else if (KeyHelper.matchOk(event) || event.matches(StandardKey.SelectAll) ) {
+ //these events are matched on release
+ event.accepted = true
+ }
+
+ if (event.matches(StandardKey.SelectAll) || KeyHelper.matchOk(event)) {
+ _releaseActionButtonPressed = true
+ } else {
+ _releaseActionButtonPressed = false
+ }
+
+ if (newIndex !== -1 && newIndex !== currentIndex) {
+ event.accepted = true;
+
+ var oldIndex = currentIndex;
+ currentIndex = newIndex;
+ selectionUpdated(event.modifiers, oldIndex, newIndex);
+
+ // NOTE: We make sure we have the proper visual focus on components.
+ if (oldIndex < currentIndex)
+ setCurrentItemFocus(Qt.TabFocusReason);
+ else
+ setCurrentItemFocus(Qt.BacktabFocusReason);
+ }
+
+ if (!event.accepted) {
+ Navigation.defaultKeyAction(event)
+ }
+ }
+
+ Keys.onReleased: {
+ if (!_releaseActionButtonPressed)
+ return
+
+ if (event.matches(StandardKey.SelectAll)) {
+ event.accepted = true
+ selectAll()
+ } else if ( KeyHelper.matchOk(event) ) {
+ event.accepted = true
+ actionAtIndex(currentIndex)
+ }
+ _releaseActionButtonPressed = false
+ }
+
+ // Connections
+
+ Connections {
+ target: model
+ onDataChanged: {
+ var iMin = topLeft.row
+ var iMax = bottomRight.row + 1 // [] => [)
+ var f_l = _currentRange
+ if (iMin < f_l[1] && f_l[0] < iMax) {
+ _refreshData(iMin, iMax)
+ }
+ }
+ onRowsInserted: _onModelCountChanged()
+ onRowsRemoved: _onModelCountChanged()
+ onModelReset: _onModelCountChanged()
+ }
+
+ Connections {
+ target: delegateModel
+
+ onSelectionChanged: {
+ var i
+ for (i = 0; i < selected.length; ++i) {
+ _updateSelectedRange(selected[i].topLeft, selected[i].bottomRight, true)
+ }
+
+ for (i = 0; i < deselected.length; ++i) {
+ _updateSelectedRange(deselected[i].topLeft, deselected[i].bottomRight, false)
+ }
+ }
+
+ function _updateSelectedRange(topLeft, bottomRight, select) {
+ var iMin = topLeft.row
+ var iMax = bottomRight.row + 1 // [] => [)
+ if (iMin < root._currentRange[1] && root._currentRange[0] < iMax) {
+ iMin = Math.max(iMin, root._currentRange[0])
+ iMax = Math.min(iMax, root._currentRange[1])
+ for (var j = iMin; j < iMax; j++) {
+ var item = root._getItem(j)
+ console.assert(item)
+ item.selected = select
+ }
+ }
+ }
+ }
+
+ Connections {
+ target: mainInterface
+ onIntfScaleFactorChanged: flickable.layout(true)
+ }
+
+ // Animations
+
+ PropertyAnimation {
+ id: animateContentY;
+ target: flickable;
+ properties: "contentY"
+ }
+
+ // Functions
+
function setCurrentItemFocus(reason) {
// NOTE: Saving the focus reason for later.
@@ -149,24 +320,16 @@ FocusScope {
flickable.retract()
}
- function getNbItemsPerRow() {
- return Math.max(Math.floor(((width - root.rightMargin - root.leftMargin) + root.horizontalSpacing) / root._effectiveCellWidth), 1)
- }
-
function getItemRowCol(id) {
- var nbItemsPerRow = getNbItemsPerRow()
- var rowId = Math.floor(id / nbItemsPerRow)
- var colId = id % nbItemsPerRow
+ var rowId = Math.floor(id / _nbItemPerRow)
+ var colId = id % _nbItemPerRow
return [colId, rowId]
}
function getItemPos(id) {
- var remainingSpace = (flickable.width - rightMargin - leftMargin)
- - getNbItemsPerRow() * _effectiveCellWidth + horizontalSpacing;
-
var rowCol = getItemRowCol(id);
- var x = rowCol[0] * _effectiveCellWidth + remainingSpace / 2 + leftMargin;
+ var x = rowCol[0] * _effectiveCellWidth + contentMargin + leftMargin;
var y = rowCol[1] * _effectiveCellHeight + headerHeight + topMargin;
@@ -190,13 +353,13 @@ FocusScope {
var newContentY = flickable.contentY
- var itemTopY = root.getItemPos(index)[1]
- var itemBottomY = itemTopY + root._effectiveCellHeight
+ var itemTopY = getItemPos(index)[1]
+ var itemBottomY = itemTopY + _effectiveCellHeight
var viewTopY = flickable.contentY
var viewBottomY = viewTopY + flickable.height
- if (index < getNbItemsPerRow()) {
+ if (index < _nbItemPerRow) {
//force to see the header when on the first row
newContentY = 0
} else if ( itemTopY < viewTopY ) {
@@ -212,12 +375,12 @@ FocusScope {
}
function leftClickOnItem(modifier, index) {
- delegateModel.updateSelection( modifier , currentIndex, index)
+ delegateModel.updateSelection(modifier, currentIndex, index)
if (delegateModel.isSelected(model.index(index, 0)))
currentIndex = index
else if (currentIndex === index) {
- if (root._containsItem(currentIndex))
- root._getItem(currentIndex).focus = false
+ if (_containsItem(currentIndex))
+ _getItem(currentIndex).focus = false
currentIndex = -1
}
@@ -227,27 +390,36 @@ FocusScope {
function rightClickOnItem(index) {
if (!delegateModel.isSelected(model.index(index, 0))) {
- root.leftClickOnItem(Qt.NoModifier, index)
+ leftClickOnItem(Qt.NoModifier, index)
}
}
+ function animateFlickableContentY( newContentY ) {
+ animateContentY.stop()
+ animateContentY.duration = VLCStyle.duration_slow
+ animateContentY.to = newContentY
+ animateContentY.start()
+ }
+
+ // Private
+
function _initialize() {
- if (root._isInitialised)
+ if (_isInitialised)
return;
if (flickable.width === 0 || flickable.height === 0)
return;
if (currentIndex !== 0)
positionViewAtIndex(currentIndex, ItemView.Contain)
- root._isInitialised = true;
+ _isInitialised = true;
}
function _calculateCurrentRange() {
- var myContentY = flickable.contentY - root.headerHeight - topMargin
+ var myContentY = flickable.contentY - headerHeight - topMargin
var contentYWithoutExpand = myContentY
- var heightWithoutExpand = flickable.height + root.displayMarginEnd
- if (root.expandIndex !== -1) {
+ var heightWithoutExpand = flickable.height + displayMarginEnd
+ if (expandIndex !== -1) {
if (myContentY >= expandItem.y && myContentY < expandItem.y + _expandItemVerticalSpace)
contentYWithoutExpand = expandItem.y
if (myContentY >= expandItem.y + _expandItemVerticalSpace)
@@ -259,33 +431,33 @@ FocusScope {
heightWithoutExpand -= expandDisplayedHeight
}
- var rowId = Math.floor(contentYWithoutExpand / root._effectiveCellHeight)
- var firstId = Math.max(rowId * root.getNbItemsPerRow(), 0)
+ var rowId = Math.floor(contentYWithoutExpand / _effectiveCellHeight)
+ var firstId = Math.max(rowId * _nbItemPerRow, 0)
- rowId = Math.ceil((contentYWithoutExpand + heightWithoutExpand) / root._effectiveCellHeight)
- var lastId = Math.min(rowId * root.getNbItemsPerRow(), _count)
+ rowId = Math.ceil((contentYWithoutExpand + heightWithoutExpand) / _effectiveCellHeight)
+ var lastId = Math.min(rowId * _nbItemPerRow, _count)
return [firstId, lastId]
}
function _getItem(id) {
- var i = id - root._currentRange[0]
- return root._idChildrenList[i]
+ var i = id - _currentRange[0]
+ return _idChildrenList[i]
}
function _setItem(id, item) {
- var i = id - root._currentRange[0]
- root._idChildrenList[i] = item
+ var i = id - _currentRange[0]
+ _idChildrenList[i] = item
}
function _containsItem(id) {
- var i = id - root._currentRange[0]
- return i >= 0 && i < root._idChildrenList.length && typeof root._idChildrenList[i] !== "undefined"
+ var i = id - _currentRange[0]
+ return i >= 0 && i < _idChildrenList.length && typeof _idChildrenList[i] !== "undefined"
}
function _repositionItem(id, x, y) {
- var item = root._getItem(id)
+ var item = _getItem(id)
if (item === undefined)
throw "wrong child: " + id
@@ -309,13 +481,13 @@ FocusScope {
item.y = y
item.visible = true
- root._setItem(id, item)
+ _setItem(id, item)
return item
}
function _createItem(id, x, y) {
- var item = root.delegate.createObject( flickable.contentItem, {
+ var item = delegate.createObject( flickable.contentItem, {
selected: delegateModel.isSelected(model.index(id, 0)),
index: id,
model: model.getDataAt(id),
@@ -326,17 +498,17 @@ FocusScope {
if (item === undefined)
throw "wrong unable to instantiate child " + id
- root._setItem(id, item)
+ _setItem(id, item)
return item
}
function _setupChild(id, ydelta) {
- var pos = root.getItemPos(id)
+ var pos = getItemPos(id)
var item;
- if (root._containsItem(id))
+ if (_containsItem(id))
item = _repositionItem(id, pos[0], pos[1] + ydelta)
else if (_unusedItemList.length > 0)
item = _recycleItem(id, pos[0], pos[1] + ydelta)
@@ -351,25 +523,25 @@ FocusScope {
}
function _refreshData( iMin, iMax ) {
- var f_l = root._currentRange
+ var f_l = _currentRange
if (!iMin || iMin < f_l[0])
iMin = f_l[0]
if (!iMax || iMax > f_l[1])
iMax= f_l[1]
for (var id = iMin; id < iMax; id++) {
- var item = root._getItem(id)
+ var item = _getItem(id)
item.model = model.getDataAt(id)
}
- if (root.expandIndex >= iMin && root.expandIndex < iMax) {
- expandItem.model = model.getDataAt(root.expandIndex)
+ if (expandIndex >= iMin && expandIndex < iMax) {
+ expandItem.model = model.getDataAt(expandIndex)
}
}
function _onModelCountChanged() {
_count = model ? model.rowCount() : 0
- if (!root._isInitialised)
+ if (!_isInitialised)
return
// Hide the expandItem with no animation
@@ -381,56 +553,7 @@ FocusScope {
_refreshData()
}
- Connections {
- target: model
- onDataChanged: {
- var iMin = topLeft.row
- var iMax = bottomRight.row + 1 // [] => [)
- var f_l = root._currentRange
- if (iMin < f_l[1] && f_l[0] < iMax) {
- _refreshData(iMin, iMax)
- }
- }
- onRowsInserted: _onModelCountChanged()
- onRowsRemoved: _onModelCountChanged()
- onModelReset: _onModelCountChanged()
- }
-
- Connections {
- target: delegateModel
-
- onSelectionChanged: {
- var i
- for (i = 0; i < selected.length; ++i) {
- _updateSelectedRange(selected[i].topLeft, selected[i].bottomRight, true)
- }
-
- for (i = 0; i < deselected.length; ++i) {
- _updateSelectedRange(deselected[i].topLeft, deselected[i].bottomRight, false)
- }
- }
-
- function _updateSelectedRange(topLeft, bottomRight, select) {
- var iMin = topLeft.row
- var iMax = bottomRight.row + 1 // [] => [)
- if (iMin < root._currentRange[1] && root._currentRange[0] < iMax) {
- iMin = Math.max(iMin, root._currentRange[0])
- iMax = Math.min(iMax, root._currentRange[1])
- for (var j = iMin; j < iMax; j++) {
- var item = root._getItem(j)
- console.assert(item)
- item.selected = select
- }
- }
- }
- }
-
- onModelChanged: _onModelCountChanged()
-
- Connections {
- target: mainInterface
- onIntfScaleFactorChanged: flickable.layout(true)
- }
+ // Children
//Gridview visible above the expanded item
Flickable {
@@ -466,8 +589,9 @@ FocusScope {
Loader {
id: footerItemLoader
focus: (status === Loader.Ready) ? item.focus : false
- y: root.topMargin + root.headerHeight + (root._effectiveCellHeight * (Math.ceil(model.count / getNbItemsPerRow()))) +
- _expandItemVerticalSpace
+
+ y: root.topMargin + root.headerHeight + (root._effectiveCellHeight * (Math.ceil(model.count / root._nbItemPerRow))) +
+ root._expandItemVerticalSpace
}
Connections {
@@ -500,10 +624,8 @@ FocusScope {
}
}
-
anchors.fill: parent
- onWidthChanged: { layout(true) }
- onHeightChanged: { layout(false) }
+
onContentYChanged: { scrollLayoutTimer.start() }
Timer {
@@ -521,9 +643,9 @@ FocusScope {
if (root.expandIndex !== -1) {
var rowCol = root.getItemRowCol(root.expandIndex)
var rowId = rowCol[1] + 1
- ret = rowId * root.getNbItemsPerRow()
+ ret = rowId * root._nbItemPerRow
} else {
- ret = _count
+ ret = root._count
}
return ret
}
@@ -561,16 +683,16 @@ FocusScope {
root._setItem(i, undefined)
}
- for (i = _currentRange[0]; i < _currentRange[1]; ++i) {
+ for (i = root._currentRange[0]; i < root._currentRange[1]; ++i) {
var item = root._getItem(i)
if (typeof item !== "undefined") {
item.visible = false
- _unusedItemList.push(item)
+ root._unusedItemList.push(item)
// root._setItem(i, undefined) // not needed the list will be reset following this loop
}
}
- _idChildrenList = newList
+ root._idChildrenList = newList
root._currentRange = [first, last]
}
@@ -610,13 +732,13 @@ FocusScope {
}
// Place the delegates after the expandItem
- _setupIndexes(forceRelayout, [topGridEndId, lastId], _expandItemVerticalSpace)
+ _setupIndexes(forceRelayout, [topGridEndId, lastId], root._expandItemVerticalSpace)
// Calculate and set the contentHeight
- var newContentHeight = root.getItemPos(_count - 1)[1] + root._effectiveCellHeight + _expandItemVerticalSpace
+ var newContentHeight = root.getItemPos(root._count - 1)[1] + root._effectiveCellHeight + root._expandItemVerticalSpace
contentHeight = newContentHeight + root.bottomMargin // topMargin is included from root.getItemPos
contentHeight += footerItemLoader.item ? footerItemLoader.item.height : 0
- contentWidth = root._effectiveCellWidth * root.getNbItemsPerRow() - root.horizontalSpacing
+ contentWidth = root._effectiveCellWidth * root._nbItemPerRow - root.horizontalSpacing
}
Connections {
@@ -630,17 +752,17 @@ FocusScope {
}
function expand() {
- expandIndex = _newExpandIndex
- if (expandIndex === -1)
+ root.expandIndex = root._newExpandIndex
+ if (root.expandIndex === -1)
return
- expandItem.model = model.getDataAt(expandIndex)
+ expandItem.model = model.getDataAt(root.expandIndex)
/* We must also start the expand animation here since the expandItem implicitHeight is not
changed if it had the same height at previous opening. */
expandAnimation()
}
function expandAnimation() {
- if (expandIndex === -1)
+ if (root.expandIndex === -1)
return
var expandItemHeight = expandItem.implicitHeight + root.verticalSpacing
@@ -655,7 +777,7 @@ FocusScope {
animateExpandItem.start()
// Sliding animation
- var currentItemYPos = root.getItemPos(expandIndex)[1]
+ var currentItemYPos = root.getItemPos(root.expandIndex)[1]
currentItemYPos += root._effectiveCellHeight / 2
animateFlickableContentY(currentItemYPos)
}
@@ -672,8 +794,8 @@ FocusScope {
duration: VLCStyle.duration_slow
to: 0
onStopped: {
- expandIndex = -1
- if (_newExpandIndex !== -1)
+ root.expandIndex = -1
+ if (root._newExpandIndex !== -1)
flickable.expand()
}
}
@@ -687,91 +809,4 @@ FocusScope {
from: 0
}
}
-
- PropertyAnimation {
- id: animateContentY;
- target: flickable;
- properties: "contentY"
- }
-
- function animateFlickableContentY( newContentY ) {
- animateContentY.stop()
- animateContentY.duration = VLCStyle.duration_slow
- animateContentY.to = newContentY
- animateContentY.start()
- }
-
- onCurrentIndexChanged: {
- if (expandIndex !== -1)
- retract()
- positionViewAtIndex(root.currentIndex, ItemView.Contain)
- }
-
- Keys.onPressed: {
- var colCount = root.getNbItemsPerRow()
-
- var newIndex = -1
- if (KeyHelper.matchRight(event)) {
- if ((currentIndex + 1) % colCount !== 0) {//are we not at the end of line
- newIndex = Math.min(_count - 1, currentIndex + 1)
- }
- } else if (KeyHelper.matchLeft(event)) {
- if (currentIndex % colCount !== 0) {//are we not at the begining of line
- newIndex = Math.max(0, currentIndex - 1)
- }
- } else if (KeyHelper.matchDown(event)) {
- if (Math.floor(currentIndex / colCount) !== Math.floor(_count / colCount)) { //we are not on the last line
- newIndex = Math.min(_count - 1, currentIndex + colCount)
- }
- } else if (KeyHelper.matchPageDown(event)) {
- newIndex = Math.min(_count - 1, currentIndex + colCount * 5)
- } else if (KeyHelper.matchUp(event)) {
- if (Math.floor(currentIndex / colCount) !== 0) { //we are not on the first line
- newIndex = Math.max(0, currentIndex - colCount)
- }
- } else if (KeyHelper.matchPageUp(event)) {
- newIndex = Math.max(0, currentIndex - colCount * 5)
- } else if (KeyHelper.matchOk(event) || event.matches(StandardKey.SelectAll) ) {
- //these events are matched on release
- event.accepted = true
- }
-
- if (event.matches(StandardKey.SelectAll) || KeyHelper.matchOk(event)) {
- _releaseActionButtonPressed = true
- } else {
- _releaseActionButtonPressed = false
- }
-
- if (newIndex !== -1 && newIndex !== currentIndex) {
- event.accepted = true;
-
- var oldIndex = currentIndex;
- currentIndex = newIndex;
- root.selectionUpdated(event.modifiers, oldIndex, newIndex);
-
- // NOTE: We make sure we have the proper visual focus on components.
- if (oldIndex < currentIndex)
- setCurrentItemFocus(Qt.TabFocusReason);
- else
- setCurrentItemFocus(Qt.BacktabFocusReason);
- }
-
- if (!event.accepted) {
- root.Navigation.defaultKeyAction(event)
- }
- }
-
- Keys.onReleased: {
- if (!_releaseActionButtonPressed)
- return
-
- if (event.matches(StandardKey.SelectAll)) {
- event.accepted = true
- root.selectAll()
- } else if ( KeyHelper.matchOk(event) ) {
- event.accepted = true
- root.actionAtIndex(currentIndex)
- }
- _releaseActionButtonPressed = false
- }
}
=====================================
modules/gui/qt/widgets/qml/KeyNavigableListView.qml
=====================================
@@ -35,6 +35,9 @@ FocusScope {
property var fadeColor: undefined
+ // NOTE: We want buttons to be centered verticaly but configurable.
+ property int buttonMargin: height / 2 - button.height / 2
+
property int scrollBarWidth: scroll_id.visible ? scroll_id.width : 0
property bool keyNavigationWraps : false
@@ -90,6 +93,9 @@ FocusScope {
property alias listScrollBar: scroll_id
+ property alias buttonLeft: buttonLeft
+ property alias buttonRight: buttonRight
+
// Signals
signal selectionUpdated(int keyModifiers, int oldIndex, int newIndex)
@@ -208,7 +214,7 @@ FocusScope {
section.delegate: sectionHeading
boundsBehavior: Flickable.StopAtBounds
- boundsMovement :Flickable.StopAtBounds
+ boundsMovement: Flickable.StopAtBounds
// NOTE: We always want a valid 'currentIndex' by default.
onCountChanged: if (count && currentIndex === -1) currentIndex = 0
@@ -382,23 +388,34 @@ FocusScope {
}
}
+ // FIXME: We propbably need to upgrade these RoundButton(s) eventually. And we probably need
+ // to have some kind of animation when switching pages.
+
RoundButton {
- id: leftBtn
+ id: buttonLeft
- anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
- text:"<"
+ anchors.top: parent.top
+
+ anchors.topMargin: buttonMargin
+
+ text: '<'
+
+ visible: (view.orientation === ListView.Horizontal && !(view.atXBeginning))
+
onClicked: listview_id.prevPage()
- visible: view.orientation === ListView.Horizontal && !view.atXBeginning
}
RoundButton {
- id: rightBtn
+ id: buttonRight
- anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
- text:">"
+ anchors.top: buttonLeft.top
+
+ text: '>'
+
+ visible: (view.orientation === ListView.Horizontal && !(view.atXEnd))
+
onClicked: listview_id.nextPage()
- visible: view.orientation === ListView.Horizontal && !view.atXEnd
}
}
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/0e09e40cfef870ecd614962019e0e07b3a0a881e...b18e2bf7c9bd3b99cf7dc756fa213d4c231f05e1
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/0e09e40cfef870ecd614962019e0e07b3a0a881e...b18e2bf7c9bd3b99cf7dc756fa213d4c231f05e1
You're receiving this email because of your account on code.videolan.org.
More information about the vlc-commits
mailing list