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.
298 lines
9.1 KiB
298 lines
9.1 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
|
|
import QtQuick.Controls
|
|
import QtQuick.Templates as T
|
|
import QtQml.Models
|
|
import QtQml
|
|
|
|
import org.videolan.vlc 0.1
|
|
|
|
import "qrc:///widgets/" as Widgets
|
|
import "qrc:///main/" as MainInterface
|
|
import "qrc:///util/" as Util
|
|
import "qrc:///style/"
|
|
|
|
FocusScope {
|
|
id: root
|
|
|
|
// Properties
|
|
|
|
property int leftPadding: 0
|
|
property int rightPadding: 0
|
|
|
|
property int maximumRows: {
|
|
if (model.searchPattern !== "")
|
|
return -1
|
|
else if (MainCtx.gridView)
|
|
return 2
|
|
else
|
|
return 5
|
|
}
|
|
|
|
property var sortModel: [
|
|
{ text: qsTr("Alphabetic"), criteria: "name"},
|
|
{ text: qsTr("Url"), criteria: "mrl" }
|
|
]
|
|
|
|
readonly property bool hasGridListMode: true
|
|
readonly property bool isSearchable: true
|
|
|
|
//behave like a Page
|
|
property var pagePrefix: []
|
|
|
|
// Aliases
|
|
|
|
property alias model: foldersSection.model
|
|
|
|
// Signals
|
|
|
|
signal seeAllDevices(var title, var sd_source, int reason)
|
|
signal seeAllFolders(var title, int reason)
|
|
|
|
signal browse(var tree, int reason)
|
|
|
|
focus: true
|
|
|
|
Component.onCompleted: resetFocus()
|
|
onActiveFocusChanged: resetFocus()
|
|
|
|
function setCurrentItemFocus(reason) {
|
|
if (foldersSection.visible)
|
|
foldersSection.setCurrentItemFocus(reason);
|
|
else if (deviceSection.visible)
|
|
deviceSection.setCurrentItemFocus(reason);
|
|
else if (lanSection.visible)
|
|
lanSection.setCurrentItemFocus(reason);
|
|
}
|
|
|
|
function _centerFlickableOnItem(item) {
|
|
if (item.activeFocus === false)
|
|
return
|
|
|
|
let minY
|
|
let maxY
|
|
|
|
const index = item.currentIndex
|
|
|
|
// NOTE: We want to include the header when we're on the first row.
|
|
if ((MainCtx.gridView && index < item.nbItemPerRow) || index < 1) {
|
|
minY = item.y
|
|
|
|
maxY = minY + item.getItemY(index) + item.rowHeight
|
|
} else {
|
|
minY = item.y + item.getItemY(index)
|
|
|
|
maxY = minY + item.rowHeight
|
|
}
|
|
|
|
// TODO: We could implement a scrolling animation like in ExpandGridView.
|
|
if (maxY > flickable.contentItem.contentY + flickable.height) {
|
|
flickable.contentItem.contentY = maxY - flickable.height
|
|
} else if (minY < flickable.contentItem.contentY) {
|
|
flickable.contentItem.contentY = minY
|
|
}
|
|
}
|
|
|
|
readonly property ColorContext colorContext: ColorContext {
|
|
id: theme
|
|
colorSet: ColorContext.View
|
|
}
|
|
|
|
//FIXME use the right xxxLabel class
|
|
T.Label {
|
|
anchors.centerIn: parent
|
|
|
|
visible: (foldersSection.model.count === 0 && deviceSection.model.count === 0
|
|
&&
|
|
lanSection.model.count === 0)
|
|
|
|
font.pixelSize: VLCStyle.fontHeight_xxlarge
|
|
color: root.activeFocus ? theme.accent : theme.fg.primary
|
|
text: qsTr("No network shares found")
|
|
}
|
|
|
|
ScrollView {
|
|
id: flickable
|
|
|
|
anchors.fill: parent
|
|
|
|
anchors.leftMargin: root.leftPadding
|
|
anchors.rightMargin: root.rightPadding
|
|
|
|
focus: true
|
|
|
|
Column {
|
|
width: foldersSection.width
|
|
height: implicitHeight
|
|
|
|
spacing: (MainCtx.gridView ? VLCStyle.gridView_spacing : VLCStyle.tableView_spacing) -
|
|
VLCStyle.layoutTitle_top_padding
|
|
|
|
BrowseDeviceView {
|
|
id: foldersSection
|
|
|
|
width: root.width
|
|
height: contentHeight
|
|
|
|
visible: (model.count !== 0)
|
|
|
|
model: StandardPathModel {
|
|
//we only have a handfull of standard path (5 or 6)
|
|
//so we don't limit them
|
|
|
|
sortCriteria: MainCtx.sort.criteria
|
|
sortOrder: MainCtx.sort.order
|
|
searchPattern: MainCtx.search.pattern
|
|
}
|
|
|
|
title: qsTr("My Folders")
|
|
|
|
Navigation.parentItem: root
|
|
|
|
Navigation.downAction: function() {
|
|
if (deviceSection.visible)
|
|
deviceSection.setCurrentItemFocus(Qt.TabFocusReason)
|
|
else if (lanSection.visible)
|
|
lanSection.setCurrentItemFocus(Qt.TabFocusReason)
|
|
else
|
|
root.Navigation.defaultNavigationDown()
|
|
}
|
|
|
|
onBrowse: (tree, reason) => root.browse(tree, reason)
|
|
|
|
onSeeAll: (reason) => root.seeAllFolders(title, reason)
|
|
|
|
onActiveFocusChanged: _centerFlickableOnItem(foldersSection)
|
|
onCurrentIndexChanged: _centerFlickableOnItem(foldersSection)
|
|
}
|
|
|
|
BrowseDeviceView {
|
|
id: deviceSection
|
|
|
|
width: root.width
|
|
height: contentHeight
|
|
|
|
maximumRows: root.maximumRows
|
|
|
|
visible: (model.count !== 0)
|
|
|
|
model: NetworkDeviceModel {
|
|
ctx: MainCtx
|
|
|
|
limit: deviceSection.maximumCount
|
|
|
|
sortOrder: MainCtx.sort.order
|
|
sortCriteria: MainCtx.sort.criteria
|
|
searchPattern: MainCtx.search.pattern
|
|
|
|
sd_source: NetworkDeviceModel.CAT_DEVICES
|
|
source_name: "*"
|
|
}
|
|
|
|
|
|
title: qsTr("My Machine")
|
|
|
|
Navigation.parentItem: root
|
|
|
|
Navigation.upAction: function() {
|
|
if (foldersSection.visible)
|
|
foldersSection.setCurrentItemFocus(Qt.TabFocusReason)
|
|
else
|
|
root.Navigation.defaultNavigationUp()
|
|
}
|
|
|
|
Navigation.downAction: function() {
|
|
if (lanSection.visible)
|
|
lanSection.setCurrentItemFocus(Qt.TabFocusReason)
|
|
else
|
|
root.Navigation.defaultNavigationDown()
|
|
}
|
|
|
|
onBrowse: (tree, reason) => root.browse(tree, reason)
|
|
|
|
onSeeAll: (reason) => root.seeAllDevices(title, model.sd_source, reason)
|
|
|
|
onActiveFocusChanged: _centerFlickableOnItem(deviceSection)
|
|
onCurrentIndexChanged: _centerFlickableOnItem(deviceSection)
|
|
}
|
|
|
|
BrowseDeviceView {
|
|
id: lanSection
|
|
|
|
width: root.width
|
|
height: contentHeight
|
|
|
|
maximumRows: root.maximumRows
|
|
|
|
visible: (model.count !== 0)
|
|
|
|
model: NetworkDeviceModel {
|
|
ctx: MainCtx
|
|
|
|
sd_source: NetworkDeviceModel.CAT_LAN
|
|
source_name: "*"
|
|
|
|
limit: lanSection.maximumCount
|
|
|
|
sortOrder: MainCtx.sort.order
|
|
sortCriteria: MainCtx.sort.criteria
|
|
searchPattern: MainCtx.search.pattern
|
|
}
|
|
|
|
title: qsTr("My LAN")
|
|
|
|
Navigation.parentItem: root
|
|
|
|
Navigation.upAction: function() {
|
|
if (deviceSection.visible)
|
|
deviceSection.setCurrentItemFocus(Qt.TabFocusReason)
|
|
else if (foldersSection.visible)
|
|
foldersSection.setCurrentItemFocus(Qt.TabFocusReason)
|
|
else
|
|
root.Navigation.defaultNavigationUp()
|
|
}
|
|
|
|
onBrowse: (tree, reason) => root.browse(tree, reason)
|
|
|
|
onSeeAll: (reason) => root.seeAllDevices(title, model.sd_source, reason)
|
|
|
|
onActiveFocusChanged: _centerFlickableOnItem(lanSection)
|
|
onCurrentIndexChanged: _centerFlickableOnItem(lanSection)
|
|
}
|
|
}
|
|
}
|
|
|
|
function resetFocus() {
|
|
const widgetlist = [foldersSection, deviceSection, lanSection]
|
|
for (let i in widgetlist) {
|
|
if (widgetlist[i].activeFocus && widgetlist[i].visible)
|
|
return
|
|
}
|
|
|
|
let found = false;
|
|
for (let i in widgetlist) {
|
|
if (widgetlist[i].visible && !found) {
|
|
widgetlist[i].focus = true
|
|
found = true
|
|
} else {
|
|
widgetlist[i].focus = false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|