From fd5a5dd8f474ae419a1885e4b8ba8d6047f2814a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 8 Mar 2016 16:53:04 -0800 Subject: [PATCH 01/13] Add QJSEngine compatible AssetMappingScriptInterface --- interface/src/Application.cpp | 1 + libraries/networking/src/AssetClient.cpp | 142 +++++++++++++++++++++++ libraries/networking/src/AssetClient.h | 34 ++++++ 3 files changed, 177 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 464e77ef6f..3551d58b53 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1267,6 +1267,7 @@ void Application::initializeUi() { rootContext->setContextProperty("Quat", new Quat()); rootContext->setContextProperty("Vec3", new Vec3()); rootContext->setContextProperty("Uuid", new ScriptUUID()); + rootContext->setContextProperty("Assets", new AssetMappingsScriptingInterface(engine)); rootContext->setContextProperty("AvatarList", DependencyManager::get().data()); diff --git a/libraries/networking/src/AssetClient.cpp b/libraries/networking/src/AssetClient.cpp index 7c967e681a..42bfadee32 100644 --- a/libraries/networking/src/AssetClient.cpp +++ b/libraries/networking/src/AssetClient.cpp @@ -581,3 +581,145 @@ void AssetClient::handleNodeKilled(SharedNodePointer node) { _mappingCache.clear(); } + +void AssetScriptingInterface::uploadData(QString data, QScriptValue callback) { + QByteArray dataByteArray = data.toUtf8(); + auto upload = DependencyManager::get()->createUpload(dataByteArray); + if (!upload) { + qCWarning(asset_client) << "Error uploading file to asset server"; + return; + } + + QObject::connect(upload, &AssetUpload::finished, this, [this, callback](AssetUpload* upload, const QString& hash) mutable { + if (callback.isFunction()) { + QString url = "atp://" + hash; + QScriptValueList args { url }; + callback.call(_engine->currentContext()->thisObject(), args); + } + }); + upload->start(); +} + +AssetScriptingInterface::AssetScriptingInterface(QScriptEngine* engine) : + _engine(engine) +{ +} + +void AssetScriptingInterface::downloadData(QString urlString, QScriptValue callback) { + const QString ATP_SCHEME { "atp://" }; + + if (!urlString.startsWith(ATP_SCHEME)) { + return; + } + + // Make request to atp + auto path = urlString.right(urlString.length() - ATP_SCHEME.length()); + auto parts = path.split(".", QString::SkipEmptyParts); + auto hash = parts.length() > 0 ? parts[0] : ""; + + if (hash.length() != SHA256_HASH_HEX_LENGTH) { + return; + } + + auto assetClient = DependencyManager::get(); + auto assetRequest = assetClient->createRequest(hash); + + if (!assetRequest) { + return; + } + + _pendingRequests << assetRequest; + + connect(assetRequest, &AssetRequest::finished, this, [this, callback](AssetRequest* request) mutable { + Q_ASSERT(request->getState() == AssetRequest::Finished); + + if (request->getError() == AssetRequest::Error::NoError) { + if (callback.isFunction()) { + QString data = QString::fromUtf8(request->getData()); + QScriptValueList args { data }; + callback.call(_engine->currentContext()->thisObject(), args); + } + } + + request->deleteLater(); + _pendingRequests.remove(request); + }); + + assetRequest->start(); +} + +AssetMappingsScriptingInterface::AssetMappingsScriptingInterface(QJSEngine* engine) : + _engine(engine) +{ +} + +void AssetMappingsScriptingInterface::setMapping(QString path, QString hash, QJSValue callback) { + auto assetClient = DependencyManager::get(); + auto request = assetClient->createSetMappingRequest(path, hash); + + connect(request, &SetMappingRequest::finished, this, [this, callback](SetMappingRequest* request) mutable { + QJSValueList args { uint8_t(request->getError()) }; + + callback.call(args); + + request->deleteLater(); + + }); + + request->start(); +} + +void AssetMappingsScriptingInterface::getMapping(QString path, QJSValue callback) { + auto assetClient = DependencyManager::get(); + auto request = assetClient->createGetMappingRequest(path); + + connect(request, &GetMappingRequest::finished, this, [this, callback](GetMappingRequest* request) mutable { + QJSValueList args { uint8_t(request->getError()), request->getHash() }; + + callback.call(args); + + request->deleteLater(); + + }); + + request->start(); +} + +void AssetMappingsScriptingInterface::deleteMappings(QStringList paths, QJSValue callback) { + auto assetClient = DependencyManager::get(); + auto request = assetClient->createDeleteMappingsRequest(paths); + + connect(request, &DeleteMappingsRequest::finished, this, [this, callback](DeleteMappingsRequest* request) mutable { + QJSValueList args { uint8_t(request->getError()) }; + + callback.call(args); + + request->deleteLater(); + + }); + + request->start(); +} + +void AssetMappingsScriptingInterface::getAllMappings(QJSValue callback) { + auto assetClient = DependencyManager::get(); + auto request = assetClient->createGetAllMappingsRequest(); + + connect(request, &GetAllMappingsRequest::finished, this, [this, callback](GetAllMappingsRequest* request) mutable { + auto mappings = request->getMappings(); + auto map = callback.engine()->newObject(); + + for (auto& kv : mappings ) { + map.setProperty(kv.first, kv.second); + } + + QJSValueList args { uint8_t(request->getError()), map }; + + callback.call(args); + + request->deleteLater(); + + }); + + request->start(); +} diff --git a/libraries/networking/src/AssetClient.h b/libraries/networking/src/AssetClient.h index 87b8646be1..cec1bd3872 100644 --- a/libraries/networking/src/AssetClient.h +++ b/libraries/networking/src/AssetClient.h @@ -12,6 +12,7 @@ #ifndef hifi_AssetClient_h #define hifi_AssetClient_h +#include #include #include @@ -106,4 +107,37 @@ private: friend class RenameMappingRequest; }; + +class AssetScriptingInterface : public QObject { + Q_OBJECT +public: + AssetScriptingInterface(QScriptEngine* engine); + + Q_INVOKABLE void uploadData(QString data, QScriptValue callback); + Q_INVOKABLE void downloadData(QString url, QScriptValue downloadComplete); +// Q_INVOKABLE void setMapping(QString path, QString hash, QScriptValue callback); +// Q_INVOKABLE void getMapping(QString path, QScriptValue callback); +// Q_INVOKABLE void deleteMappings(QStringList paths, QScriptValue callback); +// Q_INVOKABLE void getAllMappings(QScriptValue callback); +protected: + QSet _pendingRequests; + QScriptEngine* _engine; +}; + + +class AssetMappingsScriptingInterface : public QObject { + Q_OBJECT +public: + AssetMappingsScriptingInterface(QJSEngine* engine); + + Q_INVOKABLE void setMapping(QString path, QString hash, QJSValue callback); + Q_INVOKABLE void getMapping(QString path, QJSValue callback); + Q_INVOKABLE void deleteMappings(QStringList paths, QJSValue callback); + Q_INVOKABLE void getAllMappings(QJSValue callback); +protected: + QSet _pendingRequests; + QJSEngine* _engine; +}; + + #endif From 38edfe0557f96c3b1282c92acebc588687f43fdd Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 8 Mar 2016 16:53:18 -0800 Subject: [PATCH 02/13] Fix GetAllMappings reading --- libraries/networking/src/AssetClient.cpp | 144 +++++++++++++++++++++++ 1 file changed, 144 insertions(+) diff --git a/libraries/networking/src/AssetClient.cpp b/libraries/networking/src/AssetClient.cpp index 42bfadee32..40838e3732 100644 --- a/libraries/networking/src/AssetClient.cpp +++ b/libraries/networking/src/AssetClient.cpp @@ -31,6 +31,150 @@ MessageID AssetClient::_currentID = 0; +void MappingRequest::start() { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "start", Qt::AutoConnection); + return; + } + doStart(); +}; + +GetMappingRequest::GetMappingRequest(const AssetPath& path) : _path(path) { +}; + +void GetMappingRequest::doStart() { + + auto assetClient = DependencyManager::get(); + + // Check cache + auto it = assetClient->_mappingCache.constFind(_path); + if (it != assetClient->_mappingCache.constEnd()) { + _hash = it.value(); + emit finished(this); + return; + } + + assetClient->getAssetMapping(_path, [this, assetClient](bool responseReceived, AssetServerError error, QSharedPointer message) { + if (!responseReceived) { + _error = NetworkError; + } else { + switch (error) { + case AssetServerError::NoError: + _error = NoError; + break; + case AssetServerError::AssetNotFound: + _error = NotFound; + break; + default: + _error = UnknownError; + break; + } + } + + if (!_error) { + _hash = message->read(SHA256_HASH_LENGTH).toHex(); + assetClient->_mappingCache[_path] = _hash; + } + emit finished(this); + }); +}; + +GetAllMappingsRequest::GetAllMappingsRequest() { +}; + +void GetAllMappingsRequest::doStart() { + auto assetClient = DependencyManager::get(); + assetClient->getAllAssetMappings([this, assetClient](bool responseReceived, AssetServerError error, QSharedPointer message) { + if (!responseReceived) { + _error = NetworkError; + } else { + switch (error) { + case AssetServerError::NoError: + _error = NoError; + break; + default: + _error = UnknownError; + break; + } + } + + + if (!error) { + int numberOfMappings; + message->readPrimitive(&numberOfMappings); + assetClient->_mappingCache.clear(); + for (auto i = 0; i < numberOfMappings; ++i) { + auto path = message->readString(); + auto hash = message->read(SHA256_HASH_LENGTH).toHex(); + _mappings[path] = hash; + assetClient->_mappingCache[path] = hash; + } + } + emit finished(this); + }); +}; + +SetMappingRequest::SetMappingRequest(const AssetPath& path, const AssetHash& hash) : _path(path), _hash(hash) { +}; + +void SetMappingRequest::doStart() { + auto assetClient = DependencyManager::get(); + assetClient->setAssetMapping(_path, _hash, [this, assetClient](bool responseReceived, AssetServerError error, QSharedPointer message) { + if (!responseReceived) { + _error = NetworkError; + } else { + switch (error) { + case AssetServerError::NoError: + _error = NoError; + break; + case AssetServerError::PermissionDenied: + _error = PermissionDenied; + break; + default: + _error = UnknownError; + break; + } + } + + if (!error) { + assetClient->_mappingCache[_path] = _hash; + } + emit finished(this); + }); +}; + +DeleteMappingsRequest::DeleteMappingsRequest(const AssetPathList& paths) : _paths(paths) { +}; + +void DeleteMappingsRequest::doStart() { + auto assetClient = DependencyManager::get(); + assetClient->deleteAssetMappings(_paths, [this, assetClient](bool responseReceived, AssetServerError error, QSharedPointer message) { + if (!responseReceived) { + _error = NetworkError; + } else { + switch (error) { + case AssetServerError::NoError: + _error = NoError; + break; + case AssetServerError::PermissionDenied: + _error = PermissionDenied; + break; + default: + _error = UnknownError; + break; + } + } + + if (!error) { + // enumerate the paths and remove them from the cache + for (auto& path : _paths) { + assetClient->_mappingCache.remove(path); + } + } + emit finished(this); + }); +}; + AssetClient::AssetClient() { setCustomDeleter([](Dependency* dependency){ From 4da4fd889ae884dca0b83b4c565f6b6306cfec4c Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Mar 2016 11:04:49 -0800 Subject: [PATCH 03/13] Add AssetMappingModel --- interface/resources/qml/AssetServer.qml | 3 +- libraries/networking/src/AssetClient.cpp | 99 +++++++++++++++++++++++- libraries/networking/src/AssetClient.h | 24 +++++- 3 files changed, 122 insertions(+), 4 deletions(-) diff --git a/interface/resources/qml/AssetServer.qml b/interface/resources/qml/AssetServer.qml index 34f6502b40..3e2dba164d 100644 --- a/interface/resources/qml/AssetServer.qml +++ b/interface/resources/qml/AssetServer.qml @@ -33,7 +33,7 @@ Window { HifiConstants { id: hifi } property var scripts: ScriptDiscoveryService; - property var scriptsModel: scripts.scriptsModelFilter + property var scriptsModel: Assets.getAssetMappingModel() property var currentDirectory; Settings { @@ -45,6 +45,7 @@ Window { function reload() { print("reload"); + scriptsModel.refresh(); } function addToWorld() { print("addToWorld"); diff --git a/libraries/networking/src/AssetClient.cpp b/libraries/networking/src/AssetClient.cpp index 40838e3732..7eb49ff418 100644 --- a/libraries/networking/src/AssetClient.cpp +++ b/libraries/networking/src/AssetClient.cpp @@ -792,8 +792,11 @@ void AssetScriptingInterface::downloadData(QString urlString, QScriptValue callb assetRequest->start(); } +static int standardItemModelMetaTypeId = qRegisterMetaType("AssetMappingModel*"); + AssetMappingsScriptingInterface::AssetMappingsScriptingInterface(QJSEngine* engine) : - _engine(engine) + _engine(engine), + _assetMappingModel(this) { } @@ -867,3 +870,97 @@ void AssetMappingsScriptingInterface::getAllMappings(QJSValue callback) { request->start(); } + +AssetMappingModel::AssetMappingModel(QObject* parent) { +} + +void AssetMappingModel::refresh() { + qDebug() << "Refreshing asset mapping model"; + auto assetClient = DependencyManager::get(); + auto request = assetClient->createGetAllMappingsRequest(); + + connect(request, &GetAllMappingsRequest::finished, this, [this](GetAllMappingsRequest* request) mutable { + qDebug() << "Got response"; + auto mappings = request->getMappings(); +// clear(); + for (auto& mapping : mappings) { + auto& path = mapping.first; + auto parts = path.split("/"); + auto length = parts.length(); + + QString prefix = parts[0]; + + QStandardItem* lastItem = nullptr; + + auto it = _pathToItemMap.find(prefix); + if (it == _pathToItemMap.end()) { + lastItem = new QStandardItem(parts[0]); + _pathToItemMap[prefix] = lastItem; + appendRow(lastItem); + } else { + lastItem = it.value(); + } + + if (length > 1) { + for (int i = 1; i < length; ++i) { + prefix += "/" + parts[i]; + + auto it = _pathToItemMap.find(prefix); + if (it == _pathToItemMap.end()) { + qDebug() << "prefix not found: " << prefix; + auto item = new QStandardItem(parts[i]); + lastItem->setChild(lastItem->rowCount(), 0, item); + lastItem = item; + _pathToItemMap[prefix] = lastItem; + } else { + lastItem = it.value(); + } + } + } + + Q_ASSERT(prefix == path); + } + }); + + request->start(); +} + + +// QModelIndex AssetMappingModel::index(int row, int column, const QModelIndex& parent) const { +// if (row < 0 || column < 0) { +// return QModelIndex(); +// } + +// if (parent.isValid()) { +// auto item = static_cast(parent.internalPointer()); +// return createIndex(row, column, ) +// } +// return createIndex(row, column, getFolderNodes( +// static_cast(getTreeNodeFromIndex(parent))).at(row)); +// } + +// QModelIndex AssetMappingModel::parent(const QModelIndex& child) const { +// AssetMappingItem* parent = (static_cast(child.internalPointer()))->getParent(); +// if (!parent) { +// return QModelIndex(); +// } +// AssetMappingItem* grandParent = parent->getParent(); +// int row = getFolderNodes(grandParent).indexOf(parent); +// return createIndex(row, 0, parent); +// } + +// QVariant AssetMappingModel::data(const QModelIndex& index, int role) const { +// TreeNodeBase* node = getTreeNodeFromIndex(index); +// if (!node) { +// return QVariant(); +// } +// return QVariant(); +// } + +// int AssetMappingModel::rowCount(const QModelIndex& parent) const { +// return 1; +// } + +// int AssetMappingModel::columnCount(const QModelIndex& parent) const { +// return 1; +// } diff --git a/libraries/networking/src/AssetClient.h b/libraries/networking/src/AssetClient.h index cec1bd3872..f48be7f962 100644 --- a/libraries/networking/src/AssetClient.h +++ b/libraries/networking/src/AssetClient.h @@ -12,6 +12,7 @@ #ifndef hifi_AssetClient_h #define hifi_AssetClient_h +#include #include #include @@ -125,11 +126,31 @@ protected: }; + class AssetMappingModel : public QStandardItemModel { + Q_OBJECT + public: + AssetMappingModel(QObject* parent = nullptr); + + Q_INVOKABLE void refresh(); + private: + QHash _pathToItemMap; + }; + + //class AssetMappingItem : public QStandardItem { + //Q_OBJECT + //public: + //AssetMappingItem(); + //}; + + class AssetMappingsScriptingInterface : public QObject { Q_OBJECT + Q_PROPERTY(AssetMappingModel* mappingModel READ getAssetMappingModel CONSTANT) public: AssetMappingsScriptingInterface(QJSEngine* engine); + Q_INVOKABLE AssetMappingModel* getAssetMappingModel() { return &_assetMappingModel; }; + Q_INVOKABLE void setMapping(QString path, QString hash, QJSValue callback); Q_INVOKABLE void getMapping(QString path, QJSValue callback); Q_INVOKABLE void deleteMappings(QStringList paths, QJSValue callback); @@ -137,7 +158,6 @@ public: protected: QSet _pendingRequests; QJSEngine* _engine; + AssetMappingModel _assetMappingModel; }; - - #endif From 64bd41c37fd11c77c25cc6d8fc06184def0a3060 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Mar 2016 11:52:24 -0800 Subject: [PATCH 04/13] Add AssetMappingItem and extra data to items --- libraries/networking/src/AssetClient.cpp | 24 +++++++++++++++++------- libraries/networking/src/AssetClient.h | 22 ++++++++++++++-------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/libraries/networking/src/AssetClient.cpp b/libraries/networking/src/AssetClient.cpp index 7eb49ff418..710c1bf4bc 100644 --- a/libraries/networking/src/AssetClient.cpp +++ b/libraries/networking/src/AssetClient.cpp @@ -871,6 +871,13 @@ void AssetMappingsScriptingInterface::getAllMappings(QJSValue callback) { request->start(); } +AssetMappingItem::AssetMappingItem(const QString& name, const QString& fullPath, bool isFolder) + : name(name), + fullPath(fullPath), + isFolder(isFolder) { + +} + AssetMappingModel::AssetMappingModel(QObject* parent) { } @@ -880,9 +887,7 @@ void AssetMappingModel::refresh() { auto request = assetClient->createGetAllMappingsRequest(); connect(request, &GetAllMappingsRequest::finished, this, [this](GetAllMappingsRequest* request) mutable { - qDebug() << "Got response"; auto mappings = request->getMappings(); -// clear(); for (auto& mapping : mappings) { auto& path = mapping.first; auto parts = path.split("/"); @@ -895,6 +900,8 @@ void AssetMappingModel::refresh() { auto it = _pathToItemMap.find(prefix); if (it == _pathToItemMap.end()) { lastItem = new QStandardItem(parts[0]); + lastItem->setData(parts[0], Qt::UserRole + 1); + lastItem->setData(prefix, Qt::UserRole + 2); _pathToItemMap[prefix] = lastItem; appendRow(lastItem); } else { @@ -909,6 +916,8 @@ void AssetMappingModel::refresh() { if (it == _pathToItemMap.end()) { qDebug() << "prefix not found: " << prefix; auto item = new QStandardItem(parts[i]); + item->setData(parts[i], Qt::UserRole + 1); + item->setData(prefix, Qt::UserRole + 2); lastItem->setChild(lastItem->rowCount(), 0, item); lastItem = item; _pathToItemMap[prefix] = lastItem; @@ -925,7 +934,6 @@ void AssetMappingModel::refresh() { request->start(); } - // QModelIndex AssetMappingModel::index(int row, int column, const QModelIndex& parent) const { // if (row < 0 || column < 0) { // return QModelIndex(); @@ -950,13 +958,15 @@ void AssetMappingModel::refresh() { // } // QVariant AssetMappingModel::data(const QModelIndex& index, int role) const { -// TreeNodeBase* node = getTreeNodeFromIndex(index); -// if (!node) { -// return QVariant(); +// if (index.isValid()) { +// AssetMappingItem* item = (static_cast(index.internalPointer())); +// if (item) { +// return item->name; +// } // } // return QVariant(); // } - +// // int AssetMappingModel::rowCount(const QModelIndex& parent) const { // return 1; // } diff --git a/libraries/networking/src/AssetClient.h b/libraries/networking/src/AssetClient.h index f48be7f962..08fcb099c4 100644 --- a/libraries/networking/src/AssetClient.h +++ b/libraries/networking/src/AssetClient.h @@ -126,23 +126,29 @@ protected: }; + class AssetMappingItem : public QStandardItem { + public: + AssetMappingItem(const QString& name, const QString& fullPath, bool isFolder); + + QString name; + QString fullPath; + bool isFolder; + }; + + class AssetMappingModel : public QStandardItemModel { Q_OBJECT public: AssetMappingModel(QObject* parent = nullptr); + QVariant AssetMappingModel::data(const QModelIndex& index, int role) const; + Q_INVOKABLE void refresh(); + private: - QHash _pathToItemMap; + QHash _pathToItemMap; }; - //class AssetMappingItem : public QStandardItem { - //Q_OBJECT - //public: - //AssetMappingItem(); - //}; - - class AssetMappingsScriptingInterface : public QObject { Q_OBJECT Q_PROPERTY(AssetMappingModel* mappingModel READ getAssetMappingModel CONSTANT) From f5497aa1e7d0ed7d281cc4bb11008b0ca41f2450 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Mar 2016 13:55:33 -0800 Subject: [PATCH 05/13] Add new AssetMappingsScriptingInterface and add mappings model --- interface/resources/qml/AssetServer.qml | 5 + interface/src/Application.cpp | 8 +- libraries/networking/src/AssetClient.cpp | 393 ------------------ libraries/networking/src/AssetClient.h | 58 --- libraries/networking/src/MappingRequest.cpp | 12 +- .../src/AssetMappingsScriptingInterface.cpp | 218 ++++++++++ .../src/AssetMappingsScriptingInterface.h | 64 +++ .../src/AssetScriptingInterface.cpp | 87 ---- .../src/AssetScriptingInterface.h | 5 - 9 files changed, 298 insertions(+), 552 deletions(-) create mode 100644 libraries/script-engine/src/AssetMappingsScriptingInterface.cpp create mode 100644 libraries/script-engine/src/AssetMappingsScriptingInterface.h diff --git a/interface/resources/qml/AssetServer.qml b/interface/resources/qml/AssetServer.qml index 3e2dba164d..d773d6f86a 100644 --- a/interface/resources/qml/AssetServer.qml +++ b/interface/resources/qml/AssetServer.qml @@ -72,6 +72,7 @@ Window { } function deleteFile() { var path = scriptsModel.data(treeView.currentIndex, 0x100); + print(path); if (!path) { return; } @@ -89,6 +90,10 @@ Window { if (button === OriginalDialogs.StandardButton.Yes) { console.log("Deleting " + path); + Assets.deleteMappings([path], function(err) { + print("Finished deleting path: ", path, err); + reload(); + }); } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3551d58b53..abeff8ade6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -66,6 +66,7 @@ #include #include #include +#include #include #include #include @@ -413,6 +414,7 @@ bool setupEssentials(int& argc, char** argv) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); DependencyManager::set(); DependencyManager::set(true, qApp, qApp); DependencyManager::set(); @@ -1267,7 +1269,7 @@ void Application::initializeUi() { rootContext->setContextProperty("Quat", new Quat()); rootContext->setContextProperty("Vec3", new Vec3()); rootContext->setContextProperty("Uuid", new ScriptUUID()); - rootContext->setContextProperty("Assets", new AssetMappingsScriptingInterface(engine)); + rootContext->setContextProperty("Assets", DependencyManager::get().data()); rootContext->setContextProperty("AvatarList", DependencyManager::get().data()); @@ -4288,8 +4290,8 @@ bool Application::askToSetAvatarUrl(const QString& url) { case FSTReader::HEAD_AND_BODY_MODEL: ok = QMessageBox::Ok == OffscreenUi::question("Set Avatar", - "Would you like to use '" + modelName + "' for your avatar?", - QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok); + "Would you like to use '" + modelName + "' for your avatar?", + QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok); break; default: diff --git a/libraries/networking/src/AssetClient.cpp b/libraries/networking/src/AssetClient.cpp index 710c1bf4bc..7c967e681a 100644 --- a/libraries/networking/src/AssetClient.cpp +++ b/libraries/networking/src/AssetClient.cpp @@ -31,150 +31,6 @@ MessageID AssetClient::_currentID = 0; -void MappingRequest::start() { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "start", Qt::AutoConnection); - return; - } - doStart(); -}; - -GetMappingRequest::GetMappingRequest(const AssetPath& path) : _path(path) { -}; - -void GetMappingRequest::doStart() { - - auto assetClient = DependencyManager::get(); - - // Check cache - auto it = assetClient->_mappingCache.constFind(_path); - if (it != assetClient->_mappingCache.constEnd()) { - _hash = it.value(); - emit finished(this); - return; - } - - assetClient->getAssetMapping(_path, [this, assetClient](bool responseReceived, AssetServerError error, QSharedPointer message) { - if (!responseReceived) { - _error = NetworkError; - } else { - switch (error) { - case AssetServerError::NoError: - _error = NoError; - break; - case AssetServerError::AssetNotFound: - _error = NotFound; - break; - default: - _error = UnknownError; - break; - } - } - - if (!_error) { - _hash = message->read(SHA256_HASH_LENGTH).toHex(); - assetClient->_mappingCache[_path] = _hash; - } - emit finished(this); - }); -}; - -GetAllMappingsRequest::GetAllMappingsRequest() { -}; - -void GetAllMappingsRequest::doStart() { - auto assetClient = DependencyManager::get(); - assetClient->getAllAssetMappings([this, assetClient](bool responseReceived, AssetServerError error, QSharedPointer message) { - if (!responseReceived) { - _error = NetworkError; - } else { - switch (error) { - case AssetServerError::NoError: - _error = NoError; - break; - default: - _error = UnknownError; - break; - } - } - - - if (!error) { - int numberOfMappings; - message->readPrimitive(&numberOfMappings); - assetClient->_mappingCache.clear(); - for (auto i = 0; i < numberOfMappings; ++i) { - auto path = message->readString(); - auto hash = message->read(SHA256_HASH_LENGTH).toHex(); - _mappings[path] = hash; - assetClient->_mappingCache[path] = hash; - } - } - emit finished(this); - }); -}; - -SetMappingRequest::SetMappingRequest(const AssetPath& path, const AssetHash& hash) : _path(path), _hash(hash) { -}; - -void SetMappingRequest::doStart() { - auto assetClient = DependencyManager::get(); - assetClient->setAssetMapping(_path, _hash, [this, assetClient](bool responseReceived, AssetServerError error, QSharedPointer message) { - if (!responseReceived) { - _error = NetworkError; - } else { - switch (error) { - case AssetServerError::NoError: - _error = NoError; - break; - case AssetServerError::PermissionDenied: - _error = PermissionDenied; - break; - default: - _error = UnknownError; - break; - } - } - - if (!error) { - assetClient->_mappingCache[_path] = _hash; - } - emit finished(this); - }); -}; - -DeleteMappingsRequest::DeleteMappingsRequest(const AssetPathList& paths) : _paths(paths) { -}; - -void DeleteMappingsRequest::doStart() { - auto assetClient = DependencyManager::get(); - assetClient->deleteAssetMappings(_paths, [this, assetClient](bool responseReceived, AssetServerError error, QSharedPointer message) { - if (!responseReceived) { - _error = NetworkError; - } else { - switch (error) { - case AssetServerError::NoError: - _error = NoError; - break; - case AssetServerError::PermissionDenied: - _error = PermissionDenied; - break; - default: - _error = UnknownError; - break; - } - } - - if (!error) { - // enumerate the paths and remove them from the cache - for (auto& path : _paths) { - assetClient->_mappingCache.remove(path); - } - } - emit finished(this); - }); -}; - AssetClient::AssetClient() { setCustomDeleter([](Dependency* dependency){ @@ -725,252 +581,3 @@ void AssetClient::handleNodeKilled(SharedNodePointer node) { _mappingCache.clear(); } - -void AssetScriptingInterface::uploadData(QString data, QScriptValue callback) { - QByteArray dataByteArray = data.toUtf8(); - auto upload = DependencyManager::get()->createUpload(dataByteArray); - if (!upload) { - qCWarning(asset_client) << "Error uploading file to asset server"; - return; - } - - QObject::connect(upload, &AssetUpload::finished, this, [this, callback](AssetUpload* upload, const QString& hash) mutable { - if (callback.isFunction()) { - QString url = "atp://" + hash; - QScriptValueList args { url }; - callback.call(_engine->currentContext()->thisObject(), args); - } - }); - upload->start(); -} - -AssetScriptingInterface::AssetScriptingInterface(QScriptEngine* engine) : - _engine(engine) -{ -} - -void AssetScriptingInterface::downloadData(QString urlString, QScriptValue callback) { - const QString ATP_SCHEME { "atp://" }; - - if (!urlString.startsWith(ATP_SCHEME)) { - return; - } - - // Make request to atp - auto path = urlString.right(urlString.length() - ATP_SCHEME.length()); - auto parts = path.split(".", QString::SkipEmptyParts); - auto hash = parts.length() > 0 ? parts[0] : ""; - - if (hash.length() != SHA256_HASH_HEX_LENGTH) { - return; - } - - auto assetClient = DependencyManager::get(); - auto assetRequest = assetClient->createRequest(hash); - - if (!assetRequest) { - return; - } - - _pendingRequests << assetRequest; - - connect(assetRequest, &AssetRequest::finished, this, [this, callback](AssetRequest* request) mutable { - Q_ASSERT(request->getState() == AssetRequest::Finished); - - if (request->getError() == AssetRequest::Error::NoError) { - if (callback.isFunction()) { - QString data = QString::fromUtf8(request->getData()); - QScriptValueList args { data }; - callback.call(_engine->currentContext()->thisObject(), args); - } - } - - request->deleteLater(); - _pendingRequests.remove(request); - }); - - assetRequest->start(); -} - -static int standardItemModelMetaTypeId = qRegisterMetaType("AssetMappingModel*"); - -AssetMappingsScriptingInterface::AssetMappingsScriptingInterface(QJSEngine* engine) : - _engine(engine), - _assetMappingModel(this) -{ -} - -void AssetMappingsScriptingInterface::setMapping(QString path, QString hash, QJSValue callback) { - auto assetClient = DependencyManager::get(); - auto request = assetClient->createSetMappingRequest(path, hash); - - connect(request, &SetMappingRequest::finished, this, [this, callback](SetMappingRequest* request) mutable { - QJSValueList args { uint8_t(request->getError()) }; - - callback.call(args); - - request->deleteLater(); - - }); - - request->start(); -} - -void AssetMappingsScriptingInterface::getMapping(QString path, QJSValue callback) { - auto assetClient = DependencyManager::get(); - auto request = assetClient->createGetMappingRequest(path); - - connect(request, &GetMappingRequest::finished, this, [this, callback](GetMappingRequest* request) mutable { - QJSValueList args { uint8_t(request->getError()), request->getHash() }; - - callback.call(args); - - request->deleteLater(); - - }); - - request->start(); -} - -void AssetMappingsScriptingInterface::deleteMappings(QStringList paths, QJSValue callback) { - auto assetClient = DependencyManager::get(); - auto request = assetClient->createDeleteMappingsRequest(paths); - - connect(request, &DeleteMappingsRequest::finished, this, [this, callback](DeleteMappingsRequest* request) mutable { - QJSValueList args { uint8_t(request->getError()) }; - - callback.call(args); - - request->deleteLater(); - - }); - - request->start(); -} - -void AssetMappingsScriptingInterface::getAllMappings(QJSValue callback) { - auto assetClient = DependencyManager::get(); - auto request = assetClient->createGetAllMappingsRequest(); - - connect(request, &GetAllMappingsRequest::finished, this, [this, callback](GetAllMappingsRequest* request) mutable { - auto mappings = request->getMappings(); - auto map = callback.engine()->newObject(); - - for (auto& kv : mappings ) { - map.setProperty(kv.first, kv.second); - } - - QJSValueList args { uint8_t(request->getError()), map }; - - callback.call(args); - - request->deleteLater(); - - }); - - request->start(); -} - -AssetMappingItem::AssetMappingItem(const QString& name, const QString& fullPath, bool isFolder) - : name(name), - fullPath(fullPath), - isFolder(isFolder) { - -} - -AssetMappingModel::AssetMappingModel(QObject* parent) { -} - -void AssetMappingModel::refresh() { - qDebug() << "Refreshing asset mapping model"; - auto assetClient = DependencyManager::get(); - auto request = assetClient->createGetAllMappingsRequest(); - - connect(request, &GetAllMappingsRequest::finished, this, [this](GetAllMappingsRequest* request) mutable { - auto mappings = request->getMappings(); - for (auto& mapping : mappings) { - auto& path = mapping.first; - auto parts = path.split("/"); - auto length = parts.length(); - - QString prefix = parts[0]; - - QStandardItem* lastItem = nullptr; - - auto it = _pathToItemMap.find(prefix); - if (it == _pathToItemMap.end()) { - lastItem = new QStandardItem(parts[0]); - lastItem->setData(parts[0], Qt::UserRole + 1); - lastItem->setData(prefix, Qt::UserRole + 2); - _pathToItemMap[prefix] = lastItem; - appendRow(lastItem); - } else { - lastItem = it.value(); - } - - if (length > 1) { - for (int i = 1; i < length; ++i) { - prefix += "/" + parts[i]; - - auto it = _pathToItemMap.find(prefix); - if (it == _pathToItemMap.end()) { - qDebug() << "prefix not found: " << prefix; - auto item = new QStandardItem(parts[i]); - item->setData(parts[i], Qt::UserRole + 1); - item->setData(prefix, Qt::UserRole + 2); - lastItem->setChild(lastItem->rowCount(), 0, item); - lastItem = item; - _pathToItemMap[prefix] = lastItem; - } else { - lastItem = it.value(); - } - } - } - - Q_ASSERT(prefix == path); - } - }); - - request->start(); -} - -// QModelIndex AssetMappingModel::index(int row, int column, const QModelIndex& parent) const { -// if (row < 0 || column < 0) { -// return QModelIndex(); -// } - -// if (parent.isValid()) { -// auto item = static_cast(parent.internalPointer()); -// return createIndex(row, column, ) -// } -// return createIndex(row, column, getFolderNodes( -// static_cast(getTreeNodeFromIndex(parent))).at(row)); -// } - -// QModelIndex AssetMappingModel::parent(const QModelIndex& child) const { -// AssetMappingItem* parent = (static_cast(child.internalPointer()))->getParent(); -// if (!parent) { -// return QModelIndex(); -// } -// AssetMappingItem* grandParent = parent->getParent(); -// int row = getFolderNodes(grandParent).indexOf(parent); -// return createIndex(row, 0, parent); -// } - -// QVariant AssetMappingModel::data(const QModelIndex& index, int role) const { -// if (index.isValid()) { -// AssetMappingItem* item = (static_cast(index.internalPointer())); -// if (item) { -// return item->name; -// } -// } -// return QVariant(); -// } -// -// int AssetMappingModel::rowCount(const QModelIndex& parent) const { -// return 1; -// } - -// int AssetMappingModel::columnCount(const QModelIndex& parent) const { -// return 1; -// } diff --git a/libraries/networking/src/AssetClient.h b/libraries/networking/src/AssetClient.h index 08fcb099c4..9e34774816 100644 --- a/libraries/networking/src/AssetClient.h +++ b/libraries/networking/src/AssetClient.h @@ -108,62 +108,4 @@ private: friend class RenameMappingRequest; }; - -class AssetScriptingInterface : public QObject { - Q_OBJECT -public: - AssetScriptingInterface(QScriptEngine* engine); - - Q_INVOKABLE void uploadData(QString data, QScriptValue callback); - Q_INVOKABLE void downloadData(QString url, QScriptValue downloadComplete); -// Q_INVOKABLE void setMapping(QString path, QString hash, QScriptValue callback); -// Q_INVOKABLE void getMapping(QString path, QScriptValue callback); -// Q_INVOKABLE void deleteMappings(QStringList paths, QScriptValue callback); -// Q_INVOKABLE void getAllMappings(QScriptValue callback); -protected: - QSet _pendingRequests; - QScriptEngine* _engine; -}; - - - class AssetMappingItem : public QStandardItem { - public: - AssetMappingItem(const QString& name, const QString& fullPath, bool isFolder); - - QString name; - QString fullPath; - bool isFolder; - }; - - - class AssetMappingModel : public QStandardItemModel { - Q_OBJECT - public: - AssetMappingModel(QObject* parent = nullptr); - - QVariant AssetMappingModel::data(const QModelIndex& index, int role) const; - - Q_INVOKABLE void refresh(); - - private: - QHash _pathToItemMap; - }; - -class AssetMappingsScriptingInterface : public QObject { - Q_OBJECT - Q_PROPERTY(AssetMappingModel* mappingModel READ getAssetMappingModel CONSTANT) -public: - AssetMappingsScriptingInterface(QJSEngine* engine); - - Q_INVOKABLE AssetMappingModel* getAssetMappingModel() { return &_assetMappingModel; }; - - Q_INVOKABLE void setMapping(QString path, QString hash, QJSValue callback); - Q_INVOKABLE void getMapping(QString path, QJSValue callback); - Q_INVOKABLE void deleteMappings(QStringList paths, QJSValue callback); - Q_INVOKABLE void getAllMappings(QJSValue callback); -protected: - QSet _pendingRequests; - QJSEngine* _engine; - AssetMappingModel _assetMappingModel; -}; #endif diff --git a/libraries/networking/src/MappingRequest.cpp b/libraries/networking/src/MappingRequest.cpp index 187694e134..73ea1483b0 100644 --- a/libraries/networking/src/MappingRequest.cpp +++ b/libraries/networking/src/MappingRequest.cpp @@ -50,7 +50,7 @@ void GetMappingRequest::doStart() { break; case AssetServerError::AssetNotFound: _error = NotFound; - break; + break default: _error = UnknownError; break; @@ -85,13 +85,13 @@ void GetAllMappingsRequest::doStart() { } - if (!error) { + if (!_error) { int numberOfMappings; message->readPrimitive(&numberOfMappings); assetClient->_mappingCache.clear(); for (auto i = 0; i < numberOfMappings; ++i) { auto path = message->readString(); - auto hash = message->readString(); + auto hash = message->read(SHA256_HASH_LENGTH).toHex(); _mappings[path] = hash; assetClient->_mappingCache[path] = hash; } @@ -122,7 +122,7 @@ void SetMappingRequest::doStart() { } } - if (!error) { + if (!_error) { assetClient->_mappingCache[_path] = _hash; } emit finished(this); @@ -151,7 +151,7 @@ void DeleteMappingsRequest::doStart() { } } - if (!error) { + if (!_error) { // enumerate the paths and remove them from the cache for (auto& path : _paths) { assetClient->_mappingCache.remove(path); @@ -189,7 +189,7 @@ void RenameMappingRequest::doStart() { } } - if (!error) { + if (!_error) { // take the hash mapped for the old path from the cache auto hash = assetClient->_mappingCache.take(_oldPath); if (!hash.isEmpty()) { diff --git a/libraries/script-engine/src/AssetMappingsScriptingInterface.cpp b/libraries/script-engine/src/AssetMappingsScriptingInterface.cpp new file mode 100644 index 0000000000..c8370170db --- /dev/null +++ b/libraries/script-engine/src/AssetMappingsScriptingInterface.cpp @@ -0,0 +1,218 @@ +// +// AssetMappingsScriptingInterface.cpp +// libraries/script-engine/src +// +// Created by Ryan Huffman on 2016-03-09. +// 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 +// + +#include "AssetMappingsScriptingInterface.h" + +#include + +#include +#include +#include +#include + +AssetMappingsScriptingInterface::AssetMappingsScriptingInterface() { +} + +void AssetMappingsScriptingInterface::setMapping(QString path, QString hash, QJSValue callback) { + auto assetClient = DependencyManager::get(); + auto request = assetClient->createSetMappingRequest(path, hash); + + connect(request, &SetMappingRequest::finished, this, [this, callback](SetMappingRequest* request) mutable { + QJSValueList args { uint8_t(request->getError()) }; + + callback.call(args); + + request->deleteLater(); + + }); + + request->start(); +} + +void AssetMappingsScriptingInterface::getMapping(QString path, QJSValue callback) { + auto assetClient = DependencyManager::get(); + auto request = assetClient->createGetMappingRequest(path); + + connect(request, &GetMappingRequest::finished, this, [this, callback](GetMappingRequest* request) mutable { + QJSValueList args { uint8_t(request->getError()), request->getHash() }; + + callback.call(args); + + request->deleteLater(); + + }); + + request->start(); +} + +void AssetMappingsScriptingInterface::deleteMappings(QStringList paths, QJSValue callback) { + auto assetClient = DependencyManager::get(); + auto request = assetClient->createDeleteMappingsRequest(paths); + + connect(request, &DeleteMappingsRequest::finished, this, [this, callback](DeleteMappingsRequest* request) mutable { + QJSValueList args { uint8_t(request->getError()) }; + + callback.call(args); + + request->deleteLater(); + + }); + + request->start(); +} + +void AssetMappingsScriptingInterface::getAllMappings(QJSValue callback) { + auto assetClient = DependencyManager::get(); + auto request = assetClient->createGetAllMappingsRequest(); + + connect(request, &GetAllMappingsRequest::finished, this, [this, callback](GetAllMappingsRequest* request) mutable { + auto mappings = request->getMappings(); + auto map = callback.engine()->newObject(); + + for (auto& kv : mappings ) { + map.setProperty(kv.first, kv.second); + } + + QJSValueList args { uint8_t(request->getError()), map }; + + callback.call(args); + + request->deleteLater(); + + }); + + request->start(); +} + +void AssetMappingsScriptingInterface::renameMapping(QString oldPath, QString newPath, QJSValue callback) { + auto assetClient = DependencyManager::get(); + auto request = assetClient->createRenameMappingRequest(oldPath, newPath); + + connect(request, &RenameMappingRequest::finished, this, [this, callback](RenameMappingRequest* request) mutable { + QJSValueList args { uint8_t(request->getError()) }; + + callback.call(args); + + request->deleteLater(); + + }); + + request->start(); +} + + +AssetMappingItem::AssetMappingItem(const QString& name, const QString& fullPath, bool isFolder) + : name(name), + fullPath(fullPath), + isFolder(isFolder) { + +} + +static int assetMappingModelMetatypeId = qRegisterMetaType("AssetMappingModel*"); + +AssetMappingModel::AssetMappingModel(QObject* parent) { +} + +void AssetMappingModel::refresh() { + qDebug() << "Refreshing asset mapping model"; + auto assetClient = DependencyManager::get(); + auto request = assetClient->createGetAllMappingsRequest(); + + connect(request, &GetAllMappingsRequest::finished, this, [this](GetAllMappingsRequest* request) mutable { + auto mappings = request->getMappings(); + for (auto& mapping : mappings) { + auto& path = mapping.first; + auto parts = path.split("/"); + auto length = parts.length(); + + QString fullPath = parts[0]; + + QStandardItem* lastItem = nullptr; + + auto it = _pathToItemMap.find(fullPath); + if (it == _pathToItemMap.end()) { + lastItem = new QStandardItem(parts[0]); + lastItem->setData(parts[0], Qt::UserRole + 1); + lastItem->setData(fullPath, Qt::UserRole + 2); + _pathToItemMap[fullPath] = lastItem; + appendRow(lastItem); + } + else { + lastItem = it.value(); + } + + if (length > 1) { + for (int i = 1; i < length; ++i) { + fullPath += "/" + parts[i]; + + auto it = _pathToItemMap.find(fullPath); + if (it == _pathToItemMap.end()) { + qDebug() << "prefix not found: " << fullPath; + auto item = new QStandardItem(parts[i]); + bool isFolder = i < length - 1; + item->setData(isFolder ? fullPath + "/" : fullPath, Qt::UserRole); + lastItem->setChild(lastItem->rowCount(), 0, item); + lastItem = item; + _pathToItemMap[fullPath] = lastItem; + } + else { + lastItem = it.value(); + } + } + } + + Q_ASSERT(fullPath == path); + } + }); + + request->start(); +} + +// QModelIndex AssetMappingModel::index(int row, int column, const QModelIndex& parent) const { +// if (row < 0 || column < 0) { +// return QModelIndex(); +// } + +// if (parent.isValid()) { +// auto item = static_cast(parent.internalPointer()); +// return createIndex(row, column, ) +// } +// return createIndex(row, column, getFolderNodes( +// static_cast(getTreeNodeFromIndex(parent))).at(row)); +// } + +// QModelIndex AssetMappingModel::parent(const QModelIndex& child) const { +// AssetMappingItem* parent = (static_cast(child.internalPointer()))->getParent(); +// if (!parent) { +// return QModelIndex(); +// } +// AssetMappingItem* grandParent = parent->getParent(); +// int row = getFolderNodes(grandParent).indexOf(parent); +// return createIndex(row, 0, parent); +// } + +// QVariant AssetMappingModel::data(const QModelIndex& index, int role) const { +// if (index.isValid()) { +// AssetMappingItem* item = (static_cast(index.internalPointer())); +// if (item) { +// return item->name; +// } +// } +// return QVariant(); +// } +// +// int AssetMappingModel::rowCount(const QModelIndex& parent) const { +// return 1; +// } + +// int AssetMappingModel::columnCount(const QModelIndex& parent) const { +// return 1; +// } diff --git a/libraries/script-engine/src/AssetMappingsScriptingInterface.h b/libraries/script-engine/src/AssetMappingsScriptingInterface.h new file mode 100644 index 0000000000..66a31414bb --- /dev/null +++ b/libraries/script-engine/src/AssetMappingsScriptingInterface.h @@ -0,0 +1,64 @@ +// +// AssetScriptingInterface.h +// libraries/script-engine/src +// +// Created by Ryan Huffman on 2016-03-09. +// 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 +// + +#pragma once + +#ifndef hifi_AssetMappingsScriptingInterface_h +#define hifi_AssetMappingsScriptingInterface_h + +#include +#include + +#include + + class AssetMappingItem : public QStandardItem { + public: + AssetMappingItem(const QString& name, const QString& fullPath, bool isFolder); + + QString name; + QString fullPath; + bool isFolder; + }; + + + class AssetMappingModel : public QStandardItemModel { + Q_OBJECT + public: + AssetMappingModel(QObject* parent = nullptr); + +// QVariant AssetMappingModel::data(const QModelIndex& index, int role) const; + + Q_INVOKABLE void refresh(); + + private: + QHash _pathToItemMap; + }; + + +class AssetMappingsScriptingInterface : public QObject, public Dependency { + Q_OBJECT +public: + AssetMappingsScriptingInterface(); + + Q_INVOKABLE AssetMappingModel* getAssetMappingModel() { return &_assetMappingModel; } + + Q_INVOKABLE void setMapping(QString path, QString hash, QJSValue callback); + Q_INVOKABLE void getMapping(QString path, QJSValue callback); + Q_INVOKABLE void deleteMappings(QStringList paths, QJSValue callback); + Q_INVOKABLE void getAllMappings(QJSValue callback); + Q_INVOKABLE void renameMapping(QString oldPath, QString newPath, QJSValue callback); +protected: + QSet _pendingRequests; + AssetMappingModel _assetMappingModel; +}; + + +#endif // hifi_AssetMappingsScriptingInterface_h diff --git a/libraries/script-engine/src/AssetScriptingInterface.cpp b/libraries/script-engine/src/AssetScriptingInterface.cpp index db29008976..fb315434fd 100644 --- a/libraries/script-engine/src/AssetScriptingInterface.cpp +++ b/libraries/script-engine/src/AssetScriptingInterface.cpp @@ -84,90 +84,3 @@ void AssetScriptingInterface::downloadData(QString urlString, QScriptValue callb assetRequest->start(); } - -void AssetScriptingInterface::setMapping(QString path, QString hash, QScriptValue callback) { - auto assetClient = DependencyManager::get(); - auto request = assetClient->createSetMappingRequest(path, hash); - - connect(request, &SetMappingRequest::finished, this, [this, callback](SetMappingRequest* request) mutable { - QScriptValueList args { uint8_t(request->getError()) }; - - callback.call(_engine->currentContext()->thisObject(), args); - - request->deleteLater(); - - }); - - request->start(); -} - -void AssetScriptingInterface::getMapping(QString path, QScriptValue callback) { - auto assetClient = DependencyManager::get(); - auto request = assetClient->createGetMappingRequest(path); - - connect(request, &GetMappingRequest::finished, this, [this, callback](GetMappingRequest* request) mutable { - QScriptValueList args { uint8_t(request->getError()), request->getHash() }; - - callback.call(_engine->currentContext()->thisObject(), args); - - request->deleteLater(); - - }); - - request->start(); -} - -void AssetScriptingInterface::deleteMappings(QStringList paths, QScriptValue callback) { - auto assetClient = DependencyManager::get(); - auto request = assetClient->createDeleteMappingsRequest(paths); - - connect(request, &DeleteMappingsRequest::finished, this, [this, callback](DeleteMappingsRequest* request) mutable { - QScriptValueList args { uint8_t(request->getError()) }; - - callback.call(_engine->currentContext()->thisObject(), args); - - request->deleteLater(); - - }); - - request->start(); -} - -void AssetScriptingInterface::getAllMappings(QScriptValue callback) { - auto assetClient = DependencyManager::get(); - auto request = assetClient->createGetAllMappingsRequest(); - - connect(request, &GetAllMappingsRequest::finished, this, [this, callback](GetAllMappingsRequest* request) mutable { - auto mappings = request->getMappings(); - auto map = callback.engine()->newObject(); - - for (auto& kv : mappings ) { - map.setProperty(kv.first, kv.second); - } - - QScriptValueList args { uint8_t(request->getError()), map }; - - callback.call(_engine->currentContext()->thisObject(), args); - - request->deleteLater(); - - }); - - request->start(); -} - -void AssetScriptingInterface::renameMapping(QString oldPath, QString newPath, QScriptValue callback) { - auto assetClient = DependencyManager::get(); - auto request = assetClient->createRenameMappingRequest(oldPath, newPath); - - connect(request, &RenameMappingRequest::finished, this, [this, callback](RenameMappingRequest* request) mutable { - QScriptValueList args { uint8_t(request->getError()) }; - - callback.call(_engine->currentContext()->thisObject(), args); - - request->deleteLater(); - - }); - - request->start(); -} diff --git a/libraries/script-engine/src/AssetScriptingInterface.h b/libraries/script-engine/src/AssetScriptingInterface.h index 287300cac8..63b16fd51d 100644 --- a/libraries/script-engine/src/AssetScriptingInterface.h +++ b/libraries/script-engine/src/AssetScriptingInterface.h @@ -26,11 +26,6 @@ public: Q_INVOKABLE void uploadData(QString data, QScriptValue callback); Q_INVOKABLE void downloadData(QString url, QScriptValue downloadComplete); - Q_INVOKABLE void setMapping(QString path, QString hash, QScriptValue callback); - Q_INVOKABLE void getMapping(QString path, QScriptValue callback); - Q_INVOKABLE void deleteMappings(QStringList paths, QScriptValue callback); - Q_INVOKABLE void getAllMappings(QScriptValue callback); - Q_INVOKABLE void renameMapping(QString oldPath, QString newPath, QScriptValue callback); protected: QSet _pendingRequests; QScriptEngine* _engine; From d299ce2677ab6f0bdc205554c2c43726c8579648 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Mar 2016 14:56:56 -0800 Subject: [PATCH 06/13] Fix missing semicolon --- libraries/networking/src/MappingRequest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/MappingRequest.cpp b/libraries/networking/src/MappingRequest.cpp index 73ea1483b0..9afa3e7432 100644 --- a/libraries/networking/src/MappingRequest.cpp +++ b/libraries/networking/src/MappingRequest.cpp @@ -50,7 +50,7 @@ void GetMappingRequest::doStart() { break; case AssetServerError::AssetNotFound: _error = NotFound; - break + break; default: _error = UnknownError; break; From f23057b1c04093f3b765709e1a8593eadf90ac8a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Mar 2016 16:29:17 -0800 Subject: [PATCH 07/13] Add renaming to Asset qml --- interface/resources/qml/AssetServer.qml | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/interface/resources/qml/AssetServer.qml b/interface/resources/qml/AssetServer.qml index d773d6f86a..d76374c10c 100644 --- a/interface/resources/qml/AssetServer.qml +++ b/interface/resources/qml/AssetServer.qml @@ -33,7 +33,7 @@ Window { HifiConstants { id: hifi } property var scripts: ScriptDiscoveryService; - property var scriptsModel: Assets.getAssetMappingModel() + property var scriptsModel: Assets.mappingModel; property var currentDirectory; Settings { @@ -52,6 +52,7 @@ Window { } function renameFile() { var path = scriptsModel.data(treeView.currentIndex, 0x100); + print(path); if (!path) { return; } @@ -63,16 +64,15 @@ Window { }); object.selected.connect(function(destinationPath) { console.log("Renaming " + path + " to " + destinationPath); - - - - - + Assets.renameMapping(path, destinationPath, function(err) { + print("Finished rename: ", err); + reload(); + }); }); } function deleteFile() { var path = scriptsModel.data(treeView.currentIndex, 0x100); - print(path); + print(treeView.currentIndex, path); if (!path) { return; } @@ -94,8 +94,6 @@ Window { print("Finished deleting path: ", path, err); reload(); }); - - } }); } From ebc6c8ce44e2f4deeef96fd537dcf62f4acf7e32 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Mar 2016 16:29:51 -0800 Subject: [PATCH 08/13] Add proper model updating to asset mapping model --- .../src/AssetMappingsScriptingInterface.cpp | 91 +++++++++++++------ .../src/AssetMappingsScriptingInterface.h | 5 +- 2 files changed, 67 insertions(+), 29 deletions(-) diff --git a/libraries/script-engine/src/AssetMappingsScriptingInterface.cpp b/libraries/script-engine/src/AssetMappingsScriptingInterface.cpp index c8370170db..c5b165d7f6 100644 --- a/libraries/script-engine/src/AssetMappingsScriptingInterface.cpp +++ b/libraries/script-engine/src/AssetMappingsScriptingInterface.cpp @@ -20,6 +20,9 @@ AssetMappingsScriptingInterface::AssetMappingsScriptingInterface() { } +AssetMappingsScriptingInterface::~AssetMappingsScriptingInterface() { + qDebug() << "Destroying mapping interface"; +} void AssetMappingsScriptingInterface::setMapping(QString path, QString hash, QJSValue callback) { auto assetClient = DependencyManager::get(); @@ -118,7 +121,11 @@ AssetMappingItem::AssetMappingItem(const QString& name, const QString& fullPath, static int assetMappingModelMetatypeId = qRegisterMetaType("AssetMappingModel*"); -AssetMappingModel::AssetMappingModel(QObject* parent) { +AssetMappingModel::AssetMappingModel() { +} + +AssetMappingModel::~AssetMappingModel() { + qDebug() << " DEST"; } void AssetMappingModel::refresh() { @@ -128,49 +135,77 @@ void AssetMappingModel::refresh() { connect(request, &GetAllMappingsRequest::finished, this, [this](GetAllMappingsRequest* request) mutable { auto mappings = request->getMappings(); + auto existingPaths = _pathToItemMap.keys(); for (auto& mapping : mappings) { auto& path = mapping.first; auto parts = path.split("/"); auto length = parts.length(); - QString fullPath = parts[0]; + existingPaths.removeOne(mapping.first); + + QString fullPath = "";// parts[0]; QStandardItem* lastItem = nullptr; - auto it = _pathToItemMap.find(fullPath); - if (it == _pathToItemMap.end()) { - lastItem = new QStandardItem(parts[0]); - lastItem->setData(parts[0], Qt::UserRole + 1); - lastItem->setData(fullPath, Qt::UserRole + 2); - _pathToItemMap[fullPath] = lastItem; - appendRow(lastItem); - } - else { - lastItem = it.value(); - } + for (int i = 0; i < length; ++i) { + fullPath += (i == 0 ? "" : "/") + parts[i]; - if (length > 1) { - for (int i = 1; i < length; ++i) { - fullPath += "/" + parts[i]; - - auto it = _pathToItemMap.find(fullPath); - if (it == _pathToItemMap.end()) { - qDebug() << "prefix not found: " << fullPath; - auto item = new QStandardItem(parts[i]); - bool isFolder = i < length - 1; - item->setData(isFolder ? fullPath + "/" : fullPath, Qt::UserRole); + auto it = _pathToItemMap.find(fullPath); + if (it == _pathToItemMap.end()) { + qDebug() << "prefix not found: " << fullPath; + auto item = new QStandardItem(parts[i]); + bool isFolder = i < length - 1; + item->setData(isFolder ? fullPath + "/" : fullPath, Qt::UserRole); + item->setData(isFolder, Qt::UserRole + 1); + if (lastItem) { lastItem->setChild(lastItem->rowCount(), 0, item); - lastItem = item; - _pathToItemMap[fullPath] = lastItem; - } - else { - lastItem = it.value(); + } else { + appendRow(item); } + + lastItem = item; + _pathToItemMap[fullPath] = lastItem; + } + else { + lastItem = it.value(); } } Q_ASSERT(fullPath == path); } + for (auto& path : existingPaths) { + Q_ASSERT(_pathToItemMap.contains(path)); + auto item = _pathToItemMap[path]; + if (item->data(Qt::UserRole + 1).toBool()) { + continue; + } + + qDebug() << "removing existing: " << path; + + while (item) { + // During each iteration, delete item + QStandardItem* nextItem = nullptr; + + auto parent = item->parent(); + if (parent) { + parent->removeRow(item->row()); + if (parent->rowCount() > 0) { + // The parent still contains children, set the nextItem to null so we stop processing + nextItem = nullptr; + } else { + nextItem = parent; + } + } else { + removeRow(item->row()); + } + + _pathToItemMap.remove(path); + //delete item; + + item = nextItem; + } + //removeitem->index(); + } }); request->start(); diff --git a/libraries/script-engine/src/AssetMappingsScriptingInterface.h b/libraries/script-engine/src/AssetMappingsScriptingInterface.h index 66a31414bb..3afdab35cf 100644 --- a/libraries/script-engine/src/AssetMappingsScriptingInterface.h +++ b/libraries/script-engine/src/AssetMappingsScriptingInterface.h @@ -32,7 +32,8 @@ class AssetMappingModel : public QStandardItemModel { Q_OBJECT public: - AssetMappingModel(QObject* parent = nullptr); + AssetMappingModel(); + ~AssetMappingModel(); // QVariant AssetMappingModel::data(const QModelIndex& index, int role) const; @@ -45,8 +46,10 @@ class AssetMappingsScriptingInterface : public QObject, public Dependency { Q_OBJECT + Q_PROPERTY(AssetMappingModel* mappingModel READ getAssetMappingModel CONSTANT) public: AssetMappingsScriptingInterface(); + ~AssetMappingsScriptingInterface(); Q_INVOKABLE AssetMappingModel* getAssetMappingModel() { return &_assetMappingModel; } From 232bfc9061ebc691abf9d19d1aa62575ca856ddb Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Mar 2016 16:44:31 -0800 Subject: [PATCH 09/13] Cleanup AssetServer qml --- interface/resources/qml/AssetServer.qml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/AssetServer.qml b/interface/resources/qml/AssetServer.qml index 8134d78b26..54f7a10b25 100644 --- a/interface/resources/qml/AssetServer.qml +++ b/interface/resources/qml/AssetServer.qml @@ -47,7 +47,7 @@ Window { function doDeleteFile(path) { console.log("Deleting " + path); - Assets.deleteMappings([path], function(err) { + Assets.deleteMappings(path, function(err) { print("Finished deleting path: ", path, err); reload(); }); @@ -61,8 +61,7 @@ Window { function doRenameFile(oldPath, newPath) { console.log("Renaming " + oldPath + " to " + newPath); - console.log("Renaming " + path + " to " + destinationPath); - Assets.renameMapping(path, destinationPath, function(err) { + Assets.renameMapping(oldPath, destinationPath, function(err) { print("Finished rename: ", err); reload(); }); @@ -111,7 +110,6 @@ Window { } function renameFile() { var path = scriptsModel.data(treeView.currentIndex, 0x100); - print(path); if (!path) { return; } @@ -133,7 +131,6 @@ Window { } function deleteFile() { var path = scriptsModel.data(treeView.currentIndex, 0x100); - print(treeView.currentIndex, path); if (!path) { return; } From 3467e06199be0af83f642ebeb57c3292e7283339 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Mar 2016 16:44:41 -0800 Subject: [PATCH 10/13] Fix bugs in mapping model update --- .../src/AssetMappingsScriptingInterface.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/libraries/script-engine/src/AssetMappingsScriptingInterface.cpp b/libraries/script-engine/src/AssetMappingsScriptingInterface.cpp index c5b165d7f6..8dc40b0df1 100644 --- a/libraries/script-engine/src/AssetMappingsScriptingInterface.cpp +++ b/libraries/script-engine/src/AssetMappingsScriptingInterface.cpp @@ -173,15 +173,24 @@ void AssetMappingModel::refresh() { Q_ASSERT(fullPath == path); } + + // Remove folders from list + auto it = existingPaths.begin(); + while (it != existingPaths.end()) { + auto item = _pathToItemMap[*it]; + if (item->data(Qt::UserRole + 1).toBool()) { + it = existingPaths.erase(it); + } else { + ++it; + } + } + for (auto& path : existingPaths) { Q_ASSERT(_pathToItemMap.contains(path)); - auto item = _pathToItemMap[path]; - if (item->data(Qt::UserRole + 1).toBool()) { - continue; - } - qDebug() << "removing existing: " << path; + auto item = _pathToItemMap[path]; + while (item) { // During each iteration, delete item QStandardItem* nextItem = nullptr; From fa66c0a5211cf377da783a39e342ad7653968dce Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Mar 2016 16:44:51 -0800 Subject: [PATCH 11/13] Remove old model code --- .../src/AssetMappingsScriptingInterface.cpp | 41 ------------------- 1 file changed, 41 deletions(-) diff --git a/libraries/script-engine/src/AssetMappingsScriptingInterface.cpp b/libraries/script-engine/src/AssetMappingsScriptingInterface.cpp index 8dc40b0df1..7fab655e26 100644 --- a/libraries/script-engine/src/AssetMappingsScriptingInterface.cpp +++ b/libraries/script-engine/src/AssetMappingsScriptingInterface.cpp @@ -219,44 +219,3 @@ void AssetMappingModel::refresh() { request->start(); } - -// QModelIndex AssetMappingModel::index(int row, int column, const QModelIndex& parent) const { -// if (row < 0 || column < 0) { -// return QModelIndex(); -// } - -// if (parent.isValid()) { -// auto item = static_cast(parent.internalPointer()); -// return createIndex(row, column, ) -// } -// return createIndex(row, column, getFolderNodes( -// static_cast(getTreeNodeFromIndex(parent))).at(row)); -// } - -// QModelIndex AssetMappingModel::parent(const QModelIndex& child) const { -// AssetMappingItem* parent = (static_cast(child.internalPointer()))->getParent(); -// if (!parent) { -// return QModelIndex(); -// } -// AssetMappingItem* grandParent = parent->getParent(); -// int row = getFolderNodes(grandParent).indexOf(parent); -// return createIndex(row, 0, parent); -// } - -// QVariant AssetMappingModel::data(const QModelIndex& index, int role) const { -// if (index.isValid()) { -// AssetMappingItem* item = (static_cast(index.internalPointer())); -// if (item) { -// return item->name; -// } -// } -// return QVariant(); -// } -// -// int AssetMappingModel::rowCount(const QModelIndex& parent) const { -// return 1; -// } - -// int AssetMappingModel::columnCount(const QModelIndex& parent) const { -// return 1; -// } From dd52dd69d9fdb62919655834a6171ae65e4c1211 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Mar 2016 16:50:37 -0800 Subject: [PATCH 12/13] Fix rename mapping --- interface/resources/qml/AssetServer.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/AssetServer.qml b/interface/resources/qml/AssetServer.qml index 54f7a10b25..f9cc566d39 100644 --- a/interface/resources/qml/AssetServer.qml +++ b/interface/resources/qml/AssetServer.qml @@ -61,7 +61,7 @@ Window { function doRenameFile(oldPath, newPath) { console.log("Renaming " + oldPath + " to " + newPath); - Assets.renameMapping(oldPath, destinationPath, function(err) { + Assets.renameMapping(oldPath, newPath, function(err) { print("Finished rename: ", err); reload(); }); @@ -121,7 +121,7 @@ Window { }); object.selected.connect(function(destinationPath) { if (fileExists(destinationPath)) { - askForOverride(path, function() { + askForOverride(destinationPath, function() { doRenameFile(path, destinationPath); }); } else { From 738ae54e8dafbbc85b939a315ed44375d3baf345 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 9 Mar 2016 16:56:28 -0800 Subject: [PATCH 13/13] Remove comment --- libraries/script-engine/src/AssetMappingsScriptingInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/script-engine/src/AssetMappingsScriptingInterface.cpp b/libraries/script-engine/src/AssetMappingsScriptingInterface.cpp index 7fab655e26..4dfc99b13f 100644 --- a/libraries/script-engine/src/AssetMappingsScriptingInterface.cpp +++ b/libraries/script-engine/src/AssetMappingsScriptingInterface.cpp @@ -143,7 +143,7 @@ void AssetMappingModel::refresh() { existingPaths.removeOne(mapping.first); - QString fullPath = "";// parts[0]; + QString fullPath = ""; QStandardItem* lastItem = nullptr;