mirror of
https://github.com/overte-org/overte.git
synced 2025-07-24 00:24:00 +02:00
commit
49ded9c4df
16 changed files with 678 additions and 318 deletions
BIN
interface/resources/fonts/FiraSans-Regular.ttf
Normal file
BIN
interface/resources/fonts/FiraSans-Regular.ttf
Normal file
Binary file not shown.
Binary file not shown.
|
@ -21,7 +21,6 @@ import "../hifi/models"
|
||||||
TableView {
|
TableView {
|
||||||
id: tableView
|
id: tableView
|
||||||
|
|
||||||
// property var tableModel: ListModel { }
|
|
||||||
property int colorScheme: hifi.colorSchemes.light
|
property int colorScheme: hifi.colorSchemes.light
|
||||||
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
||||||
|
|
||||||
|
@ -46,7 +45,7 @@ TableView {
|
||||||
|
|
||||||
RalewayRegular {
|
RalewayRegular {
|
||||||
id: textHeader
|
id: textHeader
|
||||||
size: hifi.fontSizes.tableText
|
size: hifi.fontSizes.tableHeading
|
||||||
color: hifi.colors.lightGrayText
|
color: hifi.colors.lightGrayText
|
||||||
text: styleData.value
|
text: styleData.value
|
||||||
anchors {
|
anchors {
|
||||||
|
@ -87,7 +86,7 @@ TableView {
|
||||||
bottomMargin: 3 // ""
|
bottomMargin: 3 // ""
|
||||||
}
|
}
|
||||||
radius: 3
|
radius: 3
|
||||||
color: hifi.colors.tableScrollHandle
|
color: hifi.colors.tableScrollHandleDark
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +106,7 @@ TableView {
|
||||||
margins: 1 // Shrink
|
margins: 1 // Shrink
|
||||||
}
|
}
|
||||||
radius: 4
|
radius: 4
|
||||||
color: hifi.colors.tableScrollBackground
|
color: hifi.colors.tableScrollBackgroundDark
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ FocusScope {
|
||||||
HiFiGlyphs {
|
HiFiGlyphs {
|
||||||
anchors {
|
anchors {
|
||||||
top: parent.top
|
top: parent.top
|
||||||
topMargin: -8
|
topMargin: -11
|
||||||
horizontalCenter: parent.horizontalCenter
|
horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
size: hifi.dimensions.spinnerSize
|
size: hifi.dimensions.spinnerSize
|
||||||
|
|
|
@ -17,8 +17,9 @@ import "../styles-uit"
|
||||||
|
|
||||||
Original.Button {
|
Original.Button {
|
||||||
property int color: 0
|
property int color: 0
|
||||||
property int colorScheme: hifi.colorShemes.light
|
property int colorScheme: hifi.colorSchemes.light
|
||||||
property string glyph: ""
|
property string glyph: ""
|
||||||
|
property int size: 32
|
||||||
|
|
||||||
width: 120
|
width: 120
|
||||||
height: 28
|
height: 28
|
||||||
|
@ -65,7 +66,13 @@ Original.Button {
|
||||||
: hifi.buttons.disabledTextColor[control.colorScheme]
|
: hifi.buttons.disabledTextColor[control.colorScheme]
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
anchors {
|
||||||
|
// Tweak horizontal alignment so that it looks right.
|
||||||
|
left: parent.left
|
||||||
|
leftMargin: -0.5
|
||||||
|
}
|
||||||
text: control.glyph
|
text: control.glyph
|
||||||
|
size: control.size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ SpinBox {
|
||||||
incrementControl: HiFiGlyphs {
|
incrementControl: HiFiGlyphs {
|
||||||
id: incrementButton
|
id: incrementButton
|
||||||
text: hifi.glyphs.caratUp
|
text: hifi.glyphs.caratUp
|
||||||
x: 6
|
x: 10
|
||||||
y: 1
|
y: 1
|
||||||
size: hifi.dimensions.spinnerSize
|
size: hifi.dimensions.spinnerSize
|
||||||
color: styleData.upPressed ? (isLightColorScheme ? hifi.colors.black : hifi.colors.white) : hifi.colors.gray
|
color: styleData.upPressed ? (isLightColorScheme ? hifi.colors.black : hifi.colors.white) : hifi.colors.gray
|
||||||
|
@ -64,8 +64,8 @@ SpinBox {
|
||||||
|
|
||||||
decrementControl: HiFiGlyphs {
|
decrementControl: HiFiGlyphs {
|
||||||
text: hifi.glyphs.caratDn
|
text: hifi.glyphs.caratDn
|
||||||
x: 6
|
x: 10
|
||||||
y: -3
|
y: -1
|
||||||
size: hifi.dimensions.spinnerSize
|
size: hifi.dimensions.spinnerSize
|
||||||
color: styleData.downPressed ? (isLightColorScheme ? hifi.colors.black : hifi.colors.white) : hifi.colors.gray
|
color: styleData.downPressed ? (isLightColorScheme ? hifi.colors.black : hifi.colors.white) : hifi.colors.gray
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,20 +17,68 @@ import "../styles-uit"
|
||||||
TableView {
|
TableView {
|
||||||
id: tableView
|
id: tableView
|
||||||
|
|
||||||
property var tableModel: ListModel { }
|
|
||||||
property int colorScheme: hifi.colorSchemes.light
|
property int colorScheme: hifi.colorSchemes.light
|
||||||
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
|
||||||
|
property bool expandSelectedRow: false
|
||||||
|
|
||||||
model: tableModel
|
model: ListModel { }
|
||||||
|
|
||||||
TableViewColumn {
|
|
||||||
role: "name"
|
|
||||||
}
|
|
||||||
|
|
||||||
anchors { left: parent.left; right: parent.right }
|
|
||||||
|
|
||||||
headerVisible: false
|
headerVisible: false
|
||||||
headerDelegate: Item { } // Fix OSX QML bug that displays scrollbar starting too low.
|
headerDelegate: Rectangle {
|
||||||
|
height: hifi.dimensions.tableHeaderHeight
|
||||||
|
color: isLightColorScheme ? hifi.colors.tableBackgroundLight : hifi.colors.tableBackgroundDark
|
||||||
|
|
||||||
|
RalewayRegular {
|
||||||
|
id: titleText
|
||||||
|
text: styleData.value
|
||||||
|
size: hifi.fontSizes.tableHeading
|
||||||
|
font.capitalization: Font.AllUppercase
|
||||||
|
color: hifi.colors.baseGrayHighlight
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
leftMargin: hifi.dimensions.tablePadding
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HiFiGlyphs {
|
||||||
|
id: titleSort
|
||||||
|
text: sortIndicatorOrder == Qt.AscendingOrder ? hifi.glyphs.caratUp : hifi.glyphs.caratDn
|
||||||
|
color: hifi.colors.baseGrayHighlight
|
||||||
|
size: hifi.fontSizes.tableHeadingIcon
|
||||||
|
anchors {
|
||||||
|
left: titleText.right
|
||||||
|
leftMargin: -hifi.fontSizes.tableHeadingIcon / 3
|
||||||
|
right: parent.right
|
||||||
|
rightMargin: hifi.dimensions.tablePadding
|
||||||
|
verticalCenter: titleText.verticalCenter
|
||||||
|
}
|
||||||
|
visible: sortIndicatorVisible && sortIndicatorColumn === styleData.column
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: 1
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
top: parent.top
|
||||||
|
topMargin: 1
|
||||||
|
bottom: parent.bottom
|
||||||
|
bottomMargin: 2
|
||||||
|
}
|
||||||
|
color: isLightColorScheme ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight
|
||||||
|
visible: styleData.column > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
height: 1
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
bottom: parent.bottom
|
||||||
|
}
|
||||||
|
color: isLightColorScheme ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Use rectangle to draw border with rounded corners.
|
// Use rectangle to draw border with rounded corners.
|
||||||
frameVisible: false
|
frameVisible: false
|
||||||
|
@ -50,8 +98,10 @@ TableView {
|
||||||
|
|
||||||
style: TableViewStyle {
|
style: TableViewStyle {
|
||||||
// Needed in order for rows to keep displaying rows after end of table entries.
|
// Needed in order for rows to keep displaying rows after end of table entries.
|
||||||
backgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightEven : hifi.colors.tableRowDarkEven
|
backgroundColor: tableView.isLightColorScheme ? hifi.colors.tableBackgroundLight : hifi.colors.tableBackgroundDark
|
||||||
alternateBackgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightOdd : hifi.colors.tableRowDarkOdd
|
alternateBackgroundColor: tableView.isLightColorScheme ? hifi.colors.tableRowLightOdd : hifi.colors.tableRowDarkOdd
|
||||||
|
|
||||||
|
padding.top: headerVisible ? hifi.dimensions.tableHeaderHeight: 0
|
||||||
|
|
||||||
handle: Item {
|
handle: Item {
|
||||||
id: scrollbarHandle
|
id: scrollbarHandle
|
||||||
|
@ -59,33 +109,38 @@ TableView {
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors {
|
anchors {
|
||||||
fill: parent
|
fill: parent
|
||||||
|
topMargin: 3
|
||||||
|
bottomMargin: 3 // ""
|
||||||
leftMargin: 2 // Move it right
|
leftMargin: 2 // Move it right
|
||||||
rightMargin: -2 // ""
|
rightMargin: -2 // ""
|
||||||
topMargin: 3 // Shrink vertically
|
|
||||||
bottomMargin: 3 // ""
|
|
||||||
}
|
}
|
||||||
radius: 3
|
radius: 3
|
||||||
color: hifi.colors.tableScrollHandle
|
color: isLightColorScheme ? hifi.colors.tableScrollHandleLight : hifi.colors.tableScrollHandleDark
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scrollBarBackground: Item {
|
scrollBarBackground: Item {
|
||||||
implicitWidth: 10
|
implicitWidth: 9
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors {
|
anchors {
|
||||||
fill: parent
|
fill: parent
|
||||||
margins: -1 // Expand
|
margins: -1 // Expand
|
||||||
|
topMargin: headerVisible ? -hifi.dimensions.tableHeaderHeight : -1
|
||||||
}
|
}
|
||||||
color: hifi.colors.baseGrayHighlight
|
color: isLightColorScheme ? hifi.colors.tableBackgroundLight : hifi.colors.tableBackgroundDark
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
// Extend header bottom border
|
||||||
anchors {
|
anchors {
|
||||||
fill: parent
|
top: parent.top
|
||||||
margins: 1 // Shrink
|
topMargin: hifi.dimensions.tableHeaderHeight - 1
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
height: 1
|
||||||
|
color: isLightColorScheme ? hifi.colors.lightGrayText : hifi.colors.baseGrayHighlight
|
||||||
|
visible: headerVisible
|
||||||
}
|
}
|
||||||
radius: 4
|
|
||||||
color: hifi.colors.tableScrollBackground
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,85 +154,11 @@ TableView {
|
||||||
}
|
}
|
||||||
|
|
||||||
rowDelegate: Rectangle {
|
rowDelegate: Rectangle {
|
||||||
height: (styleData.selected ? 1.8 : 1) * hifi.dimensions.tableRowHeight
|
height: (styleData.selected && expandSelectedRow ? 1.8 : 1) * hifi.dimensions.tableRowHeight
|
||||||
color: styleData.selected
|
color: styleData.selected
|
||||||
? hifi.colors.primaryHighlight
|
? hifi.colors.primaryHighlight
|
||||||
: tableView.isLightColorScheme
|
: tableView.isLightColorScheme
|
||||||
? (styleData.alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd)
|
? (styleData.alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd)
|
||||||
: (styleData.alternate ? hifi.colors.tableRowDarkEven : hifi.colors.tableRowDarkOdd)
|
: (styleData.alternate ? hifi.colors.tableRowDarkEven : hifi.colors.tableRowDarkOdd)
|
||||||
}
|
}
|
||||||
|
|
||||||
itemDelegate: Item {
|
|
||||||
anchors {
|
|
||||||
left: parent ? parent.left : undefined
|
|
||||||
leftMargin: hifi.dimensions.tablePadding
|
|
||||||
right: parent ? parent.right : undefined
|
|
||||||
rightMargin: hifi.dimensions.tablePadding
|
|
||||||
}
|
|
||||||
|
|
||||||
FiraSansSemiBold {
|
|
||||||
id: textItem
|
|
||||||
text: styleData.value
|
|
||||||
size: hifi.fontSizes.tableText
|
|
||||||
color: colorScheme == hifi.colorSchemes.light
|
|
||||||
? (styleData.selected ? hifi.colors.black : hifi.colors.baseGrayHighlight)
|
|
||||||
: (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText)
|
|
||||||
anchors {
|
|
||||||
left: parent.left
|
|
||||||
right: parent.right
|
|
||||||
top: parent.top
|
|
||||||
topMargin: 3
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Put reload item in tableModel passed in from RunningScripts.
|
|
||||||
HiFiGlyphs {
|
|
||||||
id: reloadButton
|
|
||||||
text: hifi.glyphs.reloadSmall
|
|
||||||
color: reloadButtonArea.pressed ? hifi.colors.white : parent.color
|
|
||||||
anchors {
|
|
||||||
top: parent.top
|
|
||||||
right: stopButton.left
|
|
||||||
verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
MouseArea {
|
|
||||||
id: reloadButtonArea
|
|
||||||
anchors { fill: parent; margins: -2 }
|
|
||||||
onClicked: reloadScript(model.url)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Put stop item in tableModel passed in from RunningScripts.
|
|
||||||
HiFiGlyphs {
|
|
||||||
id: stopButton
|
|
||||||
text: hifi.glyphs.closeSmall
|
|
||||||
color: stopButtonArea.pressed ? hifi.colors.white : parent.color
|
|
||||||
anchors {
|
|
||||||
top: parent.top
|
|
||||||
right: parent.right
|
|
||||||
verticalCenter: parent.verticalCenter
|
|
||||||
}
|
|
||||||
MouseArea {
|
|
||||||
id: stopButtonArea
|
|
||||||
anchors { fill: parent; margins: -2 }
|
|
||||||
onClicked: stopScript(model.url)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Automatically use aux. information from tableModel
|
|
||||||
FiraSansSemiBold {
|
|
||||||
text: tableModel.get(styleData.row) ? tableModel.get(styleData.row).url : ""
|
|
||||||
elide: Text.ElideMiddle
|
|
||||||
size: hifi.fontSizes.tableText
|
|
||||||
color: colorScheme == hifi.colorSchemes.light
|
|
||||||
? (styleData.selected ? hifi.colors.black : hifi.colors.lightGray)
|
|
||||||
: (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText)
|
|
||||||
anchors {
|
|
||||||
top: textItem.bottom
|
|
||||||
left: parent.left
|
|
||||||
right: parent.right
|
|
||||||
}
|
|
||||||
visible: styleData.selected
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
// Table.qml
|
// Tree.qml
|
||||||
//
|
//
|
||||||
// Created by David Rowe on 17 Feb 2016
|
// Created by David Rowe on 17 Feb 2016
|
||||||
// Copyright 2016 High Fidelity, Inc.
|
// Copyright 2016 High Fidelity, Inc.
|
||||||
|
@ -85,27 +85,18 @@ TreeView {
|
||||||
bottomMargin: 3 // ""
|
bottomMargin: 3 // ""
|
||||||
}
|
}
|
||||||
radius: 3
|
radius: 3
|
||||||
color: hifi.colors.tableScrollHandle
|
color: hifi.colors.tableScrollHandleDark
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scrollBarBackground: Item {
|
scrollBarBackground: Item {
|
||||||
implicitWidth: 10
|
implicitWidth: 9
|
||||||
Rectangle {
|
Rectangle {
|
||||||
anchors {
|
anchors {
|
||||||
fill: parent
|
fill: parent
|
||||||
margins: -1 // Expand
|
margins: -1 // Expand
|
||||||
}
|
}
|
||||||
color: hifi.colors.baseGrayHighlight
|
color: hifi.colors.tableBackgroundDark
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
anchors {
|
|
||||||
fill: parent
|
|
||||||
margins: 1 // Shrink
|
|
||||||
}
|
|
||||||
radius: 4
|
|
||||||
color: hifi.colors.tableScrollBackground
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,14 @@
|
||||||
import QtQuick 2.0
|
//
|
||||||
|
// FileDialog.qml
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 14 Jan 2016
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
import QtQuick 2.5
|
||||||
import QtQuick.Controls 1.4
|
import QtQuick.Controls 1.4
|
||||||
import Qt.labs.folderlistmodel 2.1
|
import Qt.labs.folderlistmodel 2.1
|
||||||
import Qt.labs.settings 1.0
|
import Qt.labs.settings 1.0
|
||||||
|
@ -6,17 +16,20 @@ import QtQuick.Controls.Styles 1.4
|
||||||
import QtQuick.Dialogs 1.2 as OriginalDialogs
|
import QtQuick.Dialogs 1.2 as OriginalDialogs
|
||||||
|
|
||||||
import ".."
|
import ".."
|
||||||
import "../windows"
|
import "../controls-uit"
|
||||||
import "../styles"
|
import "../styles-uit"
|
||||||
import "../controls" as VrControls
|
import "../windows-uit"
|
||||||
|
|
||||||
import "fileDialog"
|
import "fileDialog"
|
||||||
|
|
||||||
//FIXME implement shortcuts for favorite location
|
//FIXME implement shortcuts for favorite location
|
||||||
ModalWindow {
|
ModalWindow {
|
||||||
id: root
|
id: root
|
||||||
resizable: true
|
//resizable: true
|
||||||
width: 640
|
implicitWidth: 640
|
||||||
height: 480
|
implicitHeight: 480
|
||||||
|
|
||||||
|
HifiConstants { id: hifi }
|
||||||
|
|
||||||
Settings {
|
Settings {
|
||||||
category: "FileDialog"
|
category: "FileDialog"
|
||||||
|
@ -30,12 +43,14 @@ ModalWindow {
|
||||||
// Set from OffscreenUi::getOpenFile()
|
// Set from OffscreenUi::getOpenFile()
|
||||||
property alias caption: root.title;
|
property alias caption: root.title;
|
||||||
// Set from OffscreenUi::getOpenFile()
|
// Set from OffscreenUi::getOpenFile()
|
||||||
property alias dir: model.folder;
|
property alias dir: fileTableModel.folder;
|
||||||
// Set from OffscreenUi::getOpenFile()
|
// Set from OffscreenUi::getOpenFile()
|
||||||
property alias filter: selectionType.filtersString;
|
property alias filter: selectionType.filtersString;
|
||||||
// Set from OffscreenUi::getOpenFile()
|
// Set from OffscreenUi::getOpenFile()
|
||||||
property int options; // <-- FIXME unused
|
property int options; // <-- FIXME unused
|
||||||
|
|
||||||
|
property string iconText: text !== "" ? hifi.glyphs.scriptUpload : ""
|
||||||
|
property int iconSize: 40
|
||||||
|
|
||||||
property bool selectDirectory: false;
|
property bool selectDirectory: false;
|
||||||
property bool showHidden: false;
|
property bool showHidden: false;
|
||||||
|
@ -46,77 +61,120 @@ ModalWindow {
|
||||||
property alias model: fileTableView.model
|
property alias model: fileTableView.model
|
||||||
property var drives: helper.drives()
|
property var drives: helper.drives()
|
||||||
|
|
||||||
|
property int titleWidth: 0
|
||||||
|
|
||||||
signal selectedFile(var file);
|
signal selectedFile(var file);
|
||||||
signal canceled();
|
signal canceled();
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
console.log("Helper " + helper + " drives " + drives)
|
console.log("Helper " + helper + " drives " + drives)
|
||||||
drivesSelector.onCurrentTextChanged.connect(function(){
|
|
||||||
root.dir = helper.pathToUrl(drivesSelector.currentText);
|
// HACK: The following lines force the model to initialize properly such that the go-up button
|
||||||
})
|
// works properly from the initial screen.
|
||||||
|
var initialFolder = folderListModel.folder;
|
||||||
|
fileTableModel.folder = helper.pathToUrl(drives[0]);
|
||||||
|
fileTableModel.folder = initialFolder;
|
||||||
|
|
||||||
|
iconText = root.title !== "" ? hifi.glyphs.scriptUpload : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Item {
|
||||||
anchors.fill: parent
|
clip: true
|
||||||
color: "white"
|
width: pane.width
|
||||||
|
height: pane.height
|
||||||
|
anchors.margins: 0
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
id: navControls
|
id: navControls
|
||||||
anchors { left: parent.left; top: parent.top; margins: 8 }
|
anchors {
|
||||||
spacing: 8
|
top: parent.top
|
||||||
// FIXME implement back button
|
topMargin: hifi.dimensions.contentMargin.y
|
||||||
//VrControls.ButtonAwesome {
|
left: parent.left
|
||||||
// id: backButton
|
}
|
||||||
// text: "\uf0a8"
|
spacing: hifi.dimensions.contentSpacing.x
|
||||||
// size: currentDirectory.height
|
|
||||||
// enabled: d.backStack.length != 0
|
GlyphButton {
|
||||||
// MouseArea { anchors.fill: parent; onClicked: d.navigateBack() }
|
|
||||||
//}
|
|
||||||
VrControls.ButtonAwesome {
|
|
||||||
id: upButton
|
id: upButton
|
||||||
enabled: model.parentFolder && model.parentFolder !== ""
|
glyph: hifi.glyphs.levelUp
|
||||||
text: "\uf0aa"
|
width: height
|
||||||
size: 32
|
size: 30
|
||||||
|
enabled: fileTableModel.parentFolder && fileTableModel.parentFolder !== ""
|
||||||
onClicked: d.navigateUp();
|
onClicked: d.navigateUp();
|
||||||
}
|
}
|
||||||
VrControls.ButtonAwesome {
|
|
||||||
|
GlyphButton {
|
||||||
id: homeButton
|
id: homeButton
|
||||||
property var destination: helper.home();
|
property var destination: helper.home();
|
||||||
|
glyph: hifi.glyphs.home
|
||||||
|
size: 28
|
||||||
|
width: height
|
||||||
enabled: d.homeDestination ? true : false
|
enabled: d.homeDestination ? true : false
|
||||||
text: "\uf015"
|
|
||||||
size: 32
|
|
||||||
onClicked: d.navigateHome();
|
onClicked: d.navigateHome();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VrControls.ComboBox {
|
ComboBox {
|
||||||
id: drivesSelector
|
id: pathSelector
|
||||||
width: 48
|
anchors {
|
||||||
height: homeButton.height
|
top: parent.top
|
||||||
model: drives
|
topMargin: hifi.dimensions.contentMargin.y
|
||||||
visible: drives.length > 1
|
left: navControls.right
|
||||||
currentIndex: 0
|
leftMargin: hifi.dimensions.contentSpacing.x
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
|
||||||
|
property var lastValidFolder: helper.urlToPath(fileTableModel.folder)
|
||||||
|
|
||||||
|
function calculatePathChoices(folder) {
|
||||||
|
var folders = folder.split("/"),
|
||||||
|
choices = [],
|
||||||
|
i, length;
|
||||||
|
|
||||||
|
if (folders[folders.length - 1] === "") {
|
||||||
|
folders.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
choices.push(folders[0]);
|
||||||
|
|
||||||
|
for (i = 1, length = folders.length; i < length; i++) {
|
||||||
|
choices.push(choices[i - 1] + "/" + folders[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (folders[0] === "") {
|
||||||
|
// Special handling for OSX root dir.
|
||||||
|
choices[0] = "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
choices.reverse();
|
||||||
|
|
||||||
|
if (drives && drives.length > 1) {
|
||||||
|
choices.push("This PC");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (choices.length > 0) {
|
||||||
|
pathSelector.model = choices;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextField {
|
onLastValidFolderChanged: {
|
||||||
id: currentDirectory
|
var folder = d.capitalizeDrive(lastValidFolder);
|
||||||
height: homeButton.height
|
calculatePathChoices(folder);
|
||||||
style: TextFieldStyle { renderType: Text.QtRendering }
|
}
|
||||||
anchors { left: navControls.right; right: parent.right; top: parent.top; margins: 8 }
|
|
||||||
property var lastValidFolder: helper.urlToPath(model.folder)
|
onCurrentTextChanged: {
|
||||||
onLastValidFolderChanged: text = lastValidFolder;
|
var folder = currentText;
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
font.pointSize: 14
|
if (/^[a-zA-z]:$/.test(folder)) {
|
||||||
font.bold: true
|
folder = "file:///" + folder + "/";
|
||||||
|
} else if (folder === "This PC") {
|
||||||
// FIXME add support auto-completion
|
folder = "file:///";
|
||||||
onAccepted: {
|
} else {
|
||||||
if (!helper.validFolder(text)) {
|
folder = helper.pathToUrl(folder);
|
||||||
text = lastValidFolder;
|
}
|
||||||
return
|
|
||||||
|
if (helper.urlToPath(folder).toLowerCase() !== helper.urlToPath(fileTableModel.folder).toLowerCase()) {
|
||||||
|
fileTableModel.folder = folder;
|
||||||
}
|
}
|
||||||
model.folder = helper.pathToUrl(text);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,65 +185,321 @@ ModalWindow {
|
||||||
property bool currentSelectionIsFolder;
|
property bool currentSelectionIsFolder;
|
||||||
property var backStack: []
|
property var backStack: []
|
||||||
property var tableViewConnection: Connections { target: fileTableView; onCurrentRowChanged: d.update(); }
|
property var tableViewConnection: Connections { target: fileTableView; onCurrentRowChanged: d.update(); }
|
||||||
property var modelConnection: Connections { target: model; onFolderChanged: d.update(); }
|
property var modelConnection: Connections { target: fileTableModel; onFolderChanged: d.update(); }
|
||||||
property var homeDestination: helper.home();
|
property var homeDestination: helper.home();
|
||||||
Component.onCompleted: update();
|
|
||||||
|
function capitalizeDrive(path) {
|
||||||
|
// Consistently capitalize drive letter for Windows.
|
||||||
|
if (/[a-zA-Z]:/.test(path)) {
|
||||||
|
return path.charAt(0).toUpperCase() + path.slice(1);
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
function update() {
|
function update() {
|
||||||
var row = fileTableView.currentRow;
|
var row = fileTableView.currentRow;
|
||||||
if (row === -1 && root.selectDirectory) {
|
|
||||||
currentSelectionUrl = fileTableView.model.folder;
|
if (row === -1) {
|
||||||
currentSelectionIsFolder = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentSelectionUrl = fileTableView.model.get(row, "fileURL");
|
currentSelectionUrl = helper.pathToUrl(fileTableView.model.get(row).filePath);
|
||||||
currentSelectionIsFolder = fileTableView.model.isFolder(row);
|
currentSelectionIsFolder = fileTableView.model.isFolder(row);
|
||||||
if (root.selectDirectory || !currentSelectionIsFolder) {
|
if (root.selectDirectory || !currentSelectionIsFolder) {
|
||||||
currentSelection.text = helper.urlToPath(currentSelectionUrl);
|
currentSelection.text = capitalizeDrive(helper.urlToPath(currentSelectionUrl));
|
||||||
} else {
|
} else {
|
||||||
currentSelection.text = ""
|
currentSelection.text = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function navigateUp() {
|
function navigateUp() {
|
||||||
if (model.parentFolder && model.parentFolder !== "") {
|
if (fileTableModel.parentFolder && fileTableModel.parentFolder !== "") {
|
||||||
model.folder = model.parentFolder
|
fileTableModel.folder = fileTableModel.parentFolder;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function navigateHome() {
|
function navigateHome() {
|
||||||
model.folder = homeDestination;
|
fileTableModel.folder = homeDestination;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FileTableView {
|
FolderListModel {
|
||||||
id: fileTableView
|
id: folderListModel
|
||||||
anchors { left: parent.left; right: parent.right; top: currentDirectory.bottom; bottom: currentSelection.top; margins: 8 }
|
|
||||||
onDoubleClicked: navigateToRow(row);
|
|
||||||
focus: true
|
|
||||||
Keys.onReturnPressed: navigateToCurrentRow();
|
|
||||||
Keys.onEnterPressed: navigateToCurrentRow();
|
|
||||||
model: FolderListModel {
|
|
||||||
id: model
|
|
||||||
nameFilters: selectionType.currentFilter
|
nameFilters: selectionType.currentFilter
|
||||||
showDirsFirst: true
|
showDirsFirst: true
|
||||||
showDotAndDotDot: false
|
showDotAndDotDot: false
|
||||||
showFiles: !root.selectDirectory
|
showFiles: !root.selectDirectory
|
||||||
// For some reason, declaring these bindings directly in the targets doesn't
|
|
||||||
// work for setting the initial state
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
currentDirectory.lastValidFolder = Qt.binding(function() { return helper.urlToPath(model.folder); });
|
|
||||||
upButton.enabled = Qt.binding(function() { return (model.parentFolder && model.parentFolder != "") ? true : false; });
|
|
||||||
showFiles = !root.selectDirectory
|
showFiles = !root.selectDirectory
|
||||||
}
|
}
|
||||||
|
|
||||||
onFolderChanged: {
|
onFolderChanged: {
|
||||||
fileTableView.selection.clear();
|
fileTableModel.update(); // Update once the data from the folder change is available.
|
||||||
fileTableView.selection.select(0);
|
|
||||||
fileTableView.currentRow = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getItem(index, field) {
|
||||||
|
return get(index, field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel {
|
||||||
|
// Emulates FolderListModel but contains drive data.
|
||||||
|
id: driveListModel
|
||||||
|
|
||||||
|
property int count: 1
|
||||||
|
|
||||||
|
Component.onCompleted: initialize();
|
||||||
|
|
||||||
|
function initialize() {
|
||||||
|
var drive,
|
||||||
|
i;
|
||||||
|
|
||||||
|
count = drives.length;
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
drive = drives[i].slice(0, -1); // Remove trailing "/".
|
||||||
|
append({
|
||||||
|
fileName: drive,
|
||||||
|
fileModified: new Date(0),
|
||||||
|
fileSize: 0,
|
||||||
|
filePath: drive + "/",
|
||||||
|
fileIsDir: true,
|
||||||
|
fileNameSort: drive.toLowerCase()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getItem(index, field) {
|
||||||
|
return get(index)[field];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel {
|
||||||
|
id: fileTableModel
|
||||||
|
|
||||||
|
// FolderListModel has a couple of problems:
|
||||||
|
// 1) Files and directories sort case-sensitively: https://bugreports.qt.io/browse/QTBUG-48757
|
||||||
|
// 2) Cannot browse up to the "computer" level to view Windows drives: https://bugreports.qt.io/browse/QTBUG-42901
|
||||||
|
//
|
||||||
|
// To solve these problems an intermediary ListModel is used that implements proper sorting and can be populated with
|
||||||
|
// drive information when viewing at the computer level.
|
||||||
|
|
||||||
|
property var folder
|
||||||
|
property int sortOrder: Qt.AscendingOrder
|
||||||
|
property int sortColumn: 0
|
||||||
|
property var model: folderListModel
|
||||||
|
property string parentFolder: calculateParentFolder();
|
||||||
|
|
||||||
|
readonly property string rootFolder: "file:///"
|
||||||
|
|
||||||
|
function calculateParentFolder() {
|
||||||
|
if (model === folderListModel) {
|
||||||
|
if (folderListModel.parentFolder.toString() === "" && driveListModel.count > 1) {
|
||||||
|
return rootFolder;
|
||||||
|
} else {
|
||||||
|
return folderListModel.parentFolder;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onFolderChanged: {
|
||||||
|
if (folder === rootFolder) {
|
||||||
|
model = driveListModel;
|
||||||
|
update();
|
||||||
|
} else {
|
||||||
|
var needsUpdate = model === driveListModel && folder === folderListModel.folder;
|
||||||
|
|
||||||
|
model = folderListModel;
|
||||||
|
folderListModel.folder = folder;
|
||||||
|
|
||||||
|
if (needsUpdate) {
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isFolder(row) {
|
||||||
|
if (row === -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return get(row).fileIsDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
var dataFields = ["fileName", "fileModified", "fileSize"],
|
||||||
|
sortFields = ["fileNameSort", "fileModified", "fileSize"],
|
||||||
|
dataField = dataFields[sortColumn],
|
||||||
|
sortField = sortFields[sortColumn],
|
||||||
|
sortValue,
|
||||||
|
fileName,
|
||||||
|
fileIsDir,
|
||||||
|
comparisonFunction,
|
||||||
|
lower,
|
||||||
|
middle,
|
||||||
|
upper,
|
||||||
|
rows = 0,
|
||||||
|
i;
|
||||||
|
|
||||||
|
clear();
|
||||||
|
|
||||||
|
comparisonFunction = sortOrder === Qt.AscendingOrder
|
||||||
|
? function(a, b) { return a < b; }
|
||||||
|
: function(a, b) { return a > b; }
|
||||||
|
|
||||||
|
for (i = 0; i < model.count; i++) {
|
||||||
|
fileName = model.getItem(i, "fileName");
|
||||||
|
fileIsDir = model.getItem(i, "fileIsDir");
|
||||||
|
|
||||||
|
sortValue = model.getItem(i, dataField);
|
||||||
|
if (dataField === "fileName") {
|
||||||
|
// Directories first by prefixing a "*".
|
||||||
|
// Case-insensitive.
|
||||||
|
sortValue = (fileIsDir ? "*" : "") + sortValue.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
lower = 0;
|
||||||
|
upper = rows;
|
||||||
|
while (lower < upper) {
|
||||||
|
middle = Math.floor((lower + upper) / 2);
|
||||||
|
var lessThan;
|
||||||
|
if (comparisonFunction(sortValue, get(middle)[sortField])) {
|
||||||
|
lessThan = true;
|
||||||
|
upper = middle;
|
||||||
|
} else {
|
||||||
|
lessThan = false;
|
||||||
|
lower = middle + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
insert(lower, {
|
||||||
|
fileName: fileName,
|
||||||
|
fileModified: (fileIsDir ? new Date(0) : model.getItem(i, "fileModified")),
|
||||||
|
fileSize: model.getItem(i, "fileSize"),
|
||||||
|
filePath: model.getItem(i, "filePath"),
|
||||||
|
fileIsDir: fileIsDir,
|
||||||
|
fileNameSort: (fileIsDir ? "*" : "") + fileName.toLowerCase()
|
||||||
|
});
|
||||||
|
|
||||||
|
rows++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Table {
|
||||||
|
id: fileTableView
|
||||||
|
colorScheme: hifi.colorSchemes.light
|
||||||
|
anchors {
|
||||||
|
top: navControls.bottom
|
||||||
|
topMargin: hifi.dimensions.contentSpacing.y
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
bottom: currentSelection.top
|
||||||
|
bottomMargin: hifi.dimensions.contentSpacing.y + currentSelection.controlHeight - currentSelection.height
|
||||||
|
}
|
||||||
|
headerVisible: !selectDirectory
|
||||||
|
onDoubleClicked: navigateToRow(row);
|
||||||
|
focus: true
|
||||||
|
Keys.onReturnPressed: navigateToCurrentRow();
|
||||||
|
Keys.onEnterPressed: navigateToCurrentRow();
|
||||||
|
|
||||||
|
sortIndicatorColumn: 0
|
||||||
|
sortIndicatorOrder: Qt.AscendingOrder
|
||||||
|
sortIndicatorVisible: true
|
||||||
|
|
||||||
|
model: fileTableModel
|
||||||
|
|
||||||
|
function updateSort() {
|
||||||
|
model.sortOrder = sortIndicatorOrder;
|
||||||
|
model.sortColumn = sortIndicatorColumn;
|
||||||
|
model.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
onSortIndicatorColumnChanged: { updateSort(); }
|
||||||
|
|
||||||
|
onSortIndicatorOrderChanged: { updateSort(); }
|
||||||
|
|
||||||
|
onActiveFocusChanged: {
|
||||||
|
if (activeFocus && currentRow == -1) {
|
||||||
|
fileTableView.selection.select(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
itemDelegate: Item {
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
FontLoader { id: firaSansSemiBold; source: "../../fonts/FiraSans-SemiBold.ttf"; }
|
||||||
|
FontLoader { id: firaSansRegular; source: "../../fonts/FiraSans-Regular.ttf"; }
|
||||||
|
|
||||||
|
FiraSansSemiBold {
|
||||||
|
text: getText();
|
||||||
|
elide: styleData.elideMode
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
leftMargin: hifi.dimensions.tablePadding
|
||||||
|
right: parent.right
|
||||||
|
rightMargin: hifi.dimensions.tablePadding
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
size: hifi.fontSizes.tableText
|
||||||
|
color: hifi.colors.baseGrayHighlight
|
||||||
|
font.family: (styleData.row !== -1 && fileTableView.model.get(styleData.row).fileIsDir)
|
||||||
|
? firaSansSemiBold.name : firaSansRegular.name
|
||||||
|
|
||||||
|
function getText() {
|
||||||
|
if (styleData.row === -1) {
|
||||||
|
return styleData.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (styleData.column) {
|
||||||
|
case 1: return fileTableView.model.get(styleData.row).fileIsDir ? "" : styleData.value;
|
||||||
|
case 2: return fileTableView.model.get(styleData.row).fileIsDir ? "" : formatSize(styleData.value);
|
||||||
|
default: return styleData.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function formatSize(size) {
|
||||||
|
var suffixes = [ "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" ];
|
||||||
|
var suffixIndex = 0
|
||||||
|
while ((size / 1024.0) > 1.1) {
|
||||||
|
size /= 1024.0;
|
||||||
|
++suffixIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = Math.round(size*1000)/1000;
|
||||||
|
size = size.toLocaleString()
|
||||||
|
|
||||||
|
return size + " " + suffixes[suffixIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TableViewColumn {
|
||||||
|
id: fileNameColumn
|
||||||
|
role: "fileName"
|
||||||
|
title: "Name"
|
||||||
|
width: (selectDirectory ? 1.0 : 0.5) * fileTableView.width
|
||||||
|
movable: false
|
||||||
|
resizable: true
|
||||||
|
}
|
||||||
|
TableViewColumn {
|
||||||
|
id: fileMofifiedColumn
|
||||||
|
role: "fileModified"
|
||||||
|
title: "Date"
|
||||||
|
width: 0.3 * fileTableView.width
|
||||||
|
movable: false
|
||||||
|
resizable: true
|
||||||
|
visible: !selectDirectory
|
||||||
|
}
|
||||||
|
TableViewColumn {
|
||||||
|
role: "fileSize"
|
||||||
|
title: "Size"
|
||||||
|
width: fileTableView.width - fileNameColumn.width - fileMofifiedColumn.width
|
||||||
|
movable: false
|
||||||
|
resizable: true
|
||||||
|
visible: !selectDirectory
|
||||||
}
|
}
|
||||||
|
|
||||||
function navigateToRow(row) {
|
function navigateToRow(row) {
|
||||||
|
@ -196,9 +510,9 @@ ModalWindow {
|
||||||
function navigateToCurrentRow() {
|
function navigateToCurrentRow() {
|
||||||
var row = fileTableView.currentRow
|
var row = fileTableView.currentRow
|
||||||
var isFolder = model.isFolder(row);
|
var isFolder = model.isFolder(row);
|
||||||
var file = model.get(row, "fileURL");
|
var file = model.get(row).filePath;
|
||||||
if (isFolder) {
|
if (isFolder) {
|
||||||
fileTableView.model.folder = file
|
fileTableView.model.folder = helper.pathToUrl(file);
|
||||||
} else {
|
} else {
|
||||||
okAction.trigger();
|
okAction.trigger();
|
||||||
}
|
}
|
||||||
|
@ -213,7 +527,7 @@ ModalWindow {
|
||||||
var newPrefix = prefix + event.text.toLowerCase();
|
var newPrefix = prefix + event.text.toLowerCase();
|
||||||
var matchedIndex = -1;
|
var matchedIndex = -1;
|
||||||
for (var i = 0; i < model.count; ++i) {
|
for (var i = 0; i < model.count; ++i) {
|
||||||
var name = model.get(i, "fileName").toLowerCase();
|
var name = model.get(i).fileName.toLowerCase();
|
||||||
if (0 === name.indexOf(newPrefix)) {
|
if (0 === name.indexOf(newPrefix)) {
|
||||||
matchedIndex = i;
|
matchedIndex = i;
|
||||||
break;
|
break;
|
||||||
|
@ -254,14 +568,19 @@ ModalWindow {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextField {
|
TextField {
|
||||||
id: currentSelection
|
id: currentSelection
|
||||||
style: TextFieldStyle { renderType: Text.QtRendering }
|
label: "Path:"
|
||||||
anchors { right: root.selectDirectory ? parent.right : selectionType.left; rightMargin: 8; left: parent.left; leftMargin: 8; top: selectionType.top }
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: selectionType.visible ? selectionType.left: parent.right
|
||||||
|
rightMargin: selectionType.visible ? hifi.dimensions.contentSpacing.x : 0
|
||||||
|
bottom: buttonRow.top
|
||||||
|
bottomMargin: hifi.dimensions.contentSpacing.y
|
||||||
|
}
|
||||||
readOnly: !root.saveDialog
|
readOnly: !root.saveDialog
|
||||||
activeFocusOnTab: !readOnly
|
activeFocusOnTab: !readOnly
|
||||||
onActiveFocusChanged: if (activeFocus) { selectAll(); }
|
onActiveFocusChanged: if (activeFocus) { selectAll(); }
|
||||||
|
@ -270,27 +589,34 @@ ModalWindow {
|
||||||
|
|
||||||
FileTypeSelection {
|
FileTypeSelection {
|
||||||
id: selectionType
|
id: selectionType
|
||||||
anchors { bottom: buttonRow.top; bottomMargin: 8; right: parent.right; rightMargin: 8; left: buttonRow.left }
|
anchors {
|
||||||
visible: !selectDirectory
|
top: currentSelection.top
|
||||||
|
left: buttonRow.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
visible: !selectDirectory && filtersCount > 1
|
||||||
KeyNavigation.left: fileTableView
|
KeyNavigation.left: fileTableView
|
||||||
KeyNavigation.right: openButton
|
KeyNavigation.right: openButton
|
||||||
}
|
}
|
||||||
|
|
||||||
Row {
|
Row {
|
||||||
id: buttonRow
|
id: buttonRow
|
||||||
anchors.right: parent.right
|
anchors {
|
||||||
anchors.rightMargin: 8
|
right: parent.right
|
||||||
anchors.bottom: parent.bottom
|
bottom: parent.bottom
|
||||||
anchors.bottomMargin: 8
|
}
|
||||||
spacing: 8
|
spacing: hifi.dimensions.contentSpacing.y
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
id: openButton
|
id: openButton
|
||||||
|
color: hifi.buttons.blue
|
||||||
action: okAction
|
action: okAction
|
||||||
Keys.onReturnPressed: okAction.trigger()
|
Keys.onReturnPressed: okAction.trigger()
|
||||||
KeyNavigation.up: selectionType
|
KeyNavigation.up: selectionType
|
||||||
KeyNavigation.left: selectionType
|
KeyNavigation.left: selectionType
|
||||||
KeyNavigation.right: cancelButton
|
KeyNavigation.right: cancelButton
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
id: cancelButton
|
id: cancelButton
|
||||||
action: cancelAction
|
action: cancelAction
|
||||||
|
@ -385,5 +711,3 @@ ModalWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
import QtQuick 2.0
|
|
||||||
import QtQuick.Controls 1.4
|
|
||||||
|
|
||||||
TableView {
|
|
||||||
id: root
|
|
||||||
onActiveFocusChanged: {
|
|
||||||
if (activeFocus && currentRow == -1) {
|
|
||||||
root.selection.select(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
itemDelegate: Component {
|
|
||||||
Item {
|
|
||||||
clip: true
|
|
||||||
Text {
|
|
||||||
x: 3
|
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
color: styleData.textColor
|
|
||||||
elide: styleData.elideMode
|
|
||||||
text: getText();
|
|
||||||
font.italic: root.model.get(styleData.row, "fileIsDir") ? true : false
|
|
||||||
|
|
||||||
function getText() {
|
|
||||||
switch (styleData.column) {
|
|
||||||
//case 1: return Date.fromLocaleString(locale, styleData.value, "yyyy-MM-dd hh:mm:ss");
|
|
||||||
case 2: return root.model.get(styleData.row, "fileIsDir") ? "" : formatSize(styleData.value);
|
|
||||||
default: return styleData.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function formatSize(size) {
|
|
||||||
var suffixes = [ "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" ];
|
|
||||||
var suffixIndex = 0
|
|
||||||
while ((size / 1024.0) > 1.1) {
|
|
||||||
size /= 1024.0;
|
|
||||||
++suffixIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
size = Math.round(size*1000)/1000;
|
|
||||||
size = size.toLocaleString()
|
|
||||||
|
|
||||||
return size + " " + suffixes[suffixIndex];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TableViewColumn {
|
|
||||||
role: "fileName"
|
|
||||||
title: "Name"
|
|
||||||
width: 400
|
|
||||||
}
|
|
||||||
TableViewColumn {
|
|
||||||
role: "fileModified"
|
|
||||||
title: "Date Modified"
|
|
||||||
width: 200
|
|
||||||
}
|
|
||||||
TableViewColumn {
|
|
||||||
role: "fileSize"
|
|
||||||
title: "Size"
|
|
||||||
width: 200
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,22 @@
|
||||||
|
//
|
||||||
|
// FileTypeSelection.qml
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 29 Jan 2016
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
import QtQuick 2.5
|
import QtQuick 2.5
|
||||||
|
|
||||||
import "../../controls" as VrControls
|
import "../../controls-uit"
|
||||||
|
|
||||||
VrControls.ComboBox {
|
ComboBox {
|
||||||
id: root
|
id: root
|
||||||
property string filtersString: "All Files (*.*)";
|
property string filtersString: "All Files (*.*)";
|
||||||
property var currentFilter: [ "*.*" ];
|
property var currentFilter: [ "*.*" ];
|
||||||
|
property int filtersCount: filtersString.split(';;').length
|
||||||
|
|
||||||
// Per http://doc.qt.io/qt-5/qfiledialog.html#getOpenFileName the string can contain
|
// Per http://doc.qt.io/qt-5/qfiledialog.html#getOpenFileName the string can contain
|
||||||
// multiple filters separated by semicolons
|
// multiple filters separated by semicolons
|
||||||
|
|
|
@ -118,11 +118,89 @@ Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
HifiControls.Table {
|
HifiControls.Table {
|
||||||
tableModel: runningScriptsModel
|
model: runningScriptsModel
|
||||||
|
id: table
|
||||||
height: 185
|
height: 185
|
||||||
colorScheme: hifi.colorSchemes.dark
|
colorScheme: hifi.colorSchemes.dark
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
expandSelectedRow: true
|
||||||
|
|
||||||
|
itemDelegate: Item {
|
||||||
|
anchors {
|
||||||
|
left: parent ? parent.left : undefined
|
||||||
|
leftMargin: hifi.dimensions.tablePadding
|
||||||
|
right: parent ? parent.right : undefined
|
||||||
|
rightMargin: hifi.dimensions.tablePadding
|
||||||
|
}
|
||||||
|
|
||||||
|
FiraSansSemiBold {
|
||||||
|
id: textItem
|
||||||
|
text: styleData.value
|
||||||
|
size: hifi.fontSizes.tableText
|
||||||
|
color: table.colorScheme == hifi.colorSchemes.light
|
||||||
|
? (styleData.selected ? hifi.colors.black : hifi.colors.baseGrayHighlight)
|
||||||
|
: (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText)
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
top: parent.top
|
||||||
|
topMargin: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
HiFiGlyphs {
|
||||||
|
id: reloadButton
|
||||||
|
text: hifi.glyphs.reloadSmall
|
||||||
|
color: reloadButtonArea.pressed ? hifi.colors.white : parent.color
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
right: stopButton.left
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
id: reloadButtonArea
|
||||||
|
anchors { fill: parent; margins: -2 }
|
||||||
|
onClicked: reloadScript(model.url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HiFiGlyphs {
|
||||||
|
id: stopButton
|
||||||
|
text: hifi.glyphs.closeSmall
|
||||||
|
color: stopButtonArea.pressed ? hifi.colors.white : parent.color
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
right: parent.right
|
||||||
|
verticalCenter: parent.verticalCenter
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
id: stopButtonArea
|
||||||
|
anchors { fill: parent; margins: -2 }
|
||||||
|
onClicked: stopScript(model.url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
FiraSansSemiBold {
|
||||||
|
text: runningScriptsModel.get(styleData.row) ? runningScriptsModel.get(styleData.row).url : ""
|
||||||
|
elide: Text.ElideMiddle
|
||||||
|
size: hifi.fontSizes.tableText
|
||||||
|
color: table.colorScheme == hifi.colorSchemes.light
|
||||||
|
? (styleData.selected ? hifi.colors.black : hifi.colors.lightGray)
|
||||||
|
: (styleData.selected ? hifi.colors.black : hifi.colors.lightGrayText)
|
||||||
|
anchors {
|
||||||
|
top: textItem.bottom
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
}
|
||||||
|
visible: styleData.selected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TableViewColumn {
|
||||||
|
role: "name"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HifiControls.VerticalSpacer {
|
HifiControls.VerticalSpacer {
|
||||||
|
|
23
interface/resources/qml/styles-uit/FiraSansRegular.qml
Normal file
23
interface/resources/qml/styles-uit/FiraSansRegular.qml
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
//
|
||||||
|
// FiraSansRegular.qml
|
||||||
|
//
|
||||||
|
// Created by David Rowe on 12 May 2016
|
||||||
|
// Copyright 2016 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
import QtQuick 2.5
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
import QtQuick.Controls.Styles 1.4
|
||||||
|
|
||||||
|
Text {
|
||||||
|
id: root
|
||||||
|
FontLoader { id: firaSansRegular; source: "../../fonts/FiraSans-Regular.ttf"; }
|
||||||
|
property real size: 32
|
||||||
|
font.pixelSize: size
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
font.family: firaSansRegular.name
|
||||||
|
}
|
|
@ -89,12 +89,16 @@ Item {
|
||||||
readonly property color transparent: "#00ffffff"
|
readonly property color transparent: "#00ffffff"
|
||||||
|
|
||||||
// Control specific colors
|
// Control specific colors
|
||||||
readonly property color tableRowLightOdd: white50
|
readonly property color tableRowLightOdd: "#eaeaea" // Equivalent to white50 over #e3e3e3 background
|
||||||
readonly property color tableRowLightEven: "#1a575757"
|
readonly property color tableRowLightEven: "#c6c6c6" // Equivavlent to "#1a575757" over #e3e3e3 background
|
||||||
readonly property color tableRowDarkOdd: "#80393939"
|
readonly property color tableRowDarkOdd: "#2e2e2e" // Equivalent to "#80393939" over #404040 background
|
||||||
readonly property color tableRowDarkEven: "#a6181818"
|
readonly property color tableRowDarkEven: "#1c1c1c" // Equivalent to "#a6181818" over #404040 background
|
||||||
readonly property color tableScrollHandle: "#707070"
|
readonly property color tableBackgroundLight: tableRowLightEven
|
||||||
readonly property color tableScrollBackground: "#323232"
|
readonly property color tableBackgroundDark: tableRowDarkEven
|
||||||
|
readonly property color tableScrollHandleLight: tableRowLightOdd
|
||||||
|
readonly property color tableScrollHandleDark: "#707070"
|
||||||
|
readonly property color tableScrollBackgroundLight: tableRowLightEven
|
||||||
|
readonly property color tableScrollBackgroundDark: "#323232"
|
||||||
readonly property color checkboxLightStart: "#ffffff"
|
readonly property color checkboxLightStart: "#ffffff"
|
||||||
readonly property color checkboxLightFinish: "#afafaf"
|
readonly property color checkboxLightFinish: "#afafaf"
|
||||||
readonly property color checkboxDarkStart: "#7d7d7d"
|
readonly property color checkboxDarkStart: "#7d7d7d"
|
||||||
|
@ -137,10 +141,10 @@ Item {
|
||||||
readonly property real textPadding: 8
|
readonly property real textPadding: 8
|
||||||
readonly property real sliderHandleSize: 18
|
readonly property real sliderHandleSize: 18
|
||||||
readonly property real sliderGrooveHeight: 8
|
readonly property real sliderGrooveHeight: 8
|
||||||
readonly property real spinnerSize: 42
|
readonly property real spinnerSize: 50
|
||||||
readonly property real tablePadding: 12
|
readonly property real tablePadding: 12
|
||||||
readonly property real tableRowHeight: largeScreen ? 26 : 23
|
readonly property real tableRowHeight: largeScreen ? 26 : 23
|
||||||
readonly property real tableHeaderHeight: 40
|
readonly property real tableHeaderHeight: 29
|
||||||
readonly property vector2d modalDialogMargin: Qt.vector2d(50, 30)
|
readonly property vector2d modalDialogMargin: Qt.vector2d(50, 30)
|
||||||
readonly property real modalDialogTitleHeight: 40
|
readonly property real modalDialogTitleHeight: 40
|
||||||
readonly property real controlLineHeight: 28 // Height of spinbox control on 1920 x 1080 monitor
|
readonly property real controlLineHeight: 28 // Height of spinbox control on 1920 x 1080 monitor
|
||||||
|
@ -157,6 +161,8 @@ Item {
|
||||||
readonly property real textFieldInput: dimensions.largeScreen ? 15 : 12
|
readonly property real textFieldInput: dimensions.largeScreen ? 15 : 12
|
||||||
readonly property real textFieldInputLabel: dimensions.largeScreen ? 13 : 9
|
readonly property real textFieldInputLabel: dimensions.largeScreen ? 13 : 9
|
||||||
readonly property real textFieldSearchIcon: dimensions.largeScreen ? 30 : 24
|
readonly property real textFieldSearchIcon: dimensions.largeScreen ? 30 : 24
|
||||||
|
readonly property real tableHeading: dimensions.largeScreen ? 12 : 10
|
||||||
|
readonly property real tableHeadingIcon: dimensions.largeScreen ? 40 : 33
|
||||||
readonly property real tableText: dimensions.largeScreen ? 15 : 12
|
readonly property real tableText: dimensions.largeScreen ? 15 : 12
|
||||||
readonly property real buttonLabel: dimensions.largeScreen ? 13 : 9
|
readonly property real buttonLabel: dimensions.largeScreen ? 13 : 9
|
||||||
readonly property real iconButton: dimensions.largeScreen ? 13 : 9
|
readonly property real iconButton: dimensions.largeScreen ? 13 : 9
|
||||||
|
|
|
@ -268,7 +268,7 @@ input[type=number]::-webkit-inner-spin-button {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font-family: hifi-glyphs;
|
font-family: hifi-glyphs;
|
||||||
font-size: 50px;
|
font-size: 46px;
|
||||||
color: #afafaf;
|
color: #afafaf;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
/*background-color: #000000;*/
|
/*background-color: #000000;*/
|
||||||
|
@ -276,17 +276,17 @@ input[type=number]::-webkit-inner-spin-button {
|
||||||
input[type=number]::-webkit-inner-spin-button:before,
|
input[type=number]::-webkit-inner-spin-button:before,
|
||||||
input[type=number]::-webkit-inner-spin-button:after {
|
input[type=number]::-webkit-inner-spin-button:after {
|
||||||
position:absolute;
|
position:absolute;
|
||||||
left: -21px;
|
left: -19px;
|
||||||
line-height: 8px;
|
line-height: 8px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
input[type=number]::-webkit-inner-spin-button:before {
|
input[type=number]::-webkit-inner-spin-button:before {
|
||||||
content: "6";
|
content: "6";
|
||||||
top: 5px;
|
top: 4px;
|
||||||
}
|
}
|
||||||
input[type=number]::-webkit-inner-spin-button:after {
|
input[type=number]::-webkit-inner-spin-button:after {
|
||||||
content: "5";
|
content: "5";
|
||||||
bottom: 6px;
|
bottom: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=number].hover-up::-webkit-inner-spin-button:before,
|
input[type=number].hover-up::-webkit-inner-spin-button:before,
|
||||||
|
@ -613,7 +613,7 @@ hr {
|
||||||
margin-right: -48px;
|
margin-right: -48px;
|
||||||
position: relative;
|
position: relative;
|
||||||
left: -12px;
|
left: -12px;
|
||||||
top: -11px;
|
top: -9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown dd {
|
.dropdown dd {
|
||||||
|
|
|
@ -211,6 +211,27 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: "Open File"
|
||||||
|
property var builder: Component {
|
||||||
|
FileDialog {
|
||||||
|
title: "Open File"
|
||||||
|
filter: "All Files (*.*)"
|
||||||
|
//filter: "HTML files (*.html);;Other(*.png)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
var fileDialog = builder.createObject(desktop);
|
||||||
|
fileDialog.canceled.connect(function(){
|
||||||
|
console.log("Cancelled")
|
||||||
|
})
|
||||||
|
fileDialog.selectedFile.connect(function(file){
|
||||||
|
console.log("Selected " + file)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
text: "Add Tab"
|
text: "Add Tab"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
|
@ -246,24 +267,7 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Button {
|
|
||||||
text: "Open File"
|
|
||||||
property var builder: Component {
|
|
||||||
FileDialog { }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
var fileDialog = builder.createObject(desktop);
|
|
||||||
fileDialog.canceled.connect(function(){
|
|
||||||
console.log("Cancelled")
|
|
||||||
})
|
|
||||||
fileDialog.selectedFile.connect(function(file){
|
|
||||||
console.log("Selected " + file)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Window {
|
Window {
|
||||||
id: blue
|
id: blue
|
||||||
|
|
Loading…
Reference in a new issue