You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
310 lines
9.7 KiB
310 lines
9.7 KiB
/*****************************************************************************
|
|
* Copyright (C) 2020 VLC authors and VideoLAN
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* ( at your option ) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
|
*****************************************************************************/
|
|
|
|
import QtQuick
|
|
import QtQuick.Layouts
|
|
|
|
import org.videolan.vlc 0.1
|
|
|
|
import "qrc:///style/"
|
|
import "qrc:///widgets/" as Widgets
|
|
|
|
|
|
FocusScope {
|
|
id: playerControlLayout
|
|
|
|
// Properties
|
|
|
|
property real spacing: VLCStyle.margin_normal // spacing between controls
|
|
|
|
property real layoutSpacing: VLCStyle.margin_xxlarge // spacing between layouts (left, center, and right)
|
|
|
|
property int identifier: -1
|
|
|
|
readonly property PlayerControlbarModel model: {
|
|
if (!!MainCtx.controlbarProfileModel.currentModel)
|
|
return MainCtx.controlbarProfileModel.currentModel.getModel(identifier)
|
|
else
|
|
return null
|
|
}
|
|
|
|
readonly property ColorContext colorContext: ColorContext {
|
|
id: theme
|
|
colorSet: ColorContext.Window
|
|
}
|
|
|
|
// Signals
|
|
|
|
signal requestLockUnlockAutoHide(bool lock)
|
|
|
|
signal menuOpened(var menu)
|
|
|
|
// Settings
|
|
|
|
implicitWidth: loaderLeftRight.active ? loaderLeftRight.implicitWidth
|
|
: (loaderLeft.implicitWidth + loaderCenter.implicitWidth + loaderRight.implicitWidth)
|
|
|
|
implicitHeight: Math.max(loaderLeft.implicitHeight, loaderCenter.implicitHeight, loaderRight.implicitHeight)
|
|
|
|
// Events
|
|
|
|
Component.onCompleted: console.assert(identifier >= 0)
|
|
|
|
// Children
|
|
|
|
Loader {
|
|
id: loaderLeftRight
|
|
|
|
anchors.fill: parent
|
|
|
|
active: !loaderCenter.active &&
|
|
playerControlLayout.model &&
|
|
((playerControlLayout.model.left && (playerControlLayout.model.left.count > 0)) ||
|
|
(playerControlLayout.model.right && (playerControlLayout.model.right.count > 0)))
|
|
|
|
focus: active
|
|
|
|
sourceComponent: RowLayout {
|
|
spacing: playerControlLayout.spacing
|
|
|
|
focus: true
|
|
|
|
// TODO: Qt >= 5.13 Use QConcatenateTablesProxyModel
|
|
// instead of multiple repeaters
|
|
|
|
ControlRepeater {
|
|
id: leftRepeater
|
|
model: ControlListFilter {
|
|
sourceModel: playerControlLayout.model.left
|
|
|
|
player: Player
|
|
ctx: MainCtx
|
|
}
|
|
|
|
Navigation.parentItem: playerControlLayout
|
|
Navigation.rightAction: function() {
|
|
const item = rightRepeater.itemAt(0)
|
|
if (item)
|
|
item.forceActiveFocus(Qt.TabFocusReason)
|
|
else
|
|
return false
|
|
}
|
|
|
|
availableWidth: loaderLeftRight.width
|
|
availableHeight: loaderLeftRight.height
|
|
|
|
Component.onCompleted: {
|
|
requestLockUnlockAutoHide.connect(playerControlLayout.requestLockUnlockAutoHide)
|
|
menuOpened.connect(playerControlLayout.menuOpened)
|
|
}
|
|
}
|
|
|
|
Item {
|
|
function containsVisibleItem(repeater) {
|
|
for (let i = 0; i < repeater.count; ++i) {
|
|
const item = repeater.itemAt(i)
|
|
|
|
if (item && item.visible)
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
Layout.minimumWidth: (containsVisibleItem(leftRepeater) && containsVisibleItem(rightRepeater)) ? playerControlLayout.layoutSpacing
|
|
: 0
|
|
|
|
Layout.fillWidth: true
|
|
visible: true
|
|
}
|
|
|
|
ControlRepeater {
|
|
id: rightRepeater
|
|
model: ControlListFilter {
|
|
sourceModel: playerControlLayout.model.right
|
|
|
|
player: Player
|
|
ctx: MainCtx
|
|
}
|
|
|
|
Navigation.parentItem: playerControlLayout
|
|
Navigation.leftAction: function() {
|
|
const item = leftRepeater.itemAt(leftRepeater.count - 1)
|
|
if (item)
|
|
item.forceActiveFocus(Qt.BacktabFocusReason)
|
|
else
|
|
return false
|
|
}
|
|
|
|
availableWidth: loaderLeftRight.width
|
|
availableHeight: loaderLeftRight.height
|
|
|
|
Component.onCompleted: {
|
|
requestLockUnlockAutoHide.connect(playerControlLayout.requestLockUnlockAutoHide)
|
|
menuOpened.connect(playerControlLayout.menuOpened)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
Loader {
|
|
id: loaderLeft
|
|
|
|
anchors {
|
|
right: loaderCenter.left
|
|
left: parent.left
|
|
top: parent.top
|
|
bottom: parent.bottom
|
|
|
|
// Spacing for the filler item acts as padding
|
|
rightMargin: layoutSpacing - spacing
|
|
}
|
|
|
|
active: !!playerControlLayout.model && !!playerControlLayout.model.left && (playerControlLayout.model.left.count > 0) &&
|
|
!loaderLeftRight.active
|
|
|
|
focus: active
|
|
|
|
sourceComponent: ControlLayout {
|
|
model: ControlListFilter {
|
|
sourceModel: playerControlLayout.model.left
|
|
|
|
player: Player
|
|
ctx: MainCtx
|
|
}
|
|
|
|
alignment: (Qt.AlignVCenter | Qt.AlignLeft)
|
|
|
|
spacing: playerControlLayout.spacing
|
|
|
|
focus: true
|
|
|
|
altFocusAction: () => Navigation.defaultNavigationRight()
|
|
|
|
Navigation.parentItem: playerControlLayout
|
|
Navigation.rightItem: loaderCenter.item
|
|
|
|
Component.onCompleted: {
|
|
requestLockUnlockAutoHide.connect(playerControlLayout.requestLockUnlockAutoHide)
|
|
menuOpened.connect(playerControlLayout.menuOpened)
|
|
}
|
|
}
|
|
}
|
|
|
|
Loader {
|
|
id: loaderCenter
|
|
|
|
anchors {
|
|
horizontalCenter: parent.horizontalCenter
|
|
top: parent.top
|
|
bottom: parent.bottom
|
|
}
|
|
|
|
// TODO: "ControlListFilter"'s count......
|
|
active: !!playerControlLayout.model && !!playerControlLayout.model.center && (playerControlLayout.model.center.count > 0)
|
|
|
|
Binding on width {
|
|
delayed: true
|
|
when: loaderCenter._componentCompleted
|
|
value: {
|
|
const item = loaderCenter.item
|
|
|
|
const minimumWidth = (item && item.Layout.minimumWidth > 0) ? item.Layout.minimumWidth : implicitWidth
|
|
const maximumWidth = (item && item.Layout.maximumWidth > 0) ? item.Layout.maximumWidth : implicitWidth
|
|
|
|
if ((loaderLeft.active && (loaderLeft.width > 0)) || (loaderRight.active && (loaderRight.width > 0))) {
|
|
return minimumWidth
|
|
} else {
|
|
return Math.min(loaderCenter.parent.width, maximumWidth)
|
|
}
|
|
}
|
|
}
|
|
|
|
property bool _componentCompleted: false
|
|
|
|
Component.onCompleted: {
|
|
_componentCompleted = true
|
|
}
|
|
|
|
sourceComponent: ControlLayout {
|
|
model: ControlListFilter {
|
|
sourceModel: playerControlLayout.model.center
|
|
|
|
player: Player
|
|
ctx: MainCtx
|
|
}
|
|
|
|
focus: true
|
|
|
|
spacing: playerControlLayout.spacing
|
|
|
|
altFocusAction: () => Navigation.defaultNavigationUp()
|
|
|
|
Navigation.parentItem: playerControlLayout
|
|
Navigation.leftItem: loaderLeft.item
|
|
Navigation.rightItem: loaderRight.item
|
|
|
|
Component.onCompleted: {
|
|
requestLockUnlockAutoHide.connect(playerControlLayout.requestLockUnlockAutoHide)
|
|
menuOpened.connect(playerControlLayout.menuOpened)
|
|
}
|
|
}
|
|
}
|
|
|
|
Loader {
|
|
id: loaderRight
|
|
|
|
anchors {
|
|
left: loaderCenter.right
|
|
right: parent.right
|
|
top: parent.top
|
|
bottom: parent.bottom
|
|
|
|
// Spacing for the filler item acts as padding
|
|
leftMargin: layoutSpacing - spacing
|
|
}
|
|
|
|
active: !!playerControlLayout.model && !!playerControlLayout.model.right && (playerControlLayout.model.right.count > 0) &&
|
|
!loaderLeftRight.active
|
|
|
|
sourceComponent: ControlLayout {
|
|
model: ControlListFilter {
|
|
sourceModel: playerControlLayout.model.right
|
|
|
|
player: Player
|
|
ctx: MainCtx
|
|
}
|
|
|
|
alignment: (Qt.AlignVCenter | Qt.AlignRight)
|
|
|
|
spacing: playerControlLayout.spacing
|
|
|
|
focus: true
|
|
|
|
altFocusAction: () => Navigation.defaultNavigationLeft()
|
|
|
|
Navigation.parentItem: playerControlLayout
|
|
Navigation.leftItem: loaderCenter.item
|
|
|
|
onRequestLockUnlockAutoHide: (lock) => playerControlLayout.requestLockUnlockAutoHide(lock)
|
|
|
|
onMenuOpened: (menu) => playerControlLayout.menuOpened(menu)
|
|
}
|
|
}
|
|
}
|
|
|