Merge pull request #7873 from ctrlaltdavid/20917

restyle file browser
This commit is contained in:
Brad Hefta-Gaub 2016-05-24 08:40:38 -07:00
commit 49ded9c4df
16 changed files with 678 additions and 318 deletions

Binary file not shown.

View file

@ -21,7 +21,6 @@ import "../hifi/models"
TableView {
id: tableView
// property var tableModel: ListModel { }
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
@ -46,7 +45,7 @@ TableView {
RalewayRegular {
id: textHeader
size: hifi.fontSizes.tableText
size: hifi.fontSizes.tableHeading
color: hifi.colors.lightGrayText
text: styleData.value
anchors {
@ -87,7 +86,7 @@ TableView {
bottomMargin: 3 // ""
}
radius: 3
color: hifi.colors.tableScrollHandle
color: hifi.colors.tableScrollHandleDark
}
}
@ -107,7 +106,7 @@ TableView {
margins: 1 // Shrink
}
radius: 4
color: hifi.colors.tableScrollBackground
color: hifi.colors.tableScrollBackgroundDark
}
}

View file

@ -91,7 +91,7 @@ FocusScope {
HiFiGlyphs {
anchors {
top: parent.top
topMargin: -8
topMargin: -11
horizontalCenter: parent.horizontalCenter
}
size: hifi.dimensions.spinnerSize

View file

@ -17,8 +17,9 @@ import "../styles-uit"
Original.Button {
property int color: 0
property int colorScheme: hifi.colorShemes.light
property int colorScheme: hifi.colorSchemes.light
property string glyph: ""
property int size: 32
width: 120
height: 28
@ -65,7 +66,13 @@ Original.Button {
: hifi.buttons.disabledTextColor[control.colorScheme]
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
anchors {
// Tweak horizontal alignment so that it looks right.
left: parent.left
leftMargin: -0.5
}
text: control.glyph
size: control.size
}
}
}

View file

@ -56,7 +56,7 @@ SpinBox {
incrementControl: HiFiGlyphs {
id: incrementButton
text: hifi.glyphs.caratUp
x: 6
x: 10
y: 1
size: hifi.dimensions.spinnerSize
color: styleData.upPressed ? (isLightColorScheme ? hifi.colors.black : hifi.colors.white) : hifi.colors.gray
@ -64,8 +64,8 @@ SpinBox {
decrementControl: HiFiGlyphs {
text: hifi.glyphs.caratDn
x: 6
y: -3
x: 10
y: -1
size: hifi.dimensions.spinnerSize
color: styleData.downPressed ? (isLightColorScheme ? hifi.colors.black : hifi.colors.white) : hifi.colors.gray
}

View file

@ -17,20 +17,68 @@ import "../styles-uit"
TableView {
id: tableView
property var tableModel: ListModel { }
property int colorScheme: hifi.colorSchemes.light
readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light
property bool expandSelectedRow: false
model: tableModel
TableViewColumn {
role: "name"
}
anchors { left: parent.left; right: parent.right }
model: ListModel { }
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.
frameVisible: false
@ -50,8 +98,10 @@ TableView {
style: TableViewStyle {
// Needed in order for rows to keep displaying rows after end of table entries.
backgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightEven : hifi.colors.tableRowDarkEven
alternateBackgroundColor: parent.isLightColorScheme ? hifi.colors.tableRowLightOdd : hifi.colors.tableRowDarkOdd
backgroundColor: tableView.isLightColorScheme ? hifi.colors.tableBackgroundLight : hifi.colors.tableBackgroundDark
alternateBackgroundColor: tableView.isLightColorScheme ? hifi.colors.tableRowLightOdd : hifi.colors.tableRowDarkOdd
padding.top: headerVisible ? hifi.dimensions.tableHeaderHeight: 0
handle: Item {
id: scrollbarHandle
@ -59,33 +109,38 @@ TableView {
Rectangle {
anchors {
fill: parent
topMargin: 3
bottomMargin: 3 // ""
leftMargin: 2 // Move it right
rightMargin: -2 // ""
topMargin: 3 // Shrink vertically
bottomMargin: 3 // ""
}
radius: 3
color: hifi.colors.tableScrollHandle
color: isLightColorScheme ? hifi.colors.tableScrollHandleLight : hifi.colors.tableScrollHandleDark
}
}
scrollBarBackground: Item {
implicitWidth: 10
implicitWidth: 9
Rectangle {
anchors {
fill: parent
margins: -1 // Expand
topMargin: headerVisible ? -hifi.dimensions.tableHeaderHeight : -1
}
color: hifi.colors.baseGrayHighlight
}
color: isLightColorScheme ? hifi.colors.tableBackgroundLight : hifi.colors.tableBackgroundDark
Rectangle {
anchors {
fill: parent
margins: 1 // Shrink
Rectangle {
// Extend header bottom border
anchors {
top: parent.top
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 {
height: (styleData.selected ? 1.8 : 1) * hifi.dimensions.tableRowHeight
height: (styleData.selected && expandSelectedRow ? 1.8 : 1) * hifi.dimensions.tableRowHeight
color: styleData.selected
? hifi.colors.primaryHighlight
: tableView.isLightColorScheme
? (styleData.alternate ? hifi.colors.tableRowLightEven : hifi.colors.tableRowLightOdd)
: (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
}
}
}

View file

@ -1,5 +1,5 @@
//
// Table.qml
// Tree.qml
//
// Created by David Rowe on 17 Feb 2016
// Copyright 2016 High Fidelity, Inc.
@ -85,27 +85,18 @@ TreeView {
bottomMargin: 3 // ""
}
radius: 3
color: hifi.colors.tableScrollHandle
color: hifi.colors.tableScrollHandleDark
}
}
scrollBarBackground: Item {
implicitWidth: 10
implicitWidth: 9
Rectangle {
anchors {
fill: parent
margins: -1 // Expand
}
color: hifi.colors.baseGrayHighlight
}
Rectangle {
anchors {
fill: parent
margins: 1 // Shrink
}
radius: 4
color: hifi.colors.tableScrollBackground
color: hifi.colors.tableBackgroundDark
}
}

View file

@ -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 Qt.labs.folderlistmodel 2.1
import Qt.labs.settings 1.0
@ -6,17 +16,20 @@ import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.2 as OriginalDialogs
import ".."
import "../windows"
import "../styles"
import "../controls" as VrControls
import "../controls-uit"
import "../styles-uit"
import "../windows-uit"
import "fileDialog"
//FIXME implement shortcuts for favorite location
ModalWindow {
id: root
resizable: true
width: 640
height: 480
//resizable: true
implicitWidth: 640
implicitHeight: 480
HifiConstants { id: hifi }
Settings {
category: "FileDialog"
@ -30,12 +43,14 @@ ModalWindow {
// Set from OffscreenUi::getOpenFile()
property alias caption: root.title;
// Set from OffscreenUi::getOpenFile()
property alias dir: model.folder;
property alias dir: fileTableModel.folder;
// Set from OffscreenUi::getOpenFile()
property alias filter: selectionType.filtersString;
// Set from OffscreenUi::getOpenFile()
property int options; // <-- FIXME unused
property string iconText: text !== "" ? hifi.glyphs.scriptUpload : ""
property int iconSize: 40
property bool selectDirectory: false;
property bool showHidden: false;
@ -46,77 +61,120 @@ ModalWindow {
property alias model: fileTableView.model
property var drives: helper.drives()
property int titleWidth: 0
signal selectedFile(var file);
signal canceled();
Component.onCompleted: {
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 {
anchors.fill: parent
color: "white"
Item {
clip: true
width: pane.width
height: pane.height
anchors.margins: 0
Row {
id: navControls
anchors { left: parent.left; top: parent.top; margins: 8 }
spacing: 8
// FIXME implement back button
//VrControls.ButtonAwesome {
// id: backButton
// text: "\uf0a8"
// size: currentDirectory.height
// enabled: d.backStack.length != 0
// MouseArea { anchors.fill: parent; onClicked: d.navigateBack() }
//}
VrControls.ButtonAwesome {
anchors {
top: parent.top
topMargin: hifi.dimensions.contentMargin.y
left: parent.left
}
spacing: hifi.dimensions.contentSpacing.x
GlyphButton {
id: upButton
enabled: model.parentFolder && model.parentFolder !== ""
text: "\uf0aa"
size: 32
glyph: hifi.glyphs.levelUp
width: height
size: 30
enabled: fileTableModel.parentFolder && fileTableModel.parentFolder !== ""
onClicked: d.navigateUp();
}
VrControls.ButtonAwesome {
GlyphButton {
id: homeButton
property var destination: helper.home();
glyph: hifi.glyphs.home
size: 28
width: height
enabled: d.homeDestination ? true : false
text: "\uf015"
size: 32
onClicked: d.navigateHome();
}
VrControls.ComboBox {
id: drivesSelector
width: 48
height: homeButton.height
model: drives
visible: drives.length > 1
currentIndex: 0
}
}
TextField {
id: currentDirectory
height: homeButton.height
style: TextFieldStyle { renderType: Text.QtRendering }
anchors { left: navControls.right; right: parent.right; top: parent.top; margins: 8 }
property var lastValidFolder: helper.urlToPath(model.folder)
onLastValidFolderChanged: text = lastValidFolder;
verticalAlignment: Text.AlignVCenter
font.pointSize: 14
font.bold: true
ComboBox {
id: pathSelector
anchors {
top: parent.top
topMargin: hifi.dimensions.contentMargin.y
left: navControls.right
leftMargin: hifi.dimensions.contentSpacing.x
right: parent.right
}
// FIXME add support auto-completion
onAccepted: {
if (!helper.validFolder(text)) {
text = lastValidFolder;
return
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;
}
}
onLastValidFolderChanged: {
var folder = d.capitalizeDrive(lastValidFolder);
calculatePathChoices(folder);
}
onCurrentTextChanged: {
var folder = currentText;
if (/^[a-zA-z]:$/.test(folder)) {
folder = "file:///" + folder + "/";
} else if (folder === "This PC") {
folder = "file:///";
} else {
folder = helper.pathToUrl(folder);
}
if (helper.urlToPath(folder).toLowerCase() !== helper.urlToPath(fileTableModel.folder).toLowerCase()) {
fileTableModel.folder = folder;
}
model.folder = helper.pathToUrl(text);
}
}
@ -127,67 +185,323 @@ ModalWindow {
property bool currentSelectionIsFolder;
property var backStack: []
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();
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() {
var row = fileTableView.currentRow;
if (row === -1 && root.selectDirectory) {
currentSelectionUrl = fileTableView.model.folder;
currentSelectionIsFolder = true;
if (row === -1) {
return;
}
currentSelectionUrl = fileTableView.model.get(row, "fileURL");
currentSelectionUrl = helper.pathToUrl(fileTableView.model.get(row).filePath);
currentSelectionIsFolder = fileTableView.model.isFolder(row);
if (root.selectDirectory || !currentSelectionIsFolder) {
currentSelection.text = helper.urlToPath(currentSelectionUrl);
currentSelection.text = capitalizeDrive(helper.urlToPath(currentSelectionUrl));
} else {
currentSelection.text = ""
currentSelection.text = "";
}
}
function navigateUp() {
if (model.parentFolder && model.parentFolder !== "") {
model.folder = model.parentFolder
if (fileTableModel.parentFolder && fileTableModel.parentFolder !== "") {
fileTableModel.folder = fileTableModel.parentFolder;
return true;
}
}
function navigateHome() {
model.folder = homeDestination;
fileTableModel.folder = homeDestination;
return true;
}
}
FileTableView {
FolderListModel {
id: folderListModel
nameFilters: selectionType.currentFilter
showDirsFirst: true
showDotAndDotDot: false
showFiles: !root.selectDirectory
Component.onCompleted: {
showFiles = !root.selectDirectory
}
onFolderChanged: {
fileTableModel.update(); // Update once the data from the folder change is available.
}
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
anchors { left: parent.left; right: parent.right; top: currentDirectory.bottom; bottom: currentSelection.top; margins: 8 }
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();
model: FolderListModel {
id: model
nameFilters: selectionType.currentFilter
showDirsFirst: true
showDotAndDotDot: false
showFiles: !root.selectDirectory
// For some reason, declaring these bindings directly in the targets doesn't
// work for setting the initial state
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
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)
}
onFolderChanged: {
fileTableView.selection.clear();
fileTableView.selection.select(0);
fileTableView.currentRow = 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) {
currentRow = row;
navigateToCurrentRow();
@ -196,9 +510,9 @@ ModalWindow {
function navigateToCurrentRow() {
var row = fileTableView.currentRow
var isFolder = model.isFolder(row);
var file = model.get(row, "fileURL");
var file = model.get(row).filePath;
if (isFolder) {
fileTableView.model.folder = file
fileTableView.model.folder = helper.pathToUrl(file);
} else {
okAction.trigger();
}
@ -213,7 +527,7 @@ ModalWindow {
var newPrefix = prefix + event.text.toLowerCase();
var matchedIndex = -1;
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)) {
matchedIndex = i;
break;
@ -254,14 +568,19 @@ ModalWindow {
}
break;
}
}
}
TextField {
id: currentSelection
style: TextFieldStyle { renderType: Text.QtRendering }
anchors { right: root.selectDirectory ? parent.right : selectionType.left; rightMargin: 8; left: parent.left; leftMargin: 8; top: selectionType.top }
label: "Path:"
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
activeFocusOnTab: !readOnly
onActiveFocusChanged: if (activeFocus) { selectAll(); }
@ -270,27 +589,34 @@ ModalWindow {
FileTypeSelection {
id: selectionType
anchors { bottom: buttonRow.top; bottomMargin: 8; right: parent.right; rightMargin: 8; left: buttonRow.left }
visible: !selectDirectory
anchors {
top: currentSelection.top
left: buttonRow.left
right: parent.right
}
visible: !selectDirectory && filtersCount > 1
KeyNavigation.left: fileTableView
KeyNavigation.right: openButton
}
Row {
id: buttonRow
anchors.right: parent.right
anchors.rightMargin: 8
anchors.bottom: parent.bottom
anchors.bottomMargin: 8
spacing: 8
anchors {
right: parent.right
bottom: parent.bottom
}
spacing: hifi.dimensions.contentSpacing.y
Button {
id: openButton
color: hifi.buttons.blue
action: okAction
Keys.onReturnPressed: okAction.trigger()
KeyNavigation.up: selectionType
KeyNavigation.left: selectionType
KeyNavigation.right: cancelButton
}
Button {
id: cancelButton
action: cancelAction
@ -385,5 +711,3 @@ ModalWindow {
}
}
}

View file

@ -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
}
}

View file

@ -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 "../../controls" as VrControls
import "../../controls-uit"
VrControls.ComboBox {
ComboBox {
id: root
property string filtersString: "All Files (*.*)";
property var currentFilter: [ "*.*" ];
property int filtersCount: filtersString.split(';;').length
// Per http://doc.qt.io/qt-5/qfiledialog.html#getOpenFileName the string can contain
// multiple filters separated by semicolons

View file

@ -118,11 +118,89 @@ Window {
}
HifiControls.Table {
tableModel: runningScriptsModel
model: runningScriptsModel
id: table
height: 185
colorScheme: hifi.colorSchemes.dark
anchors.left: parent.left
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 {

View 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
}

View file

@ -89,12 +89,16 @@ Item {
readonly property color transparent: "#00ffffff"
// Control specific colors
readonly property color tableRowLightOdd: white50
readonly property color tableRowLightEven: "#1a575757"
readonly property color tableRowDarkOdd: "#80393939"
readonly property color tableRowDarkEven: "#a6181818"
readonly property color tableScrollHandle: "#707070"
readonly property color tableScrollBackground: "#323232"
readonly property color tableRowLightOdd: "#eaeaea" // Equivalent to white50 over #e3e3e3 background
readonly property color tableRowLightEven: "#c6c6c6" // Equivavlent to "#1a575757" over #e3e3e3 background
readonly property color tableRowDarkOdd: "#2e2e2e" // Equivalent to "#80393939" over #404040 background
readonly property color tableRowDarkEven: "#1c1c1c" // Equivalent to "#a6181818" over #404040 background
readonly property color tableBackgroundLight: tableRowLightEven
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 checkboxLightFinish: "#afafaf"
readonly property color checkboxDarkStart: "#7d7d7d"
@ -137,10 +141,10 @@ Item {
readonly property real textPadding: 8
readonly property real sliderHandleSize: 18
readonly property real sliderGrooveHeight: 8
readonly property real spinnerSize: 42
readonly property real spinnerSize: 50
readonly property real tablePadding: 12
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 real modalDialogTitleHeight: 40
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 textFieldInputLabel: dimensions.largeScreen ? 13 : 9
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 buttonLabel: dimensions.largeScreen ? 13 : 9
readonly property real iconButton: dimensions.largeScreen ? 13 : 9

View file

@ -268,7 +268,7 @@ input[type=number]::-webkit-inner-spin-button {
height: 100%;
overflow: hidden;
font-family: hifi-glyphs;
font-size: 50px;
font-size: 46px;
color: #afafaf;
cursor: pointer;
/*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:after {
position:absolute;
left: -21px;
left: -19px;
line-height: 8px;
text-align: center;
}
input[type=number]::-webkit-inner-spin-button:before {
content: "6";
top: 5px;
top: 4px;
}
input[type=number]::-webkit-inner-spin-button:after {
content: "5";
bottom: 6px;
bottom: 4px;
}
input[type=number].hover-up::-webkit-inner-spin-button:before,
@ -613,7 +613,7 @@ hr {
margin-right: -48px;
position: relative;
left: -12px;
top: -11px;
top: -9px;
}
.dropdown dd {

View file

@ -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 {
text: "Add Tab"
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 {
id: blue