mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-12 20:24:38 +02:00
Merge pull request #3289 from ctrlaltdavid/19840
Code Review for Job #19840
This commit is contained in:
commit
86aa9a1dcf
10 changed files with 1986 additions and 461 deletions
|
@ -59,6 +59,13 @@ UnitTest.prototype.assertEquals = function(expected, actual, message) {
|
|||
}
|
||||
};
|
||||
|
||||
UnitTest.prototype.assertContains = function (expected, actual, message) {
|
||||
this.numAssertions++;
|
||||
if (actual.indexOf(expected) == -1) {
|
||||
throw new AssertionException(expected, actual, message);
|
||||
}
|
||||
};
|
||||
|
||||
UnitTest.prototype.assertHasProperty = function(property, actual, message) {
|
||||
this.numAssertions++;
|
||||
if (actual[property] === undefined) {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -145,3 +145,98 @@ test("Test timeout", function() {
|
|||
this.assertEquals(0, req.status, "status should be `0`");
|
||||
this.assertEquals(4, req.errorCode, "4 is the timeout error code for QNetworkReply::NetworkError");
|
||||
});
|
||||
|
||||
|
||||
var localFile = Window.browse("Find defaultScripts.js file ...", "", "defaultScripts.js (defaultScripts.js)");
|
||||
|
||||
if (localFile !== null) {
|
||||
|
||||
localFile = "file:///" + localFile;
|
||||
|
||||
test("Test GET local file synchronously", function () {
|
||||
var req = new XMLHttpRequest();
|
||||
|
||||
var statesVisited = [true, false, false, false, false]
|
||||
req.onreadystatechange = function () {
|
||||
statesVisited[req.readyState] = true;
|
||||
};
|
||||
|
||||
req.open("GET", localFile, false);
|
||||
req.send();
|
||||
|
||||
this.assertEquals(req.DONE, req.readyState, "readyState should be DONE");
|
||||
this.assertEquals(200, req.status, "status should be `200`");
|
||||
this.assertEquals("OK", req.statusText, "statusText should be `OK`");
|
||||
this.assertEquals(0, req.errorCode);
|
||||
this.assertNotEquals("", req.getAllResponseHeaders(), "headers should not be null");
|
||||
this.assertContains("High Fidelity", req.response.substring(0, 100), "expected text not found in response")
|
||||
|
||||
for (var i = 0; i <= req.DONE; i++) {
|
||||
this.assertEquals(true, statesVisited[i], i + " should be set");
|
||||
}
|
||||
});
|
||||
|
||||
test("Test GET nonexistent local file", function () {
|
||||
var nonexistentFile = localFile.replace(".js", "NoExist.js");
|
||||
|
||||
var req = new XMLHttpRequest();
|
||||
req.open("GET", nonexistentFile, false);
|
||||
req.send();
|
||||
|
||||
this.assertEquals(req.DONE, req.readyState, "readyState should be DONE");
|
||||
this.assertEquals(404, req.status, "status should be `404`");
|
||||
this.assertEquals("Not Found", req.statusText, "statusText should be `Not Found`");
|
||||
this.assertNotEquals(0, req.errorCode);
|
||||
});
|
||||
|
||||
test("Test GET local file already open", function () {
|
||||
// Can't open file exclusively in order to test.
|
||||
});
|
||||
|
||||
test("Test GET local file with data not implemented", function () {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open("GET", localFile, true);
|
||||
req.send("data");
|
||||
|
||||
this.assertEquals(req.DONE, req.readyState, "readyState should be DONE");
|
||||
this.assertEquals(501, req.status, "status should be `501`");
|
||||
this.assertEquals("Not Implemented", req.statusText, "statusText should be `Not Implemented`");
|
||||
this.assertNotEquals(0, req.errorCode);
|
||||
});
|
||||
|
||||
test("Test GET local file asynchronously not implemented", function () {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open("GET", localFile, true);
|
||||
req.send();
|
||||
|
||||
this.assertEquals(req.DONE, req.readyState, "readyState should be DONE");
|
||||
this.assertEquals(501, req.status, "status should be `501`");
|
||||
this.assertEquals("Not Implemented", req.statusText, "statusText should be `Not Implemented`");
|
||||
this.assertNotEquals(0, req.errorCode);
|
||||
});
|
||||
|
||||
test("Test POST local file not implemented", function () {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open("POST", localFile, false);
|
||||
req.send();
|
||||
|
||||
this.assertEquals(req.DONE, req.readyState, "readyState should be DONE");
|
||||
this.assertEquals(501, req.status, "status should be `501`");
|
||||
this.assertEquals("Not Implemented", req.statusText, "statusText should be `Not Implemented`");
|
||||
this.assertNotEquals(0, req.errorCode);
|
||||
});
|
||||
|
||||
test("Test local file username and password not implemented", function () {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open("GET", localFile, false, "username", "password");
|
||||
req.send();
|
||||
|
||||
this.assertEquals(req.DONE, req.readyState, "readyState should be DONE");
|
||||
this.assertEquals(501, req.status, "status should be `501`");
|
||||
this.assertEquals("Not Implemented", req.statusText, "statusText should be `Not Implemented`");
|
||||
this.assertNotEquals(0, req.errorCode);
|
||||
});
|
||||
|
||||
} else {
|
||||
print("Local file operation not tested");
|
||||
}
|
||||
|
|
|
@ -186,6 +186,14 @@ ToolBar = function(x, y, direction) {
|
|||
return this.tools.length;
|
||||
}
|
||||
|
||||
this.selectTool = function (tool, select) {
|
||||
this.tools[tool].select(select);
|
||||
}
|
||||
|
||||
this.toolSelected = function (tool) {
|
||||
return this.tools[tool].selected();
|
||||
}
|
||||
|
||||
this.cleanup = function() {
|
||||
for(var tool in this.tools) {
|
||||
this.tools[tool].cleanup();
|
||||
|
|
|
@ -100,14 +100,52 @@ QScriptValue WindowScriptingInterface::showConfirm(const QString& message) {
|
|||
return QScriptValue(response == QMessageBox::Yes);
|
||||
}
|
||||
|
||||
void WindowScriptingInterface::chooseDirectory() {
|
||||
QPushButton* button = reinterpret_cast<QPushButton*>(sender());
|
||||
|
||||
QString title = button->property("title").toString();
|
||||
QString path = button->property("path").toString();
|
||||
QRegExp displayAs = button->property("displayAs").toRegExp();
|
||||
QRegExp validateAs = button->property("validateAs").toRegExp();
|
||||
QString errorMessage = button->property("errorMessage").toString();
|
||||
|
||||
QString directory = QFileDialog::getExistingDirectory(button, title, path);
|
||||
if (directory.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!validateAs.exactMatch(directory)) {
|
||||
QMessageBox::warning(NULL, "Invalid Directory", errorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
button->setProperty("path", directory);
|
||||
|
||||
displayAs.indexIn(directory);
|
||||
QString buttonText = displayAs.cap(1) != "" ? displayAs.cap(1) : ".";
|
||||
button->setText(buttonText);
|
||||
}
|
||||
|
||||
QString WindowScriptingInterface::jsRegExp2QtRegExp(QString string) {
|
||||
// Converts string representation of RegExp from JavaScript format to Qt format.
|
||||
return string.mid(1, string.length() - 2) // No enclosing slashes.
|
||||
.replace("\\/", "/"); // No escaping of forward slash.
|
||||
}
|
||||
|
||||
/// Display a form layout with an edit box
|
||||
/// \param const QString& title title to display
|
||||
/// \param const QScriptValue form to display (array containing labels and values)
|
||||
/// \return QScriptValue result form (unchanged is dialog canceled)
|
||||
/// \param const QScriptValue form to display as an array of objects:
|
||||
/// - label, value
|
||||
/// - label, directory, title, display regexp, validate regexp, error message
|
||||
/// - button ("Cancel")
|
||||
/// \return QScriptValue `true` if 'OK' was clicked, `false` otherwise
|
||||
QScriptValue WindowScriptingInterface::showForm(const QString& title, QScriptValue form) {
|
||||
|
||||
if (form.isArray() && form.property("length").toInt32() > 0) {
|
||||
QDialog* editDialog = new QDialog(Application::getInstance()->getWindow());
|
||||
editDialog->setWindowTitle(title);
|
||||
|
||||
bool cancelButton = false;
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout();
|
||||
editDialog->setLayout(layout);
|
||||
|
@ -127,44 +165,104 @@ QScriptValue WindowScriptingInterface::showForm(const QString& title, QScriptVal
|
|||
area->setWidget(container);
|
||||
|
||||
QVector<QLineEdit*> edits;
|
||||
QVector<QPushButton*> directories;
|
||||
for (int i = 0; i < form.property("length").toInt32(); ++i) {
|
||||
QScriptValue item = form.property(i);
|
||||
edits.push_back(new QLineEdit(item.property("value").toString()));
|
||||
formLayout->addRow(item.property("label").toString(), edits.back());
|
||||
|
||||
if (item.property("button").toString() != "") {
|
||||
cancelButton = cancelButton || item.property("button").toString().toLower() == "cancel";
|
||||
|
||||
} else if (item.property("directory").toString() != "") {
|
||||
QString path = item.property("directory").toString();
|
||||
QString title = item.property("title").toString();
|
||||
if (title == "") {
|
||||
title = "Choose Directory";
|
||||
}
|
||||
QString displayAsString = item.property("displayAs").toString();
|
||||
QRegExp displayAs = QRegExp(displayAsString != "" ? jsRegExp2QtRegExp(displayAsString) : "^(.*)$");
|
||||
QString validateAsString = item.property("validateAs").toString();
|
||||
QRegExp validateAs = QRegExp(validateAsString != "" ? jsRegExp2QtRegExp(validateAsString) : ".*");
|
||||
QString errorMessage = item.property("errorMessage").toString();
|
||||
if (errorMessage == "") {
|
||||
errorMessage = "Invalid directory";
|
||||
}
|
||||
|
||||
QPushButton* directory = new QPushButton(displayAs.cap(1));
|
||||
directory->setProperty("title", title);
|
||||
directory->setProperty("path", path);
|
||||
directory->setProperty("displayAs", displayAs);
|
||||
directory->setProperty("validateAs", validateAs);
|
||||
directory->setProperty("errorMessage", errorMessage);
|
||||
displayAs.indexIn(path);
|
||||
directory->setText(displayAs.cap(1) != "" ? displayAs.cap(1) : ".");
|
||||
|
||||
directory->setMinimumWidth(200);
|
||||
directories.push_back(directory);
|
||||
|
||||
formLayout->addRow(new QLabel(item.property("label").toString()), directory);
|
||||
connect(directory, SIGNAL(clicked(bool)), SLOT(chooseDirectory()));
|
||||
|
||||
} else {
|
||||
QLineEdit* edit = new QLineEdit(item.property("value").toString());
|
||||
edit->setMinimumWidth(200);
|
||||
edits.push_back(edit);
|
||||
formLayout->addRow(new QLabel(item.property("label").toString()), edit);
|
||||
}
|
||||
}
|
||||
QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok);
|
||||
|
||||
QDialogButtonBox* buttons = new QDialogButtonBox(
|
||||
QDialogButtonBox::Ok
|
||||
| (cancelButton ? QDialogButtonBox::Cancel : QDialogButtonBox::NoButton)
|
||||
);
|
||||
connect(buttons, SIGNAL(accepted()), editDialog, SLOT(accept()));
|
||||
connect(buttons, SIGNAL(rejected()), editDialog, SLOT(reject()));
|
||||
layout->addWidget(buttons);
|
||||
|
||||
if (editDialog->exec() == QDialog::Accepted) {
|
||||
int result = editDialog->exec();
|
||||
if (result == QDialog::Accepted) {
|
||||
int e = -1;
|
||||
int d = -1;
|
||||
for (int i = 0; i < form.property("length").toInt32(); ++i) {
|
||||
QScriptValue item = form.property(i);
|
||||
QScriptValue value = item.property("value");
|
||||
bool ok = true;
|
||||
if (value.isNumber()) {
|
||||
value = edits.at(i)->text().toDouble(&ok);
|
||||
} else if (value.isString()) {
|
||||
value = edits.at(i)->text();
|
||||
} else if (value.isBool()) {
|
||||
if (edits.at(i)->text() == "true") {
|
||||
value = true;
|
||||
} else if (edits.at(i)->text() == "false") {
|
||||
value = false;
|
||||
} else {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
item.setProperty("value", value);
|
||||
|
||||
if (item.property("button").toString() != "") {
|
||||
// Nothing to do
|
||||
} else if (item.property("directory").toString() != "") {
|
||||
d += 1;
|
||||
value = directories.at(d)->property("path").toString();
|
||||
item.setProperty("directory", value);
|
||||
form.setProperty(i, item);
|
||||
} else {
|
||||
e += 1;
|
||||
bool ok = true;
|
||||
if (value.isNumber()) {
|
||||
value = edits.at(e)->text().toDouble(&ok);
|
||||
} else if (value.isString()) {
|
||||
value = edits.at(e)->text();
|
||||
} else if (value.isBool()) {
|
||||
if (edits.at(e)->text() == "true") {
|
||||
value = true;
|
||||
} else if (edits.at(e)->text() == "false") {
|
||||
value = false;
|
||||
} else {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
item.setProperty("value", value);
|
||||
form.setProperty(i, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete editDialog;
|
||||
|
||||
return (result == QDialog::Accepted);
|
||||
}
|
||||
|
||||
return form;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Display a prompt with a text box
|
||||
|
|
|
@ -42,9 +42,12 @@ private slots:
|
|||
QScriptValue showBrowse(const QString& title, const QString& directory, const QString& nameFilter,
|
||||
QFileDialog::AcceptMode acceptMode = QFileDialog::AcceptOpen);
|
||||
QScriptValue showS3Browse(const QString& nameFilter);
|
||||
void chooseDirectory();
|
||||
|
||||
private:
|
||||
WindowScriptingInterface();
|
||||
|
||||
QString jsRegExp2QtRegExp(QString string);
|
||||
};
|
||||
|
||||
#endif // hifi_WindowScriptingInterface_h
|
||||
|
|
|
@ -11,9 +11,15 @@
|
|||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include <QBuffer>
|
||||
#include <QImage>
|
||||
|
||||
#include "ArrayBufferClass.h"
|
||||
#include "ArrayBufferPrototype.h"
|
||||
|
||||
static const int QCOMPRESS_HEADER_POSITION = 0;
|
||||
static const int QCOMPRESS_HEADER_SIZE = 4;
|
||||
|
||||
Q_DECLARE_METATYPE(QByteArray*)
|
||||
|
||||
ArrayBufferPrototype::ArrayBufferPrototype(QObject* parent) : QObject(parent) {
|
||||
|
@ -43,6 +49,41 @@ QByteArray ArrayBufferPrototype::slice(qint32 begin) const {
|
|||
return ba->mid(begin, -1);
|
||||
}
|
||||
|
||||
QByteArray ArrayBufferPrototype::compress() const {
|
||||
// Compresses the ArrayBuffer data in Zlib format.
|
||||
QByteArray* ba = thisArrayBuffer();
|
||||
|
||||
QByteArray buffer = qCompress(*ba);
|
||||
buffer.remove(QCOMPRESS_HEADER_POSITION, QCOMPRESS_HEADER_SIZE); // Remove Qt's custom header to make it proper Zlib.
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
QByteArray ArrayBufferPrototype::recodeImage(const QString& sourceFormat, const QString& targetFormat, qint32 maxSize) const {
|
||||
// Recodes image data if sourceFormat and targetFormat are different.
|
||||
// Rescales image data if either dimension is greater than the specified maximum.
|
||||
QByteArray* ba = thisArrayBuffer();
|
||||
|
||||
bool mustRecode = sourceFormat.toLower() != targetFormat.toLower();
|
||||
|
||||
QImage image = QImage::fromData(*ba);
|
||||
if (image.width() > maxSize || image.height() > maxSize) {
|
||||
image = image.scaled(maxSize, maxSize, Qt::KeepAspectRatio);
|
||||
mustRecode = true;
|
||||
}
|
||||
|
||||
if (mustRecode) {
|
||||
QBuffer buffer;
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
std::string str = targetFormat.toUpper().toStdString();
|
||||
const char* format = str.c_str();
|
||||
image.save(&buffer, format);
|
||||
return buffer.data();
|
||||
}
|
||||
|
||||
return *ba;
|
||||
}
|
||||
|
||||
QByteArray* ArrayBufferPrototype::thisArrayBuffer() const {
|
||||
return qscriptvalue_cast<QByteArray*>(thisObject().data());
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ public:
|
|||
public slots:
|
||||
QByteArray slice(qint32 begin, qint32 end) const;
|
||||
QByteArray slice(qint32 begin) const;
|
||||
QByteArray compress() const;
|
||||
QByteArray recodeImage(const QString& sourceFormat, const QString& targetFormat, qint32 maxSize) const;
|
||||
|
||||
private:
|
||||
QByteArray* thisArrayBuffer() const;
|
||||
|
|
|
@ -13,10 +13,15 @@
|
|||
//
|
||||
|
||||
#include <QEventLoop>
|
||||
#include <QFile>
|
||||
|
||||
#include <NetworkAccessManager.h>
|
||||
|
||||
#include <AccountManager.h>
|
||||
#include "XMLHttpRequestClass.h"
|
||||
#include "ScriptEngine.h"
|
||||
|
||||
Q_DECLARE_METATYPE(QByteArray*)
|
||||
|
||||
XMLHttpRequestClass::XMLHttpRequestClass(QScriptEngine* engine) :
|
||||
_engine(engine),
|
||||
|
@ -33,6 +38,7 @@ XMLHttpRequestClass::XMLHttpRequestClass(QScriptEngine* engine) :
|
|||
_onReadyStateChange(QScriptValue::NullValue),
|
||||
_readyState(XMLHttpRequestClass::UNSENT),
|
||||
_errorCode(QNetworkReply::NoError),
|
||||
_file(NULL),
|
||||
_timeout(0),
|
||||
_timer(this),
|
||||
_numRedirects(0) {
|
||||
|
@ -52,6 +58,20 @@ QScriptValue XMLHttpRequestClass::constructor(QScriptContext* context, QScriptEn
|
|||
QScriptValue XMLHttpRequestClass::getStatus() const {
|
||||
if (_reply) {
|
||||
return QScriptValue(_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt());
|
||||
}
|
||||
if(_url.isLocalFile()) {
|
||||
switch (_errorCode) {
|
||||
case QNetworkReply::NoError:
|
||||
return QScriptValue(200);
|
||||
case QNetworkReply::ContentNotFoundError:
|
||||
return QScriptValue(404);
|
||||
case QNetworkReply::ContentAccessDenied:
|
||||
return QScriptValue(409);
|
||||
case QNetworkReply::TimeoutError:
|
||||
return QScriptValue(408);
|
||||
case QNetworkReply::ContentOperationNotPermittedError:
|
||||
return QScriptValue(501);
|
||||
}
|
||||
}
|
||||
return QScriptValue(0);
|
||||
}
|
||||
|
@ -60,6 +80,20 @@ QString XMLHttpRequestClass::getStatusText() const {
|
|||
if (_reply) {
|
||||
return _reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
|
||||
}
|
||||
if (_url.isLocalFile()) {
|
||||
switch (_errorCode) {
|
||||
case QNetworkReply::NoError:
|
||||
return "OK";
|
||||
case QNetworkReply::ContentNotFoundError:
|
||||
return "Not Found";
|
||||
case QNetworkReply::ContentAccessDenied:
|
||||
return "Conflict";
|
||||
case QNetworkReply::TimeoutError:
|
||||
return "Timeout";
|
||||
case QNetworkReply::ContentOperationNotPermittedError:
|
||||
return "Not Implemented";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
@ -104,6 +138,13 @@ QScriptValue XMLHttpRequestClass::getAllResponseHeaders() const {
|
|||
}
|
||||
return QString(headers.data());
|
||||
}
|
||||
if (_url.isLocalFile()) {
|
||||
QString headers = QString("Content-Type: application/octet-stream\n");
|
||||
headers.append("Content-Length: ");
|
||||
headers.append(QString("%1").arg(_rawResponseData.length()));
|
||||
headers.append("\n");
|
||||
return headers;
|
||||
}
|
||||
return QScriptValue("");
|
||||
}
|
||||
|
||||
|
@ -111,6 +152,14 @@ QScriptValue XMLHttpRequestClass::getResponseHeader(const QString& name) const {
|
|||
if (_reply && _reply->hasRawHeader(name.toLatin1())) {
|
||||
return QScriptValue(QString(_reply->rawHeader(name.toLatin1())));
|
||||
}
|
||||
if (_url.isLocalFile()) {
|
||||
if (name.toLower() == "content-type") {
|
||||
return QString("application/octet-stream");
|
||||
}
|
||||
if (name.toLower() == "content-length") {
|
||||
return QString("%1").arg(_rawResponseData.length());
|
||||
}
|
||||
}
|
||||
return QScriptValue::NullValue;
|
||||
}
|
||||
|
||||
|
@ -126,34 +175,72 @@ void XMLHttpRequestClass::setReadyState(ReadyState readyState) {
|
|||
void XMLHttpRequestClass::open(const QString& method, const QString& url, bool async, const QString& username,
|
||||
const QString& password) {
|
||||
if (_readyState == UNSENT) {
|
||||
_async = async;
|
||||
_url.setUrl(url);
|
||||
if (!username.isEmpty()) {
|
||||
_url.setUserName(username);
|
||||
}
|
||||
if (!password.isEmpty()) {
|
||||
_url.setPassword(password);
|
||||
}
|
||||
_request.setUrl(_url);
|
||||
_method = method;
|
||||
setReadyState(OPENED);
|
||||
_url.setUrl(url);
|
||||
_async = async;
|
||||
|
||||
if (_url.isLocalFile()) {
|
||||
if (_method.toUpper() == "GET" && !_async && username.isEmpty() && password.isEmpty()) {
|
||||
_file = new QFile(_url.toLocalFile());
|
||||
if (!_file->exists()) {
|
||||
qDebug() << "Can't find file " << _url.fileName();
|
||||
abortRequest();
|
||||
_errorCode = QNetworkReply::ContentNotFoundError;
|
||||
setReadyState(DONE);
|
||||
emit requestComplete();
|
||||
} else if (!_file->open(QIODevice::ReadOnly)) {
|
||||
qDebug() << "Can't open file " << _url.fileName();
|
||||
abortRequest();
|
||||
//_errorCode = QNetworkReply::ContentConflictError; // TODO: Use this status when update to Qt 5.3
|
||||
_errorCode = QNetworkReply::ContentAccessDenied;
|
||||
setReadyState(DONE);
|
||||
emit requestComplete();
|
||||
} else {
|
||||
setReadyState(OPENED);
|
||||
}
|
||||
} else {
|
||||
notImplemented();
|
||||
}
|
||||
} else {
|
||||
if (url.toLower().left(33) == "https://data.highfidelity.io/api/") {
|
||||
_url.setQuery("access_token=" + AccountManager::getInstance().getAccountInfo().getAccessToken().token);
|
||||
}
|
||||
if (!username.isEmpty()) {
|
||||
_url.setUserName(username);
|
||||
}
|
||||
if (!password.isEmpty()) {
|
||||
_url.setPassword(password);
|
||||
}
|
||||
_request.setUrl(_url);
|
||||
setReadyState(OPENED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void XMLHttpRequestClass::send() {
|
||||
send(QString::Null());
|
||||
send(QScriptValue::NullValue);
|
||||
}
|
||||
|
||||
void XMLHttpRequestClass::send(const QString& data) {
|
||||
void XMLHttpRequestClass::send(const QScriptValue& data) {
|
||||
if (_readyState == OPENED && !_reply) {
|
||||
if (!data.isNull()) {
|
||||
_sendData = new QBuffer(this);
|
||||
_sendData->setData(data.toUtf8());
|
||||
if (_url.isLocalFile()) {
|
||||
notImplemented();
|
||||
return;
|
||||
} else {
|
||||
_sendData = new QBuffer(this);
|
||||
if (data.isObject()) {
|
||||
QByteArray ba = qscriptvalue_cast<QByteArray>(data);
|
||||
_sendData->setData(ba);
|
||||
} else {
|
||||
_sendData->setData(data.toString().toUtf8());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doSend();
|
||||
|
||||
if (!_async) {
|
||||
if (!_async && !_url.isLocalFile()) {
|
||||
QEventLoop loop;
|
||||
connect(this, SIGNAL(requestComplete()), &loop, SLOT(quit()));
|
||||
loop.exec();
|
||||
|
@ -162,14 +249,24 @@ void XMLHttpRequestClass::send(const QString& data) {
|
|||
}
|
||||
|
||||
void XMLHttpRequestClass::doSend() {
|
||||
_reply = NetworkAccessManager::getInstance().sendCustomRequest(_request, _method.toLatin1(), _sendData);
|
||||
|
||||
connectToReply(_reply);
|
||||
|
||||
if (!_url.isLocalFile()) {
|
||||
_reply = NetworkAccessManager::getInstance().sendCustomRequest(_request, _method.toLatin1(), _sendData);
|
||||
connectToReply(_reply);
|
||||
}
|
||||
|
||||
if (_timeout > 0) {
|
||||
_timer.start(_timeout);
|
||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(requestTimeout()));
|
||||
}
|
||||
|
||||
if (_url.isLocalFile()) {
|
||||
setReadyState(HEADERS_RECEIVED);
|
||||
setReadyState(LOADING);
|
||||
_rawResponseData = _file->readAll();
|
||||
_file->close();
|
||||
requestFinished();
|
||||
}
|
||||
}
|
||||
|
||||
void XMLHttpRequestClass::requestTimeout() {
|
||||
|
@ -188,9 +285,16 @@ void XMLHttpRequestClass::requestError(QNetworkReply::NetworkError code) {
|
|||
void XMLHttpRequestClass::requestFinished() {
|
||||
disconnect(&_timer, SIGNAL(timeout()), this, SLOT(requestTimeout()));
|
||||
|
||||
_errorCode = _reply->error();
|
||||
if (!_url.isLocalFile()) {
|
||||
_errorCode = _reply->error();
|
||||
} else {
|
||||
_errorCode = QNetworkReply::NoError;
|
||||
}
|
||||
|
||||
if (_errorCode == QNetworkReply::NoError) {
|
||||
_rawResponseData.append(_reply->readAll());
|
||||
if (!_url.isLocalFile()) {
|
||||
_rawResponseData.append(_reply->readAll());
|
||||
}
|
||||
|
||||
if (_responseType == "json") {
|
||||
_responseData = _engine->evaluate("(" + QString(_rawResponseData.data()) + ")");
|
||||
|
@ -199,11 +303,13 @@ void XMLHttpRequestClass::requestFinished() {
|
|||
_responseData = QScriptValue::NullValue;
|
||||
}
|
||||
} else if (_responseType == "arraybuffer") {
|
||||
_responseData = QScriptValue(_rawResponseData.data());
|
||||
QScriptValue data = _engine->newVariant(QVariant::fromValue(_rawResponseData));
|
||||
_responseData = _engine->newObject(reinterpret_cast<ScriptEngine*>(_engine)->getArrayBufferClass(), data);
|
||||
} else {
|
||||
_responseData = QScriptValue(QString(_rawResponseData.data()));
|
||||
}
|
||||
}
|
||||
|
||||
setReadyState(DONE);
|
||||
emit requestComplete();
|
||||
}
|
||||
|
@ -217,6 +323,19 @@ void XMLHttpRequestClass::abortRequest() {
|
|||
delete _reply;
|
||||
_reply = NULL;
|
||||
}
|
||||
|
||||
if (_file != NULL) {
|
||||
_file->close();
|
||||
_file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void XMLHttpRequestClass::notImplemented() {
|
||||
abortRequest();
|
||||
//_errorCode = QNetworkReply::OperationNotImplementedError; TODO: Use this status code when update to Qt 5.3
|
||||
_errorCode = QNetworkReply::ContentOperationNotPermittedError;
|
||||
setReadyState(DONE);
|
||||
emit requestComplete();
|
||||
}
|
||||
|
||||
void XMLHttpRequestClass::connectToReply(QNetworkReply* reply) {
|
||||
|
|
|
@ -84,7 +84,7 @@ public slots:
|
|||
void open(const QString& method, const QString& url, bool async = true, const QString& username = "",
|
||||
const QString& password = "");
|
||||
void send();
|
||||
void send(const QString& data);
|
||||
void send(const QScriptValue& data);
|
||||
QScriptValue getAllResponseHeaders() const;
|
||||
QScriptValue getResponseHeader(const QString& name) const;
|
||||
|
||||
|
@ -97,6 +97,7 @@ private:
|
|||
void connectToReply(QNetworkReply* reply);
|
||||
void disconnectFromReply(QNetworkReply* reply);
|
||||
void abortRequest();
|
||||
void notImplemented();
|
||||
|
||||
QScriptEngine* _engine;
|
||||
bool _async;
|
||||
|
@ -112,6 +113,7 @@ private:
|
|||
QScriptValue _onReadyStateChange;
|
||||
ReadyState _readyState;
|
||||
QNetworkReply::NetworkError _errorCode;
|
||||
QFile* _file;
|
||||
int _timeout;
|
||||
QTimer _timer;
|
||||
int _numRedirects;
|
||||
|
|
Loading…
Reference in a new issue