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.
247 lines
8.4 KiB
247 lines
8.4 KiB
/*****************************************************************************
|
|
* Copyright (C) 2019 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 2.11
|
|
import QtQuick.Controls 2.4
|
|
|
|
import "qrc:///style/"
|
|
import "qrc:///util/KeyHelper.js" as KeyHelper
|
|
|
|
NavigableFocusScope {
|
|
id: listview_id
|
|
|
|
property int modelCount: view.count
|
|
|
|
signal selectionUpdated( int keyModifiers, int oldIndex,int newIndex )
|
|
signal selectAll()
|
|
signal actionAtIndex( int index )
|
|
|
|
//forward view properties
|
|
property alias spacing: view.spacing
|
|
property alias interactive: view.interactive
|
|
property alias model: view.model
|
|
property alias delegate: view.delegate
|
|
|
|
property alias originX: view.originX
|
|
property alias originY: view.originY
|
|
|
|
property alias contentX: view.contentX
|
|
property alias contentY: view.contentY
|
|
property alias contentHeight: view.contentHeight
|
|
property alias contentWidth: view.contentWidth
|
|
|
|
property alias footer: view.footer
|
|
property alias footerItem: view.footerItem
|
|
property alias header: view.header
|
|
property alias headerItem: view.headerItem
|
|
property alias headerPositioning: view.headerPositioning
|
|
|
|
property alias currentIndex: view.currentIndex
|
|
property alias currentItem: view.currentItem
|
|
|
|
property alias highlightMoveVelocity: view.highlightMoveVelocity
|
|
|
|
property alias section: view.section
|
|
property alias orientation: view.orientation
|
|
|
|
property int highlightMargin: VLCStyle.margin_large
|
|
|
|
Accessible.role: Accessible.List
|
|
|
|
function nextPage() {
|
|
view.contentX += (Math.min(view.width, (view.contentWidth - view.width - view.contentX ) ))
|
|
}
|
|
function prevPage() {
|
|
view.contentX -= Math.min(view.width,view.contentX )
|
|
}
|
|
|
|
function positionViewAtIndex(index, mode) {
|
|
view.positionViewAtIndex(index, mode)
|
|
}
|
|
|
|
Component {
|
|
id: sectionHeading
|
|
|
|
Column {
|
|
width: parent.width
|
|
|
|
Text {
|
|
text: section
|
|
font.pixelSize: VLCStyle.fontSize_xlarge
|
|
color: VLCStyle.colors.accent
|
|
}
|
|
|
|
Rectangle {
|
|
width: parent.width
|
|
height: 1
|
|
color: VLCStyle.colors.textDisabled
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
Connections {
|
|
target: view.headerItem
|
|
onFocusChanged: {
|
|
if (!headerItem.focus) {
|
|
view.currentItem.focus = true
|
|
}
|
|
}
|
|
}
|
|
|
|
ListView {
|
|
id: view
|
|
anchors.fill: parent
|
|
//key navigation is reimplemented for item selection
|
|
keyNavigationEnabled: false
|
|
|
|
preferredHighlightBegin : (view.orientation === ListView.Vertical)
|
|
? highlightMargin + (headerItem ? headerItem.height : 0)
|
|
: highlightMargin
|
|
preferredHighlightEnd : (view.orientation === ListView.Vertical)
|
|
? height - highlightMargin
|
|
: width - highlightMargin
|
|
highlightRangeMode: ListView.ApplyRange
|
|
|
|
focus: true
|
|
|
|
clip: true
|
|
ScrollBar.vertical: ScrollBar { id: scroll_id }
|
|
ScrollBar.horizontal: ScrollBar { }
|
|
|
|
highlightMoveDuration: 300 //ms
|
|
highlightMoveVelocity: 1000 //px/s
|
|
|
|
section.property: ""
|
|
section.criteria: ViewSection.FullString
|
|
section.delegate: sectionHeading
|
|
|
|
Connections {
|
|
target: view.currentItem
|
|
ignoreUnknownSignals: true
|
|
onActionRight: listview_id.navigationRight(currentIndex)
|
|
onActionLeft: listview_id.navigationLeft(currentIndex)
|
|
onActionDown: {
|
|
if ( currentIndex !== modelCount - 1 ) {
|
|
var newIndex = currentIndex + 1
|
|
var oldIndex = currentIndex
|
|
currentIndex = newIndex
|
|
selectionUpdated(0, oldIndex, newIndex)
|
|
} else {
|
|
root.navigationDown(currentIndex)
|
|
}
|
|
}
|
|
onActionUp: {
|
|
if ( currentIndex !== 0 ) {
|
|
var newIndex = currentIndex - 1
|
|
var oldIndex = currentIndex
|
|
currentIndex = newIndex
|
|
selectionUpdated(0, oldIndex, newIndex)
|
|
} else {
|
|
root.navigationUp(currentIndex)
|
|
}
|
|
}
|
|
}
|
|
|
|
Keys.onPressed: {
|
|
var newIndex = -1
|
|
|
|
if (orientation === ListView.Vertical)
|
|
{
|
|
if ( KeyHelper.matchDown(event) ) {
|
|
if (currentIndex !== modelCount - 1 )
|
|
newIndex = currentIndex + 1
|
|
} else if ( KeyHelper.matchPageDown(event) ) {
|
|
newIndex = Math.min(modelCount - 1, currentIndex + 10)
|
|
} else if ( KeyHelper.matchUp(event) ) {
|
|
if ( currentIndex !== 0 )
|
|
newIndex = currentIndex - 1
|
|
} else if ( KeyHelper.matchPageUp(event) ) {
|
|
newIndex = Math.max(0, currentIndex - 10)
|
|
}
|
|
}else{
|
|
if ( KeyHelper.matchRight(event) ) {
|
|
if (currentIndex !== modelCount - 1 )
|
|
newIndex = currentIndex + 1
|
|
}
|
|
else if ( KeyHelper.matchPageDown(event) ) {
|
|
newIndex = Math.min(modelCount - 1, currentIndex + 10)
|
|
} else if ( KeyHelper.matchLeft(event) ) {
|
|
if ( currentIndex !== 0 )
|
|
newIndex = currentIndex - 1
|
|
} else if ( KeyHelper.matchPageUp(event) ) {
|
|
newIndex = Math.max(0, currentIndex - 10)
|
|
}
|
|
}
|
|
|
|
if (KeyHelper.matchOk(event) || event.matches(StandardKey.SelectAll) ) {
|
|
//these events are matched on release
|
|
event.accepted = true
|
|
}
|
|
|
|
if (newIndex >= 0 && newIndex < modelCount) {
|
|
var oldIndex = currentIndex
|
|
currentIndex = newIndex
|
|
event.accepted = true
|
|
selectionUpdated(event.modifiers, oldIndex, newIndex)
|
|
}
|
|
|
|
if (!event.accepted)
|
|
defaultKeyAction(event, currentIndex)
|
|
}
|
|
|
|
Keys.onReleased: {
|
|
if (event.matches(StandardKey.SelectAll)) {
|
|
event.accepted = true
|
|
selectAll()
|
|
} else if ( KeyHelper.matchOk(event) ) { //enter/return/space
|
|
event.accepted = true
|
|
actionAtIndex(currentIndex)
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
anchors { bottom: parent.bottom; left: parent.left; right: parent.right }
|
|
z: 1
|
|
visible: orientation === ListView.Vertical && !view.atYEnd
|
|
height: highlightMargin * 2
|
|
gradient: Gradient{
|
|
GradientStop { position: 0.0; color: "transparent" }
|
|
GradientStop { position: 1.0; color: VLCStyle.colors.bg }
|
|
}
|
|
}
|
|
}
|
|
|
|
RoundButton{
|
|
id: leftBtn
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
anchors.left: parent.left
|
|
text:"<"
|
|
onClicked: listview_id.prevPage()
|
|
visible: view.orientation === ListView.Horizontal && view.contentX > 0
|
|
}
|
|
|
|
|
|
RoundButton{
|
|
id: rightBtn
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
anchors.right: parent.right
|
|
text:">"
|
|
onClicked: listview_id.nextPage()
|
|
visible: view.orientation === ListView.Horizontal && (view.contentWidth - view.width - view.contentX) > 0
|
|
}
|
|
}
|
|
|