mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 01:03:57 +02:00
commit
47f18e5166
3 changed files with 146 additions and 125 deletions
|
@ -36,7 +36,6 @@ Window {
|
|||
property var assetProxyModel: Assets.proxyModel;
|
||||
property var assetMappingsModel: Assets.mappingModel;
|
||||
property var currentDirectory;
|
||||
property alias currentFileUrl: fileUrlTextField.text;
|
||||
|
||||
Settings {
|
||||
category: "Overlay.AssetServer"
|
||||
|
@ -46,8 +45,8 @@ Window {
|
|||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
assetMappingsModel.errorGettingMappings.connect(handleGetMappingsError)
|
||||
reload()
|
||||
assetMappingsModel.errorGettingMappings.connect(handleGetMappingsError);
|
||||
reload();
|
||||
}
|
||||
|
||||
function doDeleteFile(path) {
|
||||
|
@ -241,47 +240,67 @@ Window {
|
|||
});
|
||||
}
|
||||
|
||||
function chooseClicked() {
|
||||
var browser = desktop.fileDialog({
|
||||
selectDirectory: false,
|
||||
dir: currentDirectory
|
||||
});
|
||||
browser.selectedFile.connect(function(url){
|
||||
fileUrlTextField.text = fileDialogHelper.urlToPath(url);
|
||||
currentDirectory = browser.dir;
|
||||
});
|
||||
}
|
||||
|
||||
property var uploadOpen: false;
|
||||
Timer {
|
||||
id: timer
|
||||
}
|
||||
function uploadClicked() {
|
||||
if (uploadOpen) {
|
||||
return;
|
||||
}
|
||||
uploadOpen = true;
|
||||
|
||||
var fileUrl = fileUrlTextField.text
|
||||
var shouldAddToWorld = addToWorldCheckBox.checked
|
||||
var fileUrl = "";
|
||||
|
||||
var path = assetProxyModel.data(treeView.selection.currentIndex, 0x100);
|
||||
var directory = path ? path.slice(0, path.lastIndexOf('/') + 1) : "/";
|
||||
var filename = fileUrl.slice(fileUrl.lastIndexOf('/') + 1);
|
||||
|
||||
Assets.uploadFile(fileUrl, directory + filename, function(err, path) {
|
||||
if (err) {
|
||||
console.log("Asset Browser - error uploading: ", fileUrl, " - error ", err);
|
||||
var box = errorMessageBox("There was an error uploading:\n" + fileUrl + "\n" + err);
|
||||
box.selected.connect(reload);
|
||||
} else {
|
||||
console.log("Asset Browser - finished uploading: ", fileUrl);
|
||||
|
||||
if (shouldAddToWorld) {
|
||||
addToWorld("atp:" + path);
|
||||
}
|
||||
|
||||
reload();
|
||||
}
|
||||
var browser = desktop.fileDialog({
|
||||
selectDirectory: false,
|
||||
dir: currentDirectory
|
||||
});
|
||||
browser.canceled.connect(function() {
|
||||
uploadOpen = false;
|
||||
});
|
||||
browser.selectedFile.connect(function(url){
|
||||
var fileUrl = fileDialogHelper.urlToPath(url);
|
||||
currentDirectory = browser.dir;
|
||||
|
||||
var path = assetProxyModel.data(treeView.selection.currentIndex, 0x100);
|
||||
var directory = path ? path.slice(0, path.lastIndexOf('/') + 1) : "/";
|
||||
var filename = fileUrl.slice(fileUrl.lastIndexOf('/') + 1);
|
||||
|
||||
Assets.uploadFile(fileUrl, directory + filename,
|
||||
function() {
|
||||
// Upload started
|
||||
uploadSpinner.visible = true;
|
||||
uploadButton.enabled = false;
|
||||
uploadProgressLabel.text = "In progress...";
|
||||
},
|
||||
function(err, path) {
|
||||
print(err, path);
|
||||
if (!err) {
|
||||
uploadProgressLabel.text = "Upload Complete";
|
||||
timer.interval = 1000;
|
||||
timer.repeat = false;
|
||||
timer.triggered.connect(function() {
|
||||
uploadSpinner.visible = false;
|
||||
uploadButton.enabled = true;
|
||||
uploadOpen = false;
|
||||
});
|
||||
timer.start();
|
||||
console.log("Asset Browser - finished uploading: ", fileUrl);
|
||||
reload();
|
||||
} else {
|
||||
if (err > 0) {
|
||||
console.log("Asset Browser - error uploading: ", fileUrl, " - error ", err);
|
||||
var box = errorMessageBox("There was an error uploading:\n" + fileUrl + "\n" + Assets.getErrorString(err));
|
||||
box.selected.connect(reload);
|
||||
}
|
||||
uploadSpinner.visible = false;
|
||||
uploadButton.enabled = true;
|
||||
uploadOpen = false;
|
||||
}
|
||||
})
|
||||
});
|
||||
uploadOpen = false;
|
||||
}
|
||||
|
||||
function errorMessageBox(message) {
|
||||
|
@ -297,8 +316,9 @@ Window {
|
|||
return treeView.selection.hasSelection()
|
||||
}
|
||||
|
||||
Column {
|
||||
Item {
|
||||
width: pane.contentWidth
|
||||
height: pane.height
|
||||
|
||||
HifiControls.ContentSection {
|
||||
id: assetDirectory
|
||||
|
@ -386,96 +406,52 @@ Window {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.Tree {
|
||||
id: treeView
|
||||
height: 400
|
||||
treeModel: assetProxyModel
|
||||
colorScheme: root.colorScheme
|
||||
canEdit: true
|
||||
HifiControls.Tree {
|
||||
id: treeView
|
||||
anchors.top: assetDirectory.bottom
|
||||
anchors.bottom: uploadSection.top
|
||||
anchors.margins: 12
|
||||
anchors.bottomMargin: 0
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
treeModel: assetProxyModel
|
||||
canEdit: true
|
||||
colorScheme: root.colorScheme
|
||||
|
||||
modifyEl: renameEl
|
||||
modifyEl: renameEl
|
||||
|
||||
MouseArea {
|
||||
propagateComposedEvents: true
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.RightButton
|
||||
onClicked: {
|
||||
var index = treeView.indexAt(mouse.x, mouse.y);
|
||||
MouseArea {
|
||||
propagateComposedEvents: true
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.RightButton
|
||||
onClicked: {
|
||||
var index = treeView.indexAt(mouse.x, mouse.y);
|
||||
|
||||
treeView.selection.setCurrentIndex(index, 0x0002);
|
||||
treeView.selection.setCurrentIndex(index, 0x0002);
|
||||
|
||||
contextMenu.currentIndex = index;
|
||||
contextMenu.popup();
|
||||
}
|
||||
contextMenu.currentIndex = index;
|
||||
contextMenu.popup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.ContentSection {
|
||||
id: uploadSection
|
||||
name: ""
|
||||
name: "Upload A File"
|
||||
spacing: hifi.dimensions.contentSpacing.y
|
||||
|
||||
HifiControls.TextField {
|
||||
id: fileUrlTextField
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: chooseButton.width + hifi.dimensions.contentSpacing.x
|
||||
|
||||
label: "Upload File"
|
||||
placeholderText: "Paste URL or choose file"
|
||||
colorScheme: root.colorScheme
|
||||
}
|
||||
anchors.bottom: parent.bottom
|
||||
height: 130
|
||||
|
||||
Item {
|
||||
// Take the chooseButton out of the column flow.
|
||||
id: chooseButtonContainer
|
||||
anchors.top: fileUrlTextField.top
|
||||
anchors.right: parent.right
|
||||
|
||||
HifiControls.Button {
|
||||
id: chooseButton
|
||||
anchors.right: parent.right
|
||||
|
||||
text: "Choose"
|
||||
color: hifi.buttons.white
|
||||
colorScheme: root.colorScheme
|
||||
enabled: true
|
||||
|
||||
width: 100
|
||||
|
||||
onClicked: root.chooseClicked()
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.CheckBox {
|
||||
id: addToWorldCheckBox
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: uploadButton.width + hifi.dimensions.contentSpacing.x
|
||||
|
||||
text: "Add to world on upload"
|
||||
|
||||
opacity: canAddToWorld(fileUrlTextField.text) ? 1 : 0
|
||||
|
||||
checked: false
|
||||
}
|
||||
|
||||
Item {
|
||||
// Take the uploadButton out of the column flow.
|
||||
id: uploadButtonContainer
|
||||
anchors.top: addToWorldCheckBox.top
|
||||
anchors.right: parent.right
|
||||
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
HifiControls.Button {
|
||||
id: uploadButton
|
||||
anchors.right: parent.right
|
||||
|
||||
text: "Upload"
|
||||
text: "Choose File"
|
||||
color: hifi.buttons.blue
|
||||
colorScheme: root.colorScheme
|
||||
height: 30
|
||||
|
@ -499,9 +475,44 @@ Window {
|
|||
onTriggered: uploadClicked();
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: uploadSpinner
|
||||
visible: false
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
width: 40
|
||||
height: 32
|
||||
|
||||
Image {
|
||||
id: image
|
||||
width: 24
|
||||
height: 24
|
||||
source: "../images/Loading-Outer-Ring.png"
|
||||
RotationAnimation on rotation {
|
||||
loops: Animation.Infinite
|
||||
from: 0
|
||||
to: 360
|
||||
duration: 2000
|
||||
}
|
||||
}
|
||||
Image {
|
||||
width: 24
|
||||
height: 24
|
||||
source: "../images/Loading-Inner-H.png"
|
||||
}
|
||||
HifiControls.Label {
|
||||
id: uploadProgressLabel
|
||||
anchors.left: image.right
|
||||
anchors.leftMargin: 10
|
||||
anchors.verticalCenter: image.verticalCenter
|
||||
text: "In progress..."
|
||||
colorScheme: root.colorScheme
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
HifiControls.VerticalSpacer {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,11 +59,16 @@ void AssetMappingsScriptingInterface::getMapping(QString path, QJSValue callback
|
|||
request->start();
|
||||
}
|
||||
|
||||
void AssetMappingsScriptingInterface::uploadFile(QString path, QString mapping, QJSValue callback) {
|
||||
void AssetMappingsScriptingInterface::uploadFile(QString path, QString mapping, QJSValue startedCallback, QJSValue completedCallback) {
|
||||
static const QString helpText =
|
||||
"Upload your asset to a specific folder by entering the full path. Specifying "
|
||||
"a new folder name will automatically create that folder for you.";
|
||||
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
auto result = offscreenUi->inputDialog(OffscreenUi::ICON_NONE, "Enter asset path:", "", mapping);
|
||||
auto result = offscreenUi->inputDialog(OffscreenUi::ICON_INFORMATION, "Specify Asset Path", helpText, mapping);
|
||||
|
||||
if (!result.isValid()) {
|
||||
completedCallback.call({ -1 });
|
||||
return;
|
||||
}
|
||||
mapping = result.toString();
|
||||
|
@ -79,19 +84,22 @@ void AssetMappingsScriptingInterface::uploadFile(QString path, QString mapping,
|
|||
auto button = offscreenUi->messageBox(OffscreenUi::ICON_QUESTION, "Overwrite File", message,
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||
if (button == QMessageBox::No) {
|
||||
completedCallback.call({ -1 });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
startedCallback.call();
|
||||
|
||||
auto upload = DependencyManager::get<AssetClient>()->createUpload(path);
|
||||
QObject::connect(upload, &AssetUpload::finished, this, [=](AssetUpload* upload, const QString& hash) mutable {
|
||||
if (upload->getError() != AssetUpload::NoError) {
|
||||
if (callback.isCallable()) {
|
||||
if (completedCallback.isCallable()) {
|
||||
QJSValueList args { upload->getErrorString() };
|
||||
callback.call(args);
|
||||
completedCallback.call(args);
|
||||
}
|
||||
} else {
|
||||
setMapping(mapping, hash, callback);
|
||||
setMapping(mapping, hash, completedCallback);
|
||||
}
|
||||
|
||||
upload->deleteLater();
|
||||
|
|
|
@ -20,21 +20,23 @@
|
|||
#include <AssetClient.h>
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
class AssetMappingModel : public QStandardItemModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Q_INVOKABLE void refresh();
|
||||
|
||||
bool isKnownMapping(QString path) const { return _pathToItemMap.contains(path); }
|
||||
bool isKnownFolder(QString path) const;
|
||||
|
||||
signals:
|
||||
void errorGettingMappings(QString errorString);
|
||||
class AssetMappingModel : public QStandardItemModel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
Q_INVOKABLE void refresh();
|
||||
|
||||
private:
|
||||
QHash<QString, QStandardItem*> _pathToItemMap;
|
||||
};
|
||||
bool isKnownMapping(QString path) const { return _pathToItemMap.contains(path); }
|
||||
bool isKnownFolder(QString path) const;
|
||||
|
||||
void errorGettingMappings(QString errorString);
|
||||
|
||||
private:
|
||||
QHash<QString, QStandardItem*> _pathToItemMap;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(AssetMappingModel*);
|
||||
|
||||
class AssetMappingsScriptingInterface : public QObject {
|
||||
Q_OBJECT
|
||||
|
@ -51,7 +53,7 @@ public:
|
|||
|
||||
Q_INVOKABLE void setMapping(QString path, QString hash, QJSValue callback = QJSValue());
|
||||
Q_INVOKABLE void getMapping(QString path, QJSValue callback = QJSValue());
|
||||
Q_INVOKABLE void uploadFile(QString path, QString mapping, QJSValue callback = QJSValue());
|
||||
Q_INVOKABLE void uploadFile(QString path, QString mapping, QJSValue startedCallback = QJSValue(), QJSValue completedCallback = QJSValue());
|
||||
Q_INVOKABLE void deleteMappings(QStringList paths, QJSValue callback);
|
||||
Q_INVOKABLE void deleteMapping(QString path, QJSValue callback) { deleteMappings(QStringList(path), callback = QJSValue()); }
|
||||
Q_INVOKABLE void getAllMappings(QJSValue callback = QJSValue());
|
||||
|
|
Loading…
Reference in a new issue