mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-07 22:41:04 +02:00
thread the AssetUpload so it doesn't take over main
This commit is contained in:
parent
c277584f2e
commit
513cae0d40
10 changed files with 201 additions and 37 deletions
|
@ -80,11 +80,6 @@ void AssetServer::run() {
|
|||
file.rename(_resourcesDirectory.absoluteFilePath(hash));
|
||||
}
|
||||
}
|
||||
|
||||
while (!_isFinished) {
|
||||
// since we're a while loop we need to help Qt's event processing
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void AssetServer::handleAssetGetInfo(QSharedPointer<NLPacket> packet, SharedNodePointer senderNode) {
|
||||
|
|
|
@ -18,9 +18,8 @@
|
|||
|
||||
OctreePacketProcessor::OctreePacketProcessor() {
|
||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||
|
||||
packetReceiver.registerDirectListenerForTypes({ PacketType::OctreeStats, PacketType::EntityData,
|
||||
PacketType::EntityErase, PacketType::OctreeStats },
|
||||
|
||||
packetReceiver.registerDirectListenerForTypes({ PacketType::OctreeStats, PacketType::EntityData, PacketType::EntityErase },
|
||||
this, "handleOctreePacket");
|
||||
}
|
||||
|
||||
|
|
|
@ -12,10 +12,15 @@
|
|||
#include "AssetUploadDialogFactory.h"
|
||||
|
||||
#include <AssetClient.h>
|
||||
#include <AssetUpload.h>
|
||||
#include <AssetUtils.h>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <QtWidgets/QDialogButtonBox>
|
||||
#include <QtWidgets/QFileDialog>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
|
||||
AssetUploadDialogFactory& AssetUploadDialogFactory::getInstance() {
|
||||
static AssetUploadDialogFactory staticInstance;
|
||||
|
@ -27,29 +32,63 @@ AssetUploadDialogFactory::AssetUploadDialogFactory() {
|
|||
}
|
||||
|
||||
void AssetUploadDialogFactory::showDialog() {
|
||||
auto filename = QFileDialog::getOpenFileUrl(nullptr, "Select a file to upload");
|
||||
auto filename = QFileDialog::getOpenFileUrl(_dialogParent, "Select a file to upload");
|
||||
|
||||
if (!filename.isEmpty()) {
|
||||
qDebug() << "Selected filename for upload to asset-server: " << filename;
|
||||
|
||||
QFile file { filename.path() };
|
||||
auto assetClient = DependencyManager::get<AssetClient>();
|
||||
auto upload = assetClient->createUpload(filename.path());
|
||||
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
if (upload) {
|
||||
// connect to the finished signal so we know when the AssetUpload is done
|
||||
QObject::connect(upload, &AssetUpload::finished, this, &AssetUploadDialogFactory::handleUploadFinished);
|
||||
|
||||
QFileInfo fileInfo { filename.path() };
|
||||
auto extension = fileInfo.suffix();
|
||||
|
||||
auto data = file.readAll();
|
||||
|
||||
auto assetClient = DependencyManager::get<AssetClient>();
|
||||
|
||||
assetClient->uploadAsset(data, extension, [this, extension](bool result, QString hash) mutable {
|
||||
if (result) {
|
||||
QMessageBox::information(_dialogParent, "Upload Successful", "URL: apt:/" + hash + "." + extension);
|
||||
} else {
|
||||
QMessageBox::warning(_dialogParent, "Upload Failed", "There was an error uploading the file.");
|
||||
}
|
||||
});
|
||||
// start the upload now
|
||||
upload->start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AssetUploadDialogFactory::handleUploadFinished(AssetUpload* upload, const QString& hash) {
|
||||
if (true) {
|
||||
// show message box for successful upload, with copiable text for ATP hash
|
||||
QDialog* hashCopyDialog = new QDialog(_dialogParent);
|
||||
|
||||
// delete the dialog on close
|
||||
hashCopyDialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
// set the window title
|
||||
hashCopyDialog->setWindowTitle(tr("Successful Asset Upload"));
|
||||
|
||||
// setup a layout for the contents of the dialog
|
||||
QVBoxLayout* boxLayout = new QVBoxLayout;
|
||||
|
||||
// set the label text (this shows above the text box)
|
||||
QLabel* lineEditLabel = new QLabel;
|
||||
lineEditLabel->setText(QString("ATP URL for %1").arg(upload->getFilename()));
|
||||
|
||||
// setup the line edit to hold the copiable text
|
||||
QLineEdit* lineEdit = new QLineEdit;
|
||||
|
||||
// set the ATP URL as the text value so it's copiable
|
||||
lineEdit->insert(QString("%1://%2").arg(ATP_SCHEME).arg(hash));
|
||||
|
||||
// add the label and line edit to the dialog
|
||||
boxLayout->addWidget(lineEditLabel);
|
||||
boxLayout->addWidget(lineEdit);
|
||||
|
||||
// setup an OK button to close the dialog
|
||||
QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
|
||||
connect(buttonBox, &QDialogButtonBox::accepted, hashCopyDialog, &QDialog::close);
|
||||
boxLayout->addWidget(buttonBox);
|
||||
|
||||
// set the new layout on the dialog
|
||||
hashCopyDialog->setLayout(boxLayout);
|
||||
|
||||
// show the new dialog
|
||||
hashCopyDialog->show();
|
||||
} else {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
class AssetUpload;
|
||||
|
||||
class AssetUploadDialogFactory : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
@ -28,6 +30,8 @@ public:
|
|||
void setDialogParent(QWidget* dialogParent) { _dialogParent = dialogParent; }
|
||||
public slots:
|
||||
void showDialog();
|
||||
private slots:
|
||||
void handleUploadFinished(AssetUpload* upload, const QString& hash);
|
||||
private:
|
||||
QWidget* _dialogParent { nullptr };
|
||||
};
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <QThread>
|
||||
|
||||
#include "AssetRequest.h"
|
||||
#include "AssetUpload.h"
|
||||
#include "NodeList.h"
|
||||
#include "PacketReceiver.h"
|
||||
|
||||
|
@ -27,7 +28,7 @@ AssetClient::AssetClient() {
|
|||
packetReceiver.registerListener(PacketType::AssetUploadReply, this, "handleAssetUploadReply");
|
||||
}
|
||||
|
||||
AssetRequest* AssetClient::create(QString hash) {
|
||||
AssetRequest* AssetClient::createRequest(QString hash) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
AssetRequest* req;
|
||||
QMetaObject::invokeMethod(this, "create",
|
||||
|
@ -46,15 +47,32 @@ AssetRequest* AssetClient::create(QString hash) {
|
|||
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
||||
|
||||
if (assetServer) {
|
||||
auto assetClient = DependencyManager::get<AssetClient>();
|
||||
auto request = new AssetRequest(assetClient.data(), hash);
|
||||
|
||||
return request;
|
||||
return new AssetRequest(this, hash);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AssetUpload* AssetClient::createUpload(QString filename) {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
AssetUpload* upload;
|
||||
QMetaObject::invokeMethod(this, "createUpload",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(AssetUpload*, upload),
|
||||
Q_ARG(QString, filename));
|
||||
return upload;
|
||||
}
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
||||
|
||||
if (assetServer) {
|
||||
return new AssetUpload(this, filename);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool AssetClient::getAsset(QString hash, DataOffset start, DataOffset end, ReceivedAssetCallback callback) {
|
||||
if (hash.length() != HASH_HEX_LENGTH) {
|
||||
qDebug() << "Invalid hash size";
|
||||
|
@ -156,6 +174,7 @@ void AssetClient::handleAssetGetReply(QSharedPointer<NLPacketList> packetList, S
|
|||
bool AssetClient::uploadAsset(QByteArray data, QString extension, UploadResultCallback callback) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer);
|
||||
|
||||
if (assetServer) {
|
||||
auto packetList = std::unique_ptr<NLPacketList>(new NLPacketList(PacketType::AssetUpload, QByteArray(), true, true));
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "NLPacket.h"
|
||||
|
||||
class AssetRequest;
|
||||
class AssetUpload;
|
||||
|
||||
struct AssetInfo {
|
||||
QString hash;
|
||||
|
@ -36,11 +37,8 @@ class AssetClient : public QObject, public Dependency {
|
|||
public:
|
||||
AssetClient();
|
||||
|
||||
Q_INVOKABLE AssetRequest* create(QString hash);
|
||||
bool getAssetInfo(QString hash, GetInfoCallback callback);
|
||||
bool getAsset(QString hash, DataOffset start, DataOffset end, ReceivedAssetCallback callback);
|
||||
bool uploadAsset(QByteArray data, QString extension, UploadResultCallback callback);
|
||||
bool abortDataRequest(MessageID messageID);
|
||||
Q_INVOKABLE AssetRequest* createRequest(QString hash);
|
||||
Q_INVOKABLE AssetUpload* createUpload(QString filename);
|
||||
|
||||
private slots:
|
||||
void handleAssetGetInfoReply(QSharedPointer<NLPacket> packet, SharedNodePointer senderNode);
|
||||
|
@ -48,10 +46,18 @@ private slots:
|
|||
void handleAssetUploadReply(QSharedPointer<NLPacket> packet, SharedNodePointer senderNode);
|
||||
|
||||
private:
|
||||
bool getAssetInfo(QString hash, GetInfoCallback callback);
|
||||
bool getAsset(QString hash, DataOffset start, DataOffset end, ReceivedAssetCallback callback);
|
||||
bool uploadAsset(QByteArray data, QString extension, UploadResultCallback callback);
|
||||
bool abortDataRequest(MessageID messageID);
|
||||
|
||||
static MessageID _currentID;
|
||||
QHash<MessageID, ReceivedAssetCallback> _pendingRequests;
|
||||
QHash<MessageID, GetInfoCallback> _pendingInfoRequests;
|
||||
QHash<MessageID, UploadResultCallback> _pendingUploads;
|
||||
|
||||
friend class AssetRequest;
|
||||
friend class AssetUpload;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -18,7 +18,7 @@ void ATPResourceRequest::doSend() {
|
|||
auto assetClient = DependencyManager::get<AssetClient>();
|
||||
auto hash = _url.path();
|
||||
|
||||
auto request = assetClient->create(hash);
|
||||
auto request = assetClient->createRequest(hash);
|
||||
|
||||
if (!request) {
|
||||
return;
|
||||
|
|
53
libraries/networking/src/AssetUpload.cpp
Normal file
53
libraries/networking/src/AssetUpload.cpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
//
|
||||
// AssetUpload.cpp
|
||||
// libraries/networking/src
|
||||
//
|
||||
// Created by Stephen Birarda on 2015-08-26.
|
||||
// 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
|
||||
//
|
||||
|
||||
#include "AssetUpload.h"
|
||||
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QThread>
|
||||
|
||||
#include "AssetClient.h"
|
||||
|
||||
AssetUpload::AssetUpload(QObject* object, const QString& filename) :
|
||||
_filename(filename)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void AssetUpload::start() {
|
||||
if (QThread::currentThread() != thread()) {
|
||||
QMetaObject::invokeMethod(this, "start", Qt::AutoConnection);
|
||||
return;
|
||||
}
|
||||
|
||||
// try to open the file at the given filename
|
||||
QFile file { _filename };
|
||||
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
|
||||
// file opened, read the data and grab the extension
|
||||
auto extension = QFileInfo(_filename).suffix();
|
||||
|
||||
auto data = file.readAll();
|
||||
|
||||
// ask the AssetClient to upload the asset and emit the proper signals from the passed callback
|
||||
auto assetClient = DependencyManager::get<AssetClient>();
|
||||
|
||||
assetClient->uploadAsset(data, extension, [this](bool result, QString hash){
|
||||
if (result) {
|
||||
// successful upload - emit finished with a point to ourselves and the resulting hash
|
||||
emit finished(this, hash);
|
||||
} else {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
47
libraries/networking/src/AssetUpload.h
Normal file
47
libraries/networking/src/AssetUpload.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// AssetUpload.h
|
||||
// libraries/networking/src
|
||||
//
|
||||
// Created by Stephen Birarda on 2015-08-26.
|
||||
// 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
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef hifi_AssetUpload_h
|
||||
#define hifi_AssetUpload_h
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
// You should be able to upload an asset from any thread, and handle the responses in a safe way
|
||||
// on your own thread. Everything should happen on AssetClient's thread, the caller should
|
||||
// receive events by connecting to signals on an object that lives on AssetClient's threads.
|
||||
|
||||
class AssetUpload : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
enum Result {
|
||||
Success = 0,
|
||||
Timeout,
|
||||
TooLarge,
|
||||
};
|
||||
|
||||
AssetUpload(QObject* parent, const QString& filename);
|
||||
|
||||
Q_INVOKABLE void start();
|
||||
|
||||
const QString& getFilename() const { return _filename; }
|
||||
|
||||
signals:
|
||||
void finished(AssetUpload* upload, const QString& hash);
|
||||
void progress(uint64_t totalReceived, uint64_t total);
|
||||
|
||||
private:
|
||||
QString _filename;
|
||||
};
|
||||
|
||||
#endif // hifi_AssetUpload_h
|
|
@ -24,4 +24,6 @@ enum AssetServerError : uint8_t {
|
|||
INVALID_BYTE_RANGE,
|
||||
};
|
||||
|
||||
const QString ATP_SCHEME = "atp";
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue