mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 17:00:13 +02:00
Merge branch 'master' of git://github.com/highfidelity/hifi into 19779
Conflicts: interface/src/location/LocationManager.cpp
This commit is contained in:
commit
a13810bd72
17 changed files with 605 additions and 495 deletions
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#include <AccountManager.h>
|
#include <AccountManager.h>
|
||||||
#include <Assignment.h>
|
#include <Assignment.h>
|
||||||
|
#include <HifiConfigVariantMap.h>
|
||||||
#include <Logging.h>
|
#include <Logging.h>
|
||||||
#include <NodeList.h>
|
#include <NodeList.h>
|
||||||
#include <PacketHeaders.h>
|
#include <PacketHeaders.h>
|
||||||
|
@ -41,73 +42,65 @@ AssignmentClient::AssignmentClient(int &argc, char **argv) :
|
||||||
setOrganizationDomain("highfidelity.io");
|
setOrganizationDomain("highfidelity.io");
|
||||||
setApplicationName("assignment-client");
|
setApplicationName("assignment-client");
|
||||||
QSettings::setDefaultFormat(QSettings::IniFormat);
|
QSettings::setDefaultFormat(QSettings::IniFormat);
|
||||||
|
|
||||||
QStringList argumentList = arguments();
|
|
||||||
|
|
||||||
// register meta type is required for queued invoke method on Assignment subclasses
|
|
||||||
|
|
||||||
// set the logging target to the the CHILD_TARGET_NAME
|
// set the logging target to the the CHILD_TARGET_NAME
|
||||||
Logging::setTargetName(ASSIGNMENT_CLIENT_TARGET_NAME);
|
Logging::setTargetName(ASSIGNMENT_CLIENT_TARGET_NAME);
|
||||||
|
|
||||||
const QString ASSIGNMENT_TYPE_OVVERIDE_OPTION = "-t";
|
const QVariantMap argumentVariantMap = HifiConfigVariantMap::mergeCLParametersWithJSONConfig(arguments());
|
||||||
int argumentIndex = argumentList.indexOf(ASSIGNMENT_TYPE_OVVERIDE_OPTION);
|
|
||||||
|
const QString ASSIGNMENT_TYPE_OVERRIDE_OPTION = "t";
|
||||||
|
const QString ASSIGNMENT_POOL_OPTION = "pool";
|
||||||
|
const QString ASSIGNMENT_WALLET_DESTINATION_ID_OPTION = "wallet";
|
||||||
|
const QString CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION = "a";
|
||||||
|
|
||||||
Assignment::Type requestAssignmentType = Assignment::AllTypes;
|
Assignment::Type requestAssignmentType = Assignment::AllTypes;
|
||||||
|
|
||||||
if (argumentIndex != -1) {
|
// check for an assignment type passed on the command line or in the config
|
||||||
requestAssignmentType = (Assignment::Type) argumentList[argumentIndex + 1].toInt();
|
if (argumentVariantMap.contains(ASSIGNMENT_TYPE_OVERRIDE_OPTION)) {
|
||||||
|
requestAssignmentType = (Assignment::Type) argumentVariantMap.value(ASSIGNMENT_TYPE_OVERRIDE_OPTION).toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString ASSIGNMENT_POOL_OPTION = "--pool";
|
|
||||||
|
|
||||||
argumentIndex = argumentList.indexOf(ASSIGNMENT_POOL_OPTION);
|
|
||||||
|
|
||||||
QString assignmentPool;
|
QString assignmentPool;
|
||||||
|
|
||||||
if (argumentIndex != -1) {
|
// check for an assignment pool passed on the command line or in the config
|
||||||
assignmentPool = argumentList[argumentIndex + 1];
|
if (argumentVariantMap.contains(ASSIGNMENT_POOL_OPTION)) {
|
||||||
|
assignmentPool = argumentVariantMap.value(ASSIGNMENT_POOL_OPTION).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup our _requestAssignment member variable from the passed arguments
|
// setup our _requestAssignment member variable from the passed arguments
|
||||||
_requestAssignment = Assignment(Assignment::RequestCommand, requestAssignmentType, assignmentPool);
|
_requestAssignment = Assignment(Assignment::RequestCommand, requestAssignmentType, assignmentPool);
|
||||||
|
|
||||||
// check if we were passed a wallet UUID on the command line
|
// check for a wallet UUID on the command line or in the config
|
||||||
// this would represent where the user running AC wants funds sent to
|
// this would represent where the user running AC wants funds sent to
|
||||||
|
if (argumentVariantMap.contains(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) {
|
||||||
const QString ASSIGNMENT_WALLET_DESTINATION_ID_OPTION = "--wallet";
|
QUuid walletUUID = argumentVariantMap.value(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION).toString();
|
||||||
if ((argumentIndex = argumentList.indexOf(ASSIGNMENT_WALLET_DESTINATION_ID_OPTION)) != -1) {
|
|
||||||
QUuid walletUUID = QString(argumentList[argumentIndex + 1]);
|
|
||||||
qDebug() << "The destination wallet UUID for credits is" << uuidStringWithoutCurlyBraces(walletUUID);
|
qDebug() << "The destination wallet UUID for credits is" << uuidStringWithoutCurlyBraces(walletUUID);
|
||||||
_requestAssignment.setWalletUUID(walletUUID);
|
_requestAssignment.setWalletUUID(walletUUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a NodeList as an unassigned client
|
// create a NodeList as an unassigned client
|
||||||
NodeList* nodeList = NodeList::createInstance(NodeType::Unassigned);
|
NodeList* nodeList = NodeList::createInstance(NodeType::Unassigned);
|
||||||
|
|
||||||
// check for an overriden assignment server hostname
|
// check for an overriden assignment server hostname
|
||||||
const QString CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION = "-a";
|
if (argumentVariantMap.contains(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION)) {
|
||||||
|
_assignmentServerHostname = argumentVariantMap.value(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION).toString();
|
||||||
argumentIndex = argumentList.indexOf(CUSTOM_ASSIGNMENT_SERVER_HOSTNAME_OPTION);
|
|
||||||
|
|
||||||
if (argumentIndex != -1) {
|
|
||||||
_assignmentServerHostname = argumentList[argumentIndex + 1];
|
|
||||||
|
|
||||||
// set the custom assignment socket on our NodeList
|
// set the custom assignment socket on our NodeList
|
||||||
HifiSockAddr customAssignmentSocket = HifiSockAddr(_assignmentServerHostname, DEFAULT_DOMAIN_SERVER_PORT);
|
HifiSockAddr customAssignmentSocket = HifiSockAddr(_assignmentServerHostname, DEFAULT_DOMAIN_SERVER_PORT);
|
||||||
|
|
||||||
nodeList->setAssignmentServerSocket(customAssignmentSocket);
|
nodeList->setAssignmentServerSocket(customAssignmentSocket);
|
||||||
}
|
}
|
||||||
|
|
||||||
// call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required
|
// call a timer function every ASSIGNMENT_REQUEST_INTERVAL_MSECS to ask for assignment, if required
|
||||||
qDebug() << "Waiting for assignment -" << _requestAssignment;
|
qDebug() << "Waiting for assignment -" << _requestAssignment;
|
||||||
|
|
||||||
QTimer* timer = new QTimer(this);
|
QTimer* timer = new QTimer(this);
|
||||||
connect(timer, SIGNAL(timeout()), SLOT(sendAssignmentRequest()));
|
connect(timer, SIGNAL(timeout()), SLOT(sendAssignmentRequest()));
|
||||||
timer->start(ASSIGNMENT_REQUEST_INTERVAL_MSECS);
|
timer->start(ASSIGNMENT_REQUEST_INTERVAL_MSECS);
|
||||||
|
|
||||||
// connect our readPendingDatagrams method to the readyRead() signal of the socket
|
// connect our readPendingDatagrams method to the readyRead() signal of the socket
|
||||||
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams);
|
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams);
|
||||||
|
|
||||||
// connections to AccountManager for authentication
|
// connections to AccountManager for authentication
|
||||||
connect(&AccountManager::getInstance(), &AccountManager::authRequired,
|
connect(&AccountManager::getInstance(), &AccountManager::authRequired,
|
||||||
this, &AssignmentClient::handleAuthenticationRequest);
|
this, &AssignmentClient::handleAuthenticationRequest);
|
||||||
|
@ -121,49 +114,49 @@ void AssignmentClient::sendAssignmentRequest() {
|
||||||
|
|
||||||
void AssignmentClient::readPendingDatagrams() {
|
void AssignmentClient::readPendingDatagrams() {
|
||||||
NodeList* nodeList = NodeList::getInstance();
|
NodeList* nodeList = NodeList::getInstance();
|
||||||
|
|
||||||
QByteArray receivedPacket;
|
QByteArray receivedPacket;
|
||||||
HifiSockAddr senderSockAddr;
|
HifiSockAddr senderSockAddr;
|
||||||
|
|
||||||
while (nodeList->getNodeSocket().hasPendingDatagrams()) {
|
while (nodeList->getNodeSocket().hasPendingDatagrams()) {
|
||||||
receivedPacket.resize(nodeList->getNodeSocket().pendingDatagramSize());
|
receivedPacket.resize(nodeList->getNodeSocket().pendingDatagramSize());
|
||||||
nodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(),
|
nodeList->getNodeSocket().readDatagram(receivedPacket.data(), receivedPacket.size(),
|
||||||
senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer());
|
senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer());
|
||||||
|
|
||||||
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
|
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
|
||||||
if (packetTypeForPacket(receivedPacket) == PacketTypeCreateAssignment) {
|
if (packetTypeForPacket(receivedPacket) == PacketTypeCreateAssignment) {
|
||||||
// construct the deployed assignment from the packet data
|
// construct the deployed assignment from the packet data
|
||||||
_currentAssignment = SharedAssignmentPointer(AssignmentFactory::unpackAssignment(receivedPacket));
|
_currentAssignment = SharedAssignmentPointer(AssignmentFactory::unpackAssignment(receivedPacket));
|
||||||
|
|
||||||
if (_currentAssignment) {
|
if (_currentAssignment) {
|
||||||
qDebug() << "Received an assignment -" << *_currentAssignment;
|
qDebug() << "Received an assignment -" << *_currentAssignment;
|
||||||
|
|
||||||
// switch our DomainHandler hostname and port to whoever sent us the assignment
|
// switch our DomainHandler hostname and port to whoever sent us the assignment
|
||||||
|
|
||||||
nodeList->getDomainHandler().setSockAddr(senderSockAddr, _assignmentServerHostname);
|
nodeList->getDomainHandler().setSockAddr(senderSockAddr, _assignmentServerHostname);
|
||||||
nodeList->getDomainHandler().setAssignmentUUID(_currentAssignment->getUUID());
|
nodeList->getDomainHandler().setAssignmentUUID(_currentAssignment->getUUID());
|
||||||
|
|
||||||
qDebug() << "Destination IP for assignment is" << nodeList->getDomainHandler().getIP().toString();
|
qDebug() << "Destination IP for assignment is" << nodeList->getDomainHandler().getIP().toString();
|
||||||
|
|
||||||
// start the deployed assignment
|
// start the deployed assignment
|
||||||
AssignmentThread* workerThread = new AssignmentThread(_currentAssignment, this);
|
AssignmentThread* workerThread = new AssignmentThread(_currentAssignment, this);
|
||||||
|
|
||||||
connect(workerThread, &QThread::started, _currentAssignment.data(), &ThreadedAssignment::run);
|
connect(workerThread, &QThread::started, _currentAssignment.data(), &ThreadedAssignment::run);
|
||||||
connect(_currentAssignment.data(), &ThreadedAssignment::finished, workerThread, &QThread::quit);
|
connect(_currentAssignment.data(), &ThreadedAssignment::finished, workerThread, &QThread::quit);
|
||||||
connect(_currentAssignment.data(), &ThreadedAssignment::finished,
|
connect(_currentAssignment.data(), &ThreadedAssignment::finished,
|
||||||
this, &AssignmentClient::assignmentCompleted);
|
this, &AssignmentClient::assignmentCompleted);
|
||||||
connect(workerThread, &QThread::finished, workerThread, &QThread::deleteLater);
|
connect(workerThread, &QThread::finished, workerThread, &QThread::deleteLater);
|
||||||
|
|
||||||
_currentAssignment->moveToThread(workerThread);
|
_currentAssignment->moveToThread(workerThread);
|
||||||
|
|
||||||
// move the NodeList to the thread used for the _current assignment
|
// move the NodeList to the thread used for the _current assignment
|
||||||
nodeList->moveToThread(workerThread);
|
nodeList->moveToThread(workerThread);
|
||||||
|
|
||||||
// let the assignment handle the incoming datagrams for its duration
|
// let the assignment handle the incoming datagrams for its duration
|
||||||
disconnect(&nodeList->getNodeSocket(), 0, this, 0);
|
disconnect(&nodeList->getNodeSocket(), 0, this, 0);
|
||||||
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, _currentAssignment.data(),
|
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, _currentAssignment.data(),
|
||||||
&ThreadedAssignment::readPendingDatagrams);
|
&ThreadedAssignment::readPendingDatagrams);
|
||||||
|
|
||||||
// Starts an event loop, and emits workerThread->started()
|
// Starts an event loop, and emits workerThread->started()
|
||||||
workerThread->start();
|
workerThread->start();
|
||||||
} else {
|
} else {
|
||||||
|
@ -180,15 +173,15 @@ void AssignmentClient::readPendingDatagrams() {
|
||||||
void AssignmentClient::handleAuthenticationRequest() {
|
void AssignmentClient::handleAuthenticationRequest() {
|
||||||
const QString DATA_SERVER_USERNAME_ENV = "HIFI_AC_USERNAME";
|
const QString DATA_SERVER_USERNAME_ENV = "HIFI_AC_USERNAME";
|
||||||
const QString DATA_SERVER_PASSWORD_ENV = "HIFI_AC_PASSWORD";
|
const QString DATA_SERVER_PASSWORD_ENV = "HIFI_AC_PASSWORD";
|
||||||
|
|
||||||
// this node will be using an authentication server, let's make sure we have a username/password
|
// this node will be using an authentication server, let's make sure we have a username/password
|
||||||
QProcessEnvironment sysEnvironment = QProcessEnvironment::systemEnvironment();
|
QProcessEnvironment sysEnvironment = QProcessEnvironment::systemEnvironment();
|
||||||
|
|
||||||
QString username = sysEnvironment.value(DATA_SERVER_USERNAME_ENV);
|
QString username = sysEnvironment.value(DATA_SERVER_USERNAME_ENV);
|
||||||
QString password = sysEnvironment.value(DATA_SERVER_PASSWORD_ENV);
|
QString password = sysEnvironment.value(DATA_SERVER_PASSWORD_ENV);
|
||||||
|
|
||||||
AccountManager& accountManager = AccountManager::getInstance();
|
AccountManager& accountManager = AccountManager::getInstance();
|
||||||
|
|
||||||
if (!username.isEmpty() && !password.isEmpty()) {
|
if (!username.isEmpty() && !password.isEmpty()) {
|
||||||
// ask the account manager to log us in from the env variables
|
// ask the account manager to log us in from the env variables
|
||||||
accountManager.requestAccessToken(username, password);
|
accountManager.requestAccessToken(username, password);
|
||||||
|
@ -196,7 +189,7 @@ void AssignmentClient::handleAuthenticationRequest() {
|
||||||
qDebug() << "Authentication was requested against" << qPrintable(accountManager.getAuthURL().toString())
|
qDebug() << "Authentication was requested against" << qPrintable(accountManager.getAuthURL().toString())
|
||||||
<< "but both or one of" << qPrintable(DATA_SERVER_USERNAME_ENV)
|
<< "but both or one of" << qPrintable(DATA_SERVER_USERNAME_ENV)
|
||||||
<< "/" << qPrintable(DATA_SERVER_PASSWORD_ENV) << "are not set. Unable to authenticate.";
|
<< "/" << qPrintable(DATA_SERVER_PASSWORD_ENV) << "are not set. Unable to authenticate.";
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,15 +197,15 @@ void AssignmentClient::handleAuthenticationRequest() {
|
||||||
void AssignmentClient::assignmentCompleted() {
|
void AssignmentClient::assignmentCompleted() {
|
||||||
// reset the logging target to the the CHILD_TARGET_NAME
|
// reset the logging target to the the CHILD_TARGET_NAME
|
||||||
Logging::setTargetName(ASSIGNMENT_CLIENT_TARGET_NAME);
|
Logging::setTargetName(ASSIGNMENT_CLIENT_TARGET_NAME);
|
||||||
|
|
||||||
qDebug("Assignment finished or never started - waiting for new assignment.");
|
qDebug("Assignment finished or never started - waiting for new assignment.");
|
||||||
|
|
||||||
NodeList* nodeList = NodeList::getInstance();
|
NodeList* nodeList = NodeList::getInstance();
|
||||||
|
|
||||||
// have us handle incoming NodeList datagrams again
|
// have us handle incoming NodeList datagrams again
|
||||||
disconnect(&nodeList->getNodeSocket(), 0, _currentAssignment.data(), 0);
|
disconnect(&nodeList->getNodeSocket(), 0, _currentAssignment.data(), 0);
|
||||||
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams);
|
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams);
|
||||||
|
|
||||||
// clear our current assignment shared pointer now that we're done with it
|
// clear our current assignment shared pointer now that we're done with it
|
||||||
// if the assignment thread is still around it has its own shared pointer to the assignment
|
// if the assignment thread is still around it has its own shared pointer to the assignment
|
||||||
_currentAssignment.clear();
|
_currentAssignment.clear();
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -691,6 +691,10 @@ function rayPlaneIntersection(pickRay, point, normal) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function mousePressEvent(event) {
|
function mousePressEvent(event) {
|
||||||
|
if (altIsPressed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mouseLastPosition = { x: event.x, y: event.y };
|
mouseLastPosition = { x: event.x, y: event.y };
|
||||||
modelSelected = false;
|
modelSelected = false;
|
||||||
var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y});
|
var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y});
|
||||||
|
@ -790,6 +794,10 @@ var oldModifier = 0;
|
||||||
var modifier = 0;
|
var modifier = 0;
|
||||||
var wasShifted = false;
|
var wasShifted = false;
|
||||||
function mouseMoveEvent(event) {
|
function mouseMoveEvent(event) {
|
||||||
|
if (altIsPressed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var pickRay = Camera.computePickRay(event.x, event.y);
|
var pickRay = Camera.computePickRay(event.x, event.y);
|
||||||
|
|
||||||
if (!modelSelected) {
|
if (!modelSelected) {
|
||||||
|
@ -894,6 +902,10 @@ function mouseMoveEvent(event) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function mouseReleaseEvent(event) {
|
function mouseReleaseEvent(event) {
|
||||||
|
if (altIsPressed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
modelSelected = false;
|
modelSelected = false;
|
||||||
|
|
||||||
glowedModelID.id = -1;
|
glowedModelID.id = -1;
|
||||||
|
@ -962,4 +974,16 @@ Menu.menuItemEvent.connect(function(menuItem){
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// handling of inspect.js concurrence
|
||||||
|
altIsPressed = false;
|
||||||
|
Controller.keyPressEvent.connect(function(event) {
|
||||||
|
if (event.text == "ALT") {
|
||||||
|
altIsPressed = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Controller.keyReleaseEvent.connect(function(event) {
|
||||||
|
if (event.text == "ALT") {
|
||||||
|
altIsPressed = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
|
@ -177,30 +177,45 @@ function keyReleaseEvent(event) {
|
||||||
|
|
||||||
function mousePressEvent(event) {
|
function mousePressEvent(event) {
|
||||||
if (alt && !isActive) {
|
if (alt && !isActive) {
|
||||||
isActive = true;
|
|
||||||
mouseLastX = event.x;
|
mouseLastX = event.x;
|
||||||
mouseLastY = event.y;
|
mouseLastY = event.y;
|
||||||
|
|
||||||
// Compute trajectories related values
|
// Compute trajectories related values
|
||||||
var pickRay = Camera.computePickRay(mouseLastX, mouseLastY);
|
var pickRay = Camera.computePickRay(mouseLastX, mouseLastY);
|
||||||
var intersection = Voxels.findRayIntersection(pickRay);
|
var voxelIntersection = Voxels.findRayIntersection(pickRay);
|
||||||
|
var modelIntersection = Models.findRayIntersection(pickRay);
|
||||||
|
|
||||||
position = Camera.getPosition();
|
position = Camera.getPosition();
|
||||||
|
|
||||||
avatarTarget = MyAvatar.getTargetAvatarPosition();
|
var avatarTarget = MyAvatar.getTargetAvatarPosition();
|
||||||
voxelTarget = intersection.intersection;
|
var voxelTarget = voxelIntersection.intersection;
|
||||||
if (Vec3.length(Vec3.subtract(avatarTarget, position)) < Vec3.length(Vec3.subtract(voxelTarget, position))) {
|
|
||||||
if (avatarTarget.x != 0 || avatarTarget.y != 0 || avatarTarget.z != 0) {
|
|
||||||
center = avatarTarget;
|
var distance = -1;
|
||||||
} else {
|
var string;
|
||||||
center = voxelTarget;
|
|
||||||
}
|
if (modelIntersection.intersects && modelIntersection.accurate) {
|
||||||
} else {
|
distance = modelIntersection.distance;
|
||||||
if (voxelTarget.x != 0 || voxelTarget.y != 0 || voxelTarget.z != 0) {
|
center = modelIntersection.modelProperties.position;
|
||||||
center = voxelTarget;
|
string = "Inspecting model";
|
||||||
} else {
|
}
|
||||||
center = avatarTarget;
|
|
||||||
}
|
if ((distance == -1 || Vec3.length(Vec3.subtract(avatarTarget, position)) < distance) &&
|
||||||
|
(avatarTarget.x != 0 || avatarTarget.y != 0 || avatarTarget.z != 0)) {
|
||||||
|
distance = Vec3.length(Vec3.subtract(avatarTarget, position));
|
||||||
|
center = avatarTarget;
|
||||||
|
string = "Inspecting avatar";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((distance == -1 || Vec3.length(Vec3.subtract(voxelTarget, position)) < distance) &&
|
||||||
|
(voxelTarget.x != 0 || voxelTarget.y != 0 || voxelTarget.z != 0)) {
|
||||||
|
distance = Vec3.length(Vec3.subtract(voxelTarget, position));
|
||||||
|
center = voxelTarget;
|
||||||
|
string = "Inspecting voxel";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (distance == -1) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector = Vec3.subtract(position, center);
|
vector = Vec3.subtract(position, center);
|
||||||
|
@ -209,6 +224,8 @@ function mousePressEvent(event) {
|
||||||
altitude = Math.asin(vector.y / Vec3.length(vector));
|
altitude = Math.asin(vector.y / Vec3.length(vector));
|
||||||
|
|
||||||
Camera.keepLookingAt(center);
|
Camera.keepLookingAt(center);
|
||||||
|
print(string);
|
||||||
|
isActive = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1379,6 +1379,9 @@ void Application::setEnable3DTVMode(bool enable3DTVMode) {
|
||||||
resizeGL(_glWidget->width(),_glWidget->height());
|
resizeGL(_glWidget->width(),_glWidget->height());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::setEnableVRMode(bool enableVRMode) {
|
||||||
|
resizeGL(_glWidget->width(), _glWidget->height());
|
||||||
|
}
|
||||||
|
|
||||||
void Application::setRenderVoxels(bool voxelRender) {
|
void Application::setRenderVoxels(bool voxelRender) {
|
||||||
_voxelEditSender.setShouldSend(voxelRender);
|
_voxelEditSender.setShouldSend(voxelRender);
|
||||||
|
|
|
@ -346,6 +346,7 @@ private slots:
|
||||||
|
|
||||||
void setFullscreen(bool fullscreen);
|
void setFullscreen(bool fullscreen);
|
||||||
void setEnable3DTVMode(bool enable3DTVMode);
|
void setEnable3DTVMode(bool enable3DTVMode);
|
||||||
|
void setEnableVRMode(bool enableVRMode);
|
||||||
void cameraMenuChanged();
|
void cameraMenuChanged();
|
||||||
|
|
||||||
glm::vec2 getScaledScreenPoint(glm::vec2 projectedPoint);
|
glm::vec2 getScaledScreenPoint(glm::vec2 projectedPoint);
|
||||||
|
|
|
@ -127,7 +127,7 @@ Menu::Menu() :
|
||||||
toggleLoginMenuItem();
|
toggleLoginMenuItem();
|
||||||
|
|
||||||
// connect to the appropriate slots of the AccountManager so that we can change the Login/Logout menu item
|
// connect to the appropriate slots of the AccountManager so that we can change the Login/Logout menu item
|
||||||
connect(&accountManager, &AccountManager::accessTokenChanged, this, &Menu::toggleLoginMenuItem);
|
connect(&accountManager, &AccountManager::profileChanged, this, &Menu::toggleLoginMenuItem);
|
||||||
connect(&accountManager, &AccountManager::logoutComplete, this, &Menu::toggleLoginMenuItem);
|
connect(&accountManager, &AccountManager::logoutComplete, this, &Menu::toggleLoginMenuItem);
|
||||||
|
|
||||||
addDisabledActionAndSeparator(fileMenu, "Scripts");
|
addDisabledActionAndSeparator(fileMenu, "Scripts");
|
||||||
|
@ -256,6 +256,11 @@ Menu::Menu() :
|
||||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FullscreenMirror, Qt::Key_H, false,
|
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FullscreenMirror, Qt::Key_H, false,
|
||||||
appInstance, SLOT(cameraMenuChanged()));
|
appInstance, SLOT(cameraMenuChanged()));
|
||||||
|
|
||||||
|
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::EnableVRMode, 0,
|
||||||
|
false,
|
||||||
|
appInstance,
|
||||||
|
SLOT(setEnableVRMode(bool)));
|
||||||
|
|
||||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Enable3DTVMode, 0,
|
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Enable3DTVMode, 0,
|
||||||
false,
|
false,
|
||||||
appInstance,
|
appInstance,
|
||||||
|
@ -323,7 +328,7 @@ Menu::Menu() :
|
||||||
shadowGroup->addAction(addCheckableActionToQMenuAndActionHash(shadowMenu, "None", 0, true));
|
shadowGroup->addAction(addCheckableActionToQMenuAndActionHash(shadowMenu, "None", 0, true));
|
||||||
shadowGroup->addAction(addCheckableActionToQMenuAndActionHash(shadowMenu, MenuOption::SimpleShadows, 0, false));
|
shadowGroup->addAction(addCheckableActionToQMenuAndActionHash(shadowMenu, MenuOption::SimpleShadows, 0, false));
|
||||||
shadowGroup->addAction(addCheckableActionToQMenuAndActionHash(shadowMenu, MenuOption::CascadedShadows, 0, false));
|
shadowGroup->addAction(addCheckableActionToQMenuAndActionHash(shadowMenu, MenuOption::CascadedShadows, 0, false));
|
||||||
|
|
||||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Metavoxels, 0, true);
|
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Metavoxels, 0, true);
|
||||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::BuckyBalls, 0, false);
|
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::BuckyBalls, 0, false);
|
||||||
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Particles, 0, true);
|
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Particles, 0, true);
|
||||||
|
@ -404,7 +409,7 @@ Menu::Menu() :
|
||||||
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::DisableNackPackets, 0, false);
|
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::DisableNackPackets, 0, false);
|
||||||
|
|
||||||
addDisabledActionAndSeparator(developerMenu, "Testing");
|
addDisabledActionAndSeparator(developerMenu, "Testing");
|
||||||
|
|
||||||
QMenu* timingMenu = developerMenu->addMenu("Timing and Statistics Tools");
|
QMenu* timingMenu = developerMenu->addMenu("Timing and Statistics Tools");
|
||||||
QMenu* perfTimerMenu = timingMenu->addMenu("Performance Timer");
|
QMenu* perfTimerMenu = timingMenu->addMenu("Performance Timer");
|
||||||
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::DisplayTimingDetails, 0, true);
|
addCheckableActionToQMenuAndActionHash(perfTimerMenu, MenuOption::DisplayTimingDetails, 0, true);
|
||||||
|
@ -459,7 +464,7 @@ Menu::Menu() :
|
||||||
false,
|
false,
|
||||||
appInstance->getAudio(),
|
appInstance->getAudio(),
|
||||||
SLOT(toggleToneInjection()));
|
SLOT(toggleToneInjection()));
|
||||||
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioScope,
|
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioScope,
|
||||||
Qt::CTRL | Qt::Key_P, false,
|
Qt::CTRL | Qt::Key_P, false,
|
||||||
appInstance->getAudio(),
|
appInstance->getAudio(),
|
||||||
SLOT(toggleScope()));
|
SLOT(toggleScope()));
|
||||||
|
@ -1772,4 +1777,3 @@ QString Menu::getSnapshotsLocation() const {
|
||||||
}
|
}
|
||||||
return _snapshotsLocation;
|
return _snapshotsLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -336,6 +336,7 @@ namespace MenuOption {
|
||||||
const QString EchoLocalAudio = "Echo Local Audio";
|
const QString EchoLocalAudio = "Echo Local Audio";
|
||||||
const QString EchoServerAudio = "Echo Server Audio";
|
const QString EchoServerAudio = "Echo Server Audio";
|
||||||
const QString Enable3DTVMode = "Enable 3DTV Mode";
|
const QString Enable3DTVMode = "Enable 3DTV Mode";
|
||||||
|
const QString EnableVRMode = "Enable VR Mode";
|
||||||
const QString ExpandMiscAvatarTiming = "Expand Misc MyAvatar Timing";
|
const QString ExpandMiscAvatarTiming = "Expand Misc MyAvatar Timing";
|
||||||
const QString ExpandAvatarUpdateTiming = "Expand MyAvatar update Timing";
|
const QString ExpandAvatarUpdateTiming = "Expand MyAvatar update Timing";
|
||||||
const QString ExpandAvatarSimulateTiming = "Expand MyAvatar simulate Timing";
|
const QString ExpandAvatarSimulateTiming = "Expand MyAvatar simulate Timing";
|
||||||
|
|
|
@ -23,7 +23,7 @@ XmppClient::XmppClient() :
|
||||||
_xmppMUCManager()
|
_xmppMUCManager()
|
||||||
{
|
{
|
||||||
AccountManager& accountManager = AccountManager::getInstance();
|
AccountManager& accountManager = AccountManager::getInstance();
|
||||||
connect(&accountManager, SIGNAL(accessTokenChanged()), this, SLOT(connectToServer()));
|
connect(&accountManager, SIGNAL(profileChanged()), this, SLOT(connectToServer()));
|
||||||
connect(&accountManager, SIGNAL(logoutComplete()), this, SLOT(disconnectFromServer()));
|
connect(&accountManager, SIGNAL(logoutComplete()), this, SLOT(disconnectFromServer()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,14 @@ void OculusManager::connect() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OculusManager::isConnected() {
|
||||||
|
#ifdef HAVE_LIBOVR
|
||||||
|
return _isConnected && Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode);
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void OculusManager::configureCamera(Camera& camera, int screenWidth, int screenHeight) {
|
void OculusManager::configureCamera(Camera& camera, int screenWidth, int screenHeight) {
|
||||||
#ifdef HAVE_LIBOVR
|
#ifdef HAVE_LIBOVR
|
||||||
_stereoConfig.SetFullViewport(Viewport(0, 0, screenWidth, screenHeight));
|
_stereoConfig.SetFullViewport(Viewport(0, 0, screenWidth, screenHeight));
|
||||||
|
|
|
@ -27,7 +27,7 @@ class OculusManager {
|
||||||
public:
|
public:
|
||||||
static void connect();
|
static void connect();
|
||||||
|
|
||||||
static bool isConnected() { return _isConnected; }
|
static bool isConnected();
|
||||||
|
|
||||||
static void configureCamera(Camera& camera, int screenWidth, int screenHeight);
|
static void configureCamera(Camera& camera, int screenWidth, int screenHeight);
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,7 @@ void LocationManager::goTo(QString destination) {
|
||||||
// go to coordinate destination or to Username
|
// go to coordinate destination or to Username
|
||||||
if (!goToDestination(destination)) {
|
if (!goToDestination(destination)) {
|
||||||
destination = QString(QUrl::toPercentEncoding(destination));
|
destination = QString(QUrl::toPercentEncoding(destination));
|
||||||
|
|
||||||
JSONCallbackParameters callbackParams;
|
JSONCallbackParameters callbackParams;
|
||||||
callbackParams.jsonCallbackReceiver = this;
|
callbackParams.jsonCallbackReceiver = this;
|
||||||
callbackParams.jsonCallbackMethod = "goToAddressFromResponse";
|
callbackParams.jsonCallbackMethod = "goToAddressFromResponse";
|
||||||
|
|
|
@ -55,13 +55,13 @@ AccountManager::AccountManager() :
|
||||||
{
|
{
|
||||||
qRegisterMetaType<OAuthAccessToken>("OAuthAccessToken");
|
qRegisterMetaType<OAuthAccessToken>("OAuthAccessToken");
|
||||||
qRegisterMetaTypeStreamOperators<OAuthAccessToken>("OAuthAccessToken");
|
qRegisterMetaTypeStreamOperators<OAuthAccessToken>("OAuthAccessToken");
|
||||||
|
|
||||||
qRegisterMetaType<DataServerAccountInfo>("DataServerAccountInfo");
|
qRegisterMetaType<DataServerAccountInfo>("DataServerAccountInfo");
|
||||||
qRegisterMetaTypeStreamOperators<DataServerAccountInfo>("DataServerAccountInfo");
|
qRegisterMetaTypeStreamOperators<DataServerAccountInfo>("DataServerAccountInfo");
|
||||||
|
|
||||||
qRegisterMetaType<QNetworkAccessManager::Operation>("QNetworkAccessManager::Operation");
|
qRegisterMetaType<QNetworkAccessManager::Operation>("QNetworkAccessManager::Operation");
|
||||||
qRegisterMetaType<JSONCallbackParameters>("JSONCallbackParameters");
|
qRegisterMetaType<JSONCallbackParameters>("JSONCallbackParameters");
|
||||||
|
|
||||||
connect(&_accountInfo, &DataServerAccountInfo::balanceChanged, this, &AccountManager::accountInfoBalanceChanged);
|
connect(&_accountInfo, &DataServerAccountInfo::balanceChanged, this, &AccountManager::accountInfoBalanceChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,18 +70,18 @@ const QString DOUBLE_SLASH_SUBSTITUTE = "slashslash";
|
||||||
void AccountManager::logout() {
|
void AccountManager::logout() {
|
||||||
// a logout means we want to delete the DataServerAccountInfo we currently have for this URL, in-memory and in file
|
// a logout means we want to delete the DataServerAccountInfo we currently have for this URL, in-memory and in file
|
||||||
_accountInfo = DataServerAccountInfo();
|
_accountInfo = DataServerAccountInfo();
|
||||||
|
|
||||||
emit balanceChanged(0);
|
emit balanceChanged(0);
|
||||||
connect(&_accountInfo, &DataServerAccountInfo::balanceChanged, this, &AccountManager::accountInfoBalanceChanged);
|
connect(&_accountInfo, &DataServerAccountInfo::balanceChanged, this, &AccountManager::accountInfoBalanceChanged);
|
||||||
|
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
settings.beginGroup(ACCOUNTS_GROUP);
|
settings.beginGroup(ACCOUNTS_GROUP);
|
||||||
|
|
||||||
QString keyURLString(_authURL.toString().replace("//", DOUBLE_SLASH_SUBSTITUTE));
|
QString keyURLString(_authURL.toString().replace("//", DOUBLE_SLASH_SUBSTITUTE));
|
||||||
settings.remove(keyURLString);
|
settings.remove(keyURLString);
|
||||||
|
|
||||||
qDebug() << "Removed account info for" << _authURL << "from in-memory accounts and .ini file";
|
qDebug() << "Removed account info for" << _authURL << "from in-memory accounts and .ini file";
|
||||||
|
|
||||||
emit logoutComplete();
|
emit logoutComplete();
|
||||||
// the username has changed to blank
|
// the username has changed to blank
|
||||||
emit usernameChanged(QString());
|
emit usernameChanged(QString());
|
||||||
|
@ -93,7 +93,7 @@ void AccountManager::updateBalance() {
|
||||||
JSONCallbackParameters callbackParameters;
|
JSONCallbackParameters callbackParameters;
|
||||||
callbackParameters.jsonCallbackReceiver = &_accountInfo;
|
callbackParameters.jsonCallbackReceiver = &_accountInfo;
|
||||||
callbackParameters.jsonCallbackMethod = "setBalanceFromJSON";
|
callbackParameters.jsonCallbackMethod = "setBalanceFromJSON";
|
||||||
|
|
||||||
authenticatedRequest("/api/v1/wallets/mine", QNetworkAccessManager::GetOperation, callbackParameters);
|
authenticatedRequest("/api/v1/wallets/mine", QNetworkAccessManager::GetOperation, callbackParameters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,28 +105,33 @@ void AccountManager::accountInfoBalanceChanged(qint64 newBalance) {
|
||||||
void AccountManager::setAuthURL(const QUrl& authURL) {
|
void AccountManager::setAuthURL(const QUrl& authURL) {
|
||||||
if (_authURL != authURL) {
|
if (_authURL != authURL) {
|
||||||
_authURL = authURL;
|
_authURL = authURL;
|
||||||
|
|
||||||
qDebug() << "URL for node authentication has been changed to" << qPrintable(_authURL.toString());
|
qDebug() << "URL for node authentication has been changed to" << qPrintable(_authURL.toString());
|
||||||
qDebug() << "Re-setting authentication flow.";
|
qDebug() << "Re-setting authentication flow.";
|
||||||
|
|
||||||
// check if there are existing access tokens to load from settings
|
// check if there are existing access tokens to load from settings
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
settings.beginGroup(ACCOUNTS_GROUP);
|
settings.beginGroup(ACCOUNTS_GROUP);
|
||||||
|
|
||||||
foreach(const QString& key, settings.allKeys()) {
|
foreach(const QString& key, settings.allKeys()) {
|
||||||
// take a key copy to perform the double slash replacement
|
// take a key copy to perform the double slash replacement
|
||||||
QString keyCopy(key);
|
QString keyCopy(key);
|
||||||
QUrl keyURL(keyCopy.replace("slashslash", "//"));
|
QUrl keyURL(keyCopy.replace("slashslash", "//"));
|
||||||
|
|
||||||
if (keyURL == _authURL) {
|
if (keyURL == _authURL) {
|
||||||
// pull out the stored access token and store it in memory
|
// pull out the stored access token and store it in memory
|
||||||
_accountInfo = settings.value(key).value<DataServerAccountInfo>();
|
_accountInfo = settings.value(key).value<DataServerAccountInfo>();
|
||||||
qDebug() << "Found a data-server access token for" << qPrintable(keyURL.toString());
|
qDebug() << "Found a data-server access token for" << qPrintable(keyURL.toString());
|
||||||
|
|
||||||
emit accessTokenChanged();
|
// profile info isn't guaranteed to be saved too
|
||||||
|
if (_accountInfo.hasProfile()) {
|
||||||
|
emit profileChanged();
|
||||||
|
} else {
|
||||||
|
requestProfile();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// tell listeners that the auth endpoint has changed
|
// tell listeners that the auth endpoint has changed
|
||||||
emit authEndpointChanged();
|
emit authEndpointChanged();
|
||||||
}
|
}
|
||||||
|
@ -147,36 +152,36 @@ void AccountManager::authenticatedRequest(const QString& path, QNetworkAccessMan
|
||||||
void AccountManager::invokedRequest(const QString& path, QNetworkAccessManager::Operation operation,
|
void AccountManager::invokedRequest(const QString& path, QNetworkAccessManager::Operation operation,
|
||||||
const JSONCallbackParameters& callbackParams,
|
const JSONCallbackParameters& callbackParams,
|
||||||
const QByteArray& dataByteArray, QHttpMultiPart* dataMultiPart) {
|
const QByteArray& dataByteArray, QHttpMultiPart* dataMultiPart) {
|
||||||
|
|
||||||
if (!_networkAccessManager) {
|
if (!_networkAccessManager) {
|
||||||
_networkAccessManager = new QNetworkAccessManager(this);
|
_networkAccessManager = new QNetworkAccessManager(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasValidAccessToken()) {
|
if (hasValidAccessToken()) {
|
||||||
QNetworkRequest authenticatedRequest;
|
QNetworkRequest authenticatedRequest;
|
||||||
|
|
||||||
QUrl requestURL = _authURL;
|
QUrl requestURL = _authURL;
|
||||||
|
|
||||||
if (path.startsWith("/")) {
|
if (path.startsWith("/")) {
|
||||||
requestURL.setPath(path);
|
requestURL.setPath(path);
|
||||||
} else {
|
} else {
|
||||||
requestURL.setPath("/" + path);
|
requestURL.setPath("/" + path);
|
||||||
}
|
}
|
||||||
|
|
||||||
requestURL.setQuery("access_token=" + _accountInfo.getAccessToken().token);
|
requestURL.setQuery("access_token=" + _accountInfo.getAccessToken().token);
|
||||||
|
|
||||||
authenticatedRequest.setUrl(requestURL);
|
authenticatedRequest.setUrl(requestURL);
|
||||||
|
|
||||||
if (VERBOSE_HTTP_REQUEST_DEBUGGING) {
|
if (VERBOSE_HTTP_REQUEST_DEBUGGING) {
|
||||||
qDebug() << "Making an authenticated request to" << qPrintable(requestURL.toString());
|
qDebug() << "Making an authenticated request to" << qPrintable(requestURL.toString());
|
||||||
|
|
||||||
if (!dataByteArray.isEmpty()) {
|
if (!dataByteArray.isEmpty()) {
|
||||||
qDebug() << "The POST/PUT body -" << QString(dataByteArray);
|
qDebug() << "The POST/PUT body -" << QString(dataByteArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QNetworkReply* networkReply = NULL;
|
QNetworkReply* networkReply = NULL;
|
||||||
|
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
case QNetworkAccessManager::GetOperation:
|
case QNetworkAccessManager::GetOperation:
|
||||||
networkReply = _networkAccessManager->get(authenticatedRequest);
|
networkReply = _networkAccessManager->get(authenticatedRequest);
|
||||||
|
@ -198,24 +203,24 @@ void AccountManager::invokedRequest(const QString& path, QNetworkAccessManager::
|
||||||
networkReply = _networkAccessManager->put(authenticatedRequest, dataByteArray);
|
networkReply = _networkAccessManager->put(authenticatedRequest, dataByteArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// other methods not yet handled
|
// other methods not yet handled
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (networkReply) {
|
if (networkReply) {
|
||||||
if (!callbackParams.isEmpty()) {
|
if (!callbackParams.isEmpty()) {
|
||||||
// if we have information for a callback, insert the callbackParams into our local map
|
// if we have information for a callback, insert the callbackParams into our local map
|
||||||
_pendingCallbackMap.insert(networkReply, callbackParams);
|
_pendingCallbackMap.insert(networkReply, callbackParams);
|
||||||
|
|
||||||
if (callbackParams.updateReciever && !callbackParams.updateSlot.isEmpty()) {
|
if (callbackParams.updateReciever && !callbackParams.updateSlot.isEmpty()) {
|
||||||
callbackParams.updateReciever->connect(networkReply, SIGNAL(uploadProgress(qint64, qint64)),
|
callbackParams.updateReciever->connect(networkReply, SIGNAL(uploadProgress(qint64, qint64)),
|
||||||
callbackParams.updateSlot.toStdString().c_str());
|
callbackParams.updateSlot.toStdString().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we ended up firing of a request, hook up to it now
|
// if we ended up firing of a request, hook up to it now
|
||||||
connect(networkReply, SIGNAL(finished()), SLOT(processReply()));
|
connect(networkReply, SIGNAL(finished()), SLOT(processReply()));
|
||||||
}
|
}
|
||||||
|
@ -224,7 +229,7 @@ void AccountManager::invokedRequest(const QString& path, QNetworkAccessManager::
|
||||||
|
|
||||||
void AccountManager::processReply() {
|
void AccountManager::processReply() {
|
||||||
QNetworkReply* requestReply = reinterpret_cast<QNetworkReply*>(sender());
|
QNetworkReply* requestReply = reinterpret_cast<QNetworkReply*>(sender());
|
||||||
|
|
||||||
if (requestReply->error() == QNetworkReply::NoError) {
|
if (requestReply->error() == QNetworkReply::NoError) {
|
||||||
passSuccessToCallback(requestReply);
|
passSuccessToCallback(requestReply);
|
||||||
} else {
|
} else {
|
||||||
|
@ -235,17 +240,17 @@ void AccountManager::processReply() {
|
||||||
|
|
||||||
void AccountManager::passSuccessToCallback(QNetworkReply* requestReply) {
|
void AccountManager::passSuccessToCallback(QNetworkReply* requestReply) {
|
||||||
QJsonDocument jsonResponse = QJsonDocument::fromJson(requestReply->readAll());
|
QJsonDocument jsonResponse = QJsonDocument::fromJson(requestReply->readAll());
|
||||||
|
|
||||||
JSONCallbackParameters callbackParams = _pendingCallbackMap.value(requestReply);
|
JSONCallbackParameters callbackParams = _pendingCallbackMap.value(requestReply);
|
||||||
|
|
||||||
if (callbackParams.jsonCallbackReceiver) {
|
if (callbackParams.jsonCallbackReceiver) {
|
||||||
// invoke the right method on the callback receiver
|
// invoke the right method on the callback receiver
|
||||||
QMetaObject::invokeMethod(callbackParams.jsonCallbackReceiver, qPrintable(callbackParams.jsonCallbackMethod),
|
QMetaObject::invokeMethod(callbackParams.jsonCallbackReceiver, qPrintable(callbackParams.jsonCallbackMethod),
|
||||||
Q_ARG(const QJsonObject&, jsonResponse.object()));
|
Q_ARG(const QJsonObject&, jsonResponse.object()));
|
||||||
|
|
||||||
// remove the related reply-callback group from the map
|
// remove the related reply-callback group from the map
|
||||||
_pendingCallbackMap.remove(requestReply);
|
_pendingCallbackMap.remove(requestReply);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (VERBOSE_HTTP_REQUEST_DEBUGGING) {
|
if (VERBOSE_HTTP_REQUEST_DEBUGGING) {
|
||||||
qDebug() << "Received JSON response from data-server that has no matching callback.";
|
qDebug() << "Received JSON response from data-server that has no matching callback.";
|
||||||
|
@ -256,13 +261,13 @@ void AccountManager::passSuccessToCallback(QNetworkReply* requestReply) {
|
||||||
|
|
||||||
void AccountManager::passErrorToCallback(QNetworkReply* requestReply) {
|
void AccountManager::passErrorToCallback(QNetworkReply* requestReply) {
|
||||||
JSONCallbackParameters callbackParams = _pendingCallbackMap.value(requestReply);
|
JSONCallbackParameters callbackParams = _pendingCallbackMap.value(requestReply);
|
||||||
|
|
||||||
if (callbackParams.errorCallbackReceiver) {
|
if (callbackParams.errorCallbackReceiver) {
|
||||||
// invoke the right method on the callback receiver
|
// invoke the right method on the callback receiver
|
||||||
QMetaObject::invokeMethod(callbackParams.errorCallbackReceiver, qPrintable(callbackParams.errorCallbackMethod),
|
QMetaObject::invokeMethod(callbackParams.errorCallbackReceiver, qPrintable(callbackParams.errorCallbackMethod),
|
||||||
Q_ARG(QNetworkReply::NetworkError, requestReply->error()),
|
Q_ARG(QNetworkReply::NetworkError, requestReply->error()),
|
||||||
Q_ARG(const QString&, requestReply->errorString()));
|
Q_ARG(const QString&, requestReply->errorString()));
|
||||||
|
|
||||||
// remove the related reply-callback group from the map
|
// remove the related reply-callback group from the map
|
||||||
_pendingCallbackMap.remove(requestReply);
|
_pendingCallbackMap.remove(requestReply);
|
||||||
} else {
|
} else {
|
||||||
|
@ -274,12 +279,12 @@ void AccountManager::passErrorToCallback(QNetworkReply* requestReply) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AccountManager::hasValidAccessToken() {
|
bool AccountManager::hasValidAccessToken() {
|
||||||
|
|
||||||
if (_accountInfo.getAccessToken().token.isEmpty() || _accountInfo.getAccessToken().isExpired()) {
|
if (_accountInfo.getAccessToken().token.isEmpty() || _accountInfo.getAccessToken().isExpired()) {
|
||||||
if (VERBOSE_HTTP_REQUEST_DEBUGGING) {
|
if (VERBOSE_HTTP_REQUEST_DEBUGGING) {
|
||||||
qDebug() << "An access token is required for requests to" << qPrintable(_authURL.toString());
|
qDebug() << "An access token is required for requests to" << qPrintable(_authURL.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
|
@ -288,12 +293,12 @@ bool AccountManager::hasValidAccessToken() {
|
||||||
|
|
||||||
bool AccountManager::checkAndSignalForAccessToken() {
|
bool AccountManager::checkAndSignalForAccessToken() {
|
||||||
bool hasToken = hasValidAccessToken();
|
bool hasToken = hasValidAccessToken();
|
||||||
|
|
||||||
if (!hasToken) {
|
if (!hasToken) {
|
||||||
// emit a signal so somebody can call back to us and request an access token given a username and password
|
// emit a signal so somebody can call back to us and request an access token given a username and password
|
||||||
emit authRequired();
|
emit authRequired();
|
||||||
}
|
}
|
||||||
|
|
||||||
return hasToken;
|
return hasToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,36 +309,36 @@ void AccountManager::requestAccessToken(const QString& login, const QString& pas
|
||||||
}
|
}
|
||||||
|
|
||||||
QNetworkRequest request;
|
QNetworkRequest request;
|
||||||
|
|
||||||
QUrl grantURL = _authURL;
|
QUrl grantURL = _authURL;
|
||||||
grantURL.setPath("/oauth/token");
|
grantURL.setPath("/oauth/token");
|
||||||
|
|
||||||
const QString ACCOUNT_MANAGER_REQUESTED_SCOPE = "owner";
|
const QString ACCOUNT_MANAGER_REQUESTED_SCOPE = "owner";
|
||||||
|
|
||||||
QByteArray postData;
|
QByteArray postData;
|
||||||
postData.append("grant_type=password&");
|
postData.append("grant_type=password&");
|
||||||
postData.append("username=" + login + "&");
|
postData.append("username=" + login + "&");
|
||||||
postData.append("password=" + QUrl::toPercentEncoding(password) + "&");
|
postData.append("password=" + QUrl::toPercentEncoding(password) + "&");
|
||||||
postData.append("scope=" + ACCOUNT_MANAGER_REQUESTED_SCOPE);
|
postData.append("scope=" + ACCOUNT_MANAGER_REQUESTED_SCOPE);
|
||||||
|
|
||||||
request.setUrl(grantURL);
|
request.setUrl(grantURL);
|
||||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||||
|
|
||||||
QNetworkReply* requestReply = _networkAccessManager->post(request, postData);
|
QNetworkReply* requestReply = _networkAccessManager->post(request, postData);
|
||||||
connect(requestReply, &QNetworkReply::finished, this, &AccountManager::requestFinished);
|
connect(requestReply, &QNetworkReply::finished, this, &AccountManager::requestAccessTokenFinished);
|
||||||
connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestError(QNetworkReply::NetworkError)));
|
connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestAccessTokenError(QNetworkReply::NetworkError)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AccountManager::requestFinished() {
|
void AccountManager::requestAccessTokenFinished() {
|
||||||
QNetworkReply* requestReply = reinterpret_cast<QNetworkReply*>(sender());
|
QNetworkReply* requestReply = reinterpret_cast<QNetworkReply*>(sender());
|
||||||
|
|
||||||
QJsonDocument jsonResponse = QJsonDocument::fromJson(requestReply->readAll());
|
QJsonDocument jsonResponse = QJsonDocument::fromJson(requestReply->readAll());
|
||||||
const QJsonObject& rootObject = jsonResponse.object();
|
const QJsonObject& rootObject = jsonResponse.object();
|
||||||
|
|
||||||
if (!rootObject.contains("error")) {
|
if (!rootObject.contains("error")) {
|
||||||
// construct an OAuthAccessToken from the json object
|
// construct an OAuthAccessToken from the json object
|
||||||
|
|
||||||
if (!rootObject.contains("access_token") || !rootObject.contains("expires_in")
|
if (!rootObject.contains("access_token") || !rootObject.contains("expires_in")
|
||||||
|| !rootObject.contains("token_type")) {
|
|| !rootObject.contains("token_type")) {
|
||||||
// TODO: error handling - malformed token response
|
// TODO: error handling - malformed token response
|
||||||
|
@ -342,23 +347,21 @@ void AccountManager::requestFinished() {
|
||||||
// clear the path from the response URL so we have the right root URL for this access token
|
// clear the path from the response URL so we have the right root URL for this access token
|
||||||
QUrl rootURL = requestReply->url();
|
QUrl rootURL = requestReply->url();
|
||||||
rootURL.setPath("");
|
rootURL.setPath("");
|
||||||
|
|
||||||
qDebug() << "Storing an account with access-token for" << qPrintable(rootURL.toString());
|
qDebug() << "Storing an account with access-token for" << qPrintable(rootURL.toString());
|
||||||
|
|
||||||
_accountInfo = DataServerAccountInfo(rootObject);
|
_accountInfo = DataServerAccountInfo();
|
||||||
|
_accountInfo.setAccessTokenFromJSON(rootObject);
|
||||||
|
|
||||||
emit loginComplete(rootURL);
|
emit loginComplete(rootURL);
|
||||||
// the username has changed to whatever came back
|
|
||||||
emit usernameChanged(_accountInfo.getUsername());
|
|
||||||
|
|
||||||
// we have found or requested an access token
|
|
||||||
emit accessTokenChanged();
|
|
||||||
|
|
||||||
// store this access token into the local settings
|
// store this access token into the local settings
|
||||||
QSettings localSettings;
|
QSettings localSettings;
|
||||||
localSettings.beginGroup(ACCOUNTS_GROUP);
|
localSettings.beginGroup(ACCOUNTS_GROUP);
|
||||||
localSettings.setValue(rootURL.toString().replace("//", DOUBLE_SLASH_SUBSTITUTE),
|
localSettings.setValue(rootURL.toString().replace("//", DOUBLE_SLASH_SUBSTITUTE),
|
||||||
QVariant::fromValue(_accountInfo));
|
QVariant::fromValue(_accountInfo));
|
||||||
|
|
||||||
|
requestProfile();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO: error handling
|
// TODO: error handling
|
||||||
|
@ -367,7 +370,53 @@ void AccountManager::requestFinished() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AccountManager::requestError(QNetworkReply::NetworkError error) {
|
void AccountManager::requestAccessTokenError(QNetworkReply::NetworkError error) {
|
||||||
// TODO: error handling
|
// TODO: error handling
|
||||||
qDebug() << "AccountManager requestError - " << error;
|
qDebug() << "AccountManager requestError - " << error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AccountManager::requestProfile() {
|
||||||
|
if (!_networkAccessManager) {
|
||||||
|
_networkAccessManager = new QNetworkAccessManager(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl profileURL = _authURL;
|
||||||
|
profileURL.setPath("/api/v1/users/profile");
|
||||||
|
profileURL.setQuery("access_token=" + _accountInfo.getAccessToken().token);
|
||||||
|
|
||||||
|
QNetworkReply* profileReply = _networkAccessManager->get(QNetworkRequest(profileURL));
|
||||||
|
connect(profileReply, &QNetworkReply::finished, this, &AccountManager::requestProfileFinished);
|
||||||
|
connect(profileReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestProfileError(QNetworkReply::NetworkError)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AccountManager::requestProfileFinished() {
|
||||||
|
QNetworkReply* profileReply = reinterpret_cast<QNetworkReply*>(sender());
|
||||||
|
|
||||||
|
QJsonDocument jsonResponse = QJsonDocument::fromJson(profileReply->readAll());
|
||||||
|
const QJsonObject& rootObject = jsonResponse.object();
|
||||||
|
|
||||||
|
if (rootObject.contains("status") && rootObject["status"].toString() == "success") {
|
||||||
|
_accountInfo.setProfileInfoFromJSON(rootObject);
|
||||||
|
|
||||||
|
emit profileChanged();
|
||||||
|
|
||||||
|
// the username has changed to whatever came back
|
||||||
|
emit usernameChanged(_accountInfo.getUsername());
|
||||||
|
|
||||||
|
// store the whole profile into the local settings
|
||||||
|
QUrl rootURL = profileReply->url();
|
||||||
|
rootURL.setPath("");
|
||||||
|
QSettings localSettings;
|
||||||
|
localSettings.beginGroup(ACCOUNTS_GROUP);
|
||||||
|
localSettings.setValue(rootURL.toString().replace("//", DOUBLE_SLASH_SUBSTITUTE),
|
||||||
|
QVariant::fromValue(_accountInfo));
|
||||||
|
} else {
|
||||||
|
// TODO: error handling
|
||||||
|
qDebug() << "Error in response for profile";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AccountManager::requestProfileError(QNetworkReply::NetworkError error) {
|
||||||
|
// TODO: error handling
|
||||||
|
qDebug() << "AccountManager requestProfileError - " << error;
|
||||||
|
}
|
||||||
|
|
|
@ -23,9 +23,9 @@
|
||||||
class JSONCallbackParameters {
|
class JSONCallbackParameters {
|
||||||
public:
|
public:
|
||||||
JSONCallbackParameters();
|
JSONCallbackParameters();
|
||||||
|
|
||||||
bool isEmpty() const { return !jsonCallbackReceiver && !errorCallbackReceiver; }
|
bool isEmpty() const { return !jsonCallbackReceiver && !errorCallbackReceiver; }
|
||||||
|
|
||||||
QObject* jsonCallbackReceiver;
|
QObject* jsonCallbackReceiver;
|
||||||
QString jsonCallbackMethod;
|
QString jsonCallbackMethod;
|
||||||
QObject* errorCallbackReceiver;
|
QObject* errorCallbackReceiver;
|
||||||
|
@ -38,30 +38,33 @@ class AccountManager : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
static AccountManager& getInstance();
|
static AccountManager& getInstance();
|
||||||
|
|
||||||
void authenticatedRequest(const QString& path,
|
void authenticatedRequest(const QString& path,
|
||||||
QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation,
|
QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation,
|
||||||
const JSONCallbackParameters& callbackParams = JSONCallbackParameters(),
|
const JSONCallbackParameters& callbackParams = JSONCallbackParameters(),
|
||||||
const QByteArray& dataByteArray = QByteArray(),
|
const QByteArray& dataByteArray = QByteArray(),
|
||||||
QHttpMultiPart* dataMultiPart = NULL);
|
QHttpMultiPart* dataMultiPart = NULL);
|
||||||
|
|
||||||
const QUrl& getAuthURL() const { return _authURL; }
|
const QUrl& getAuthURL() const { return _authURL; }
|
||||||
void setAuthURL(const QUrl& authURL);
|
void setAuthURL(const QUrl& authURL);
|
||||||
bool hasAuthEndpoint() { return !_authURL.isEmpty(); }
|
bool hasAuthEndpoint() { return !_authURL.isEmpty(); }
|
||||||
|
|
||||||
bool isLoggedIn() { return !_authURL.isEmpty() && hasValidAccessToken(); }
|
bool isLoggedIn() { return !_authURL.isEmpty() && hasValidAccessToken(); }
|
||||||
bool hasValidAccessToken();
|
bool hasValidAccessToken();
|
||||||
Q_INVOKABLE bool checkAndSignalForAccessToken();
|
Q_INVOKABLE bool checkAndSignalForAccessToken();
|
||||||
|
|
||||||
void requestAccessToken(const QString& login, const QString& password);
|
void requestAccessToken(const QString& login, const QString& password);
|
||||||
|
void requestProfile();
|
||||||
|
|
||||||
const DataServerAccountInfo& getAccountInfo() const { return _accountInfo; }
|
const DataServerAccountInfo& getAccountInfo() const { return _accountInfo; }
|
||||||
|
|
||||||
void destroy() { delete _networkAccessManager; }
|
void destroy() { delete _networkAccessManager; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void requestFinished();
|
void requestAccessTokenFinished();
|
||||||
void requestError(QNetworkReply::NetworkError error);
|
void requestProfileFinished();
|
||||||
|
void requestAccessTokenError(QNetworkReply::NetworkError error);
|
||||||
|
void requestProfileError(QNetworkReply::NetworkError error);
|
||||||
void logout();
|
void logout();
|
||||||
void updateBalance();
|
void updateBalance();
|
||||||
void accountInfoBalanceChanged(qint64 newBalance);
|
void accountInfoBalanceChanged(qint64 newBalance);
|
||||||
|
@ -69,7 +72,7 @@ signals:
|
||||||
void authRequired();
|
void authRequired();
|
||||||
void authEndpointChanged();
|
void authEndpointChanged();
|
||||||
void usernameChanged(const QString& username);
|
void usernameChanged(const QString& username);
|
||||||
void accessTokenChanged();
|
void profileChanged();
|
||||||
void loginComplete(const QUrl& authURL);
|
void loginComplete(const QUrl& authURL);
|
||||||
void loginFailed();
|
void loginFailed();
|
||||||
void logoutComplete();
|
void logoutComplete();
|
||||||
|
@ -80,19 +83,19 @@ private:
|
||||||
AccountManager();
|
AccountManager();
|
||||||
AccountManager(AccountManager const& other); // not implemented
|
AccountManager(AccountManager const& other); // not implemented
|
||||||
void operator=(AccountManager const& other); // not implemented
|
void operator=(AccountManager const& other); // not implemented
|
||||||
|
|
||||||
void passSuccessToCallback(QNetworkReply* reply);
|
void passSuccessToCallback(QNetworkReply* reply);
|
||||||
void passErrorToCallback(QNetworkReply* reply);
|
void passErrorToCallback(QNetworkReply* reply);
|
||||||
|
|
||||||
Q_INVOKABLE void invokedRequest(const QString& path, QNetworkAccessManager::Operation operation,
|
Q_INVOKABLE void invokedRequest(const QString& path, QNetworkAccessManager::Operation operation,
|
||||||
const JSONCallbackParameters& callbackParams,
|
const JSONCallbackParameters& callbackParams,
|
||||||
const QByteArray& dataByteArray,
|
const QByteArray& dataByteArray,
|
||||||
QHttpMultiPart* dataMultiPart);
|
QHttpMultiPart* dataMultiPart);
|
||||||
|
|
||||||
QUrl _authURL;
|
QUrl _authURL;
|
||||||
QNetworkAccessManager* _networkAccessManager;
|
QNetworkAccessManager* _networkAccessManager;
|
||||||
QMap<QNetworkReply*, JSONCallbackParameters> _pendingCallbackMap;
|
QMap<QNetworkReply*, JSONCallbackParameters> _pendingCallbackMap;
|
||||||
|
|
||||||
DataServerAccountInfo _accountInfo;
|
DataServerAccountInfo _accountInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -21,20 +21,7 @@ DataServerAccountInfo::DataServerAccountInfo() :
|
||||||
_balance(0),
|
_balance(0),
|
||||||
_hasBalance(false)
|
_hasBalance(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
DataServerAccountInfo::DataServerAccountInfo(const QJsonObject& jsonObject) :
|
|
||||||
_accessToken(jsonObject),
|
|
||||||
_username(),
|
|
||||||
_xmppPassword(),
|
|
||||||
_balance(0),
|
|
||||||
_hasBalance(false)
|
|
||||||
{
|
|
||||||
QJsonObject userJSONObject = jsonObject["user"].toObject();
|
|
||||||
setUsername(userJSONObject["username"].toString());
|
|
||||||
setXMPPPassword(userJSONObject["xmpp_password"].toString());
|
|
||||||
setDiscourseApiKey(userJSONObject["discourse_api_key"].toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DataServerAccountInfo::DataServerAccountInfo(const DataServerAccountInfo& otherInfo) {
|
DataServerAccountInfo::DataServerAccountInfo(const DataServerAccountInfo& otherInfo) {
|
||||||
|
@ -54,7 +41,7 @@ DataServerAccountInfo& DataServerAccountInfo::operator=(const DataServerAccountI
|
||||||
|
|
||||||
void DataServerAccountInfo::swap(DataServerAccountInfo& otherInfo) {
|
void DataServerAccountInfo::swap(DataServerAccountInfo& otherInfo) {
|
||||||
using std::swap;
|
using std::swap;
|
||||||
|
|
||||||
swap(_accessToken, otherInfo._accessToken);
|
swap(_accessToken, otherInfo._accessToken);
|
||||||
swap(_username, otherInfo._username);
|
swap(_username, otherInfo._username);
|
||||||
swap(_xmppPassword, otherInfo._xmppPassword);
|
swap(_xmppPassword, otherInfo._xmppPassword);
|
||||||
|
@ -63,10 +50,14 @@ void DataServerAccountInfo::swap(DataServerAccountInfo& otherInfo) {
|
||||||
swap(_hasBalance, otherInfo._hasBalance);
|
swap(_hasBalance, otherInfo._hasBalance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DataServerAccountInfo::setAccessTokenFromJSON(const QJsonObject& jsonObject) {
|
||||||
|
_accessToken = OAuthAccessToken(jsonObject);
|
||||||
|
}
|
||||||
|
|
||||||
void DataServerAccountInfo::setUsername(const QString& username) {
|
void DataServerAccountInfo::setUsername(const QString& username) {
|
||||||
if (_username != username) {
|
if (_username != username) {
|
||||||
_username = username;
|
_username = username;
|
||||||
|
|
||||||
qDebug() << "Username changed to" << username;
|
qDebug() << "Username changed to" << username;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,7 +78,7 @@ void DataServerAccountInfo::setBalance(qint64 balance) {
|
||||||
if (!_hasBalance || _balance != balance) {
|
if (!_hasBalance || _balance != balance) {
|
||||||
_balance = balance;
|
_balance = balance;
|
||||||
_hasBalance = true;
|
_hasBalance = true;
|
||||||
|
|
||||||
emit balanceChanged(_balance);
|
emit balanceChanged(_balance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,6 +90,17 @@ void DataServerAccountInfo::setBalanceFromJSON(const QJsonObject& jsonObject) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DataServerAccountInfo::hasProfile() const {
|
||||||
|
return _username.length() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataServerAccountInfo::setProfileInfoFromJSON(const QJsonObject& jsonObject) {
|
||||||
|
QJsonObject user = jsonObject["data"].toObject()["user"].toObject();
|
||||||
|
setUsername(user["username"].toString());
|
||||||
|
setXMPPPassword(user["xmpp_password"].toString());
|
||||||
|
setDiscourseApiKey(user["discourse_api_key"].toString());
|
||||||
|
}
|
||||||
|
|
||||||
QDataStream& operator<<(QDataStream &out, const DataServerAccountInfo& info) {
|
QDataStream& operator<<(QDataStream &out, const DataServerAccountInfo& info) {
|
||||||
out << info._accessToken << info._username << info._xmppPassword << info._discourseApiKey;
|
out << info._accessToken << info._username << info._xmppPassword << info._discourseApiKey;
|
||||||
return out;
|
return out;
|
||||||
|
|
|
@ -22,12 +22,12 @@ class DataServerAccountInfo : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
DataServerAccountInfo();
|
DataServerAccountInfo();
|
||||||
DataServerAccountInfo(const QJsonObject& jsonObject);
|
|
||||||
DataServerAccountInfo(const DataServerAccountInfo& otherInfo);
|
DataServerAccountInfo(const DataServerAccountInfo& otherInfo);
|
||||||
DataServerAccountInfo& operator=(const DataServerAccountInfo& otherInfo);
|
DataServerAccountInfo& operator=(const DataServerAccountInfo& otherInfo);
|
||||||
|
|
||||||
const OAuthAccessToken& getAccessToken() const { return _accessToken; }
|
const OAuthAccessToken& getAccessToken() const { return _accessToken; }
|
||||||
|
void setAccessTokenFromJSON(const QJsonObject& jsonObject);
|
||||||
|
|
||||||
const QString& getUsername() const { return _username; }
|
const QString& getUsername() const { return _username; }
|
||||||
void setUsername(const QString& username);
|
void setUsername(const QString& username);
|
||||||
|
|
||||||
|
@ -36,20 +36,24 @@ public:
|
||||||
|
|
||||||
const QString& getDiscourseApiKey() const { return _discourseApiKey; }
|
const QString& getDiscourseApiKey() const { return _discourseApiKey; }
|
||||||
void setDiscourseApiKey(const QString& discourseApiKey);
|
void setDiscourseApiKey(const QString& discourseApiKey);
|
||||||
|
|
||||||
qint64 getBalance() const { return _balance; }
|
qint64 getBalance() const { return _balance; }
|
||||||
void setBalance(qint64 balance);
|
void setBalance(qint64 balance);
|
||||||
bool hasBalance() const { return _hasBalance; }
|
bool hasBalance() const { return _hasBalance; }
|
||||||
void setHasBalance(bool hasBalance) { _hasBalance = hasBalance; }
|
void setHasBalance(bool hasBalance) { _hasBalance = hasBalance; }
|
||||||
Q_INVOKABLE void setBalanceFromJSON(const QJsonObject& jsonObject);
|
Q_INVOKABLE void setBalanceFromJSON(const QJsonObject& jsonObject);
|
||||||
|
|
||||||
|
bool hasProfile() const;
|
||||||
|
|
||||||
|
void setProfileInfoFromJSON(const QJsonObject& jsonObject);
|
||||||
|
|
||||||
friend QDataStream& operator<<(QDataStream &out, const DataServerAccountInfo& info);
|
friend QDataStream& operator<<(QDataStream &out, const DataServerAccountInfo& info);
|
||||||
friend QDataStream& operator>>(QDataStream &in, DataServerAccountInfo& info);
|
friend QDataStream& operator>>(QDataStream &in, DataServerAccountInfo& info);
|
||||||
signals:
|
signals:
|
||||||
qint64 balanceChanged(qint64 newBalance);
|
qint64 balanceChanged(qint64 newBalance);
|
||||||
private:
|
private:
|
||||||
void swap(DataServerAccountInfo& otherInfo);
|
void swap(DataServerAccountInfo& otherInfo);
|
||||||
|
|
||||||
OAuthAccessToken _accessToken;
|
OAuthAccessToken _accessToken;
|
||||||
QString _username;
|
QString _username;
|
||||||
QString _xmppPassword;
|
QString _xmppPassword;
|
||||||
|
|
|
@ -19,71 +19,70 @@
|
||||||
#include "HifiConfigVariantMap.h"
|
#include "HifiConfigVariantMap.h"
|
||||||
|
|
||||||
QVariantMap HifiConfigVariantMap::mergeCLParametersWithJSONConfig(const QStringList& argumentList) {
|
QVariantMap HifiConfigVariantMap::mergeCLParametersWithJSONConfig(const QStringList& argumentList) {
|
||||||
|
|
||||||
QVariantMap mergedMap;
|
QVariantMap mergedMap;
|
||||||
|
|
||||||
// Add anything in the CL parameter list to the variant map.
|
// Add anything in the CL parameter list to the variant map.
|
||||||
// Take anything with a dash in it as a key, and the values after it as the value.
|
// Take anything with a dash in it as a key, and the values after it as the value.
|
||||||
|
|
||||||
const QString DASHED_KEY_REGEX_STRING = "(^-{1,2})([\\w-]+)";
|
const QString DASHED_KEY_REGEX_STRING = "(^-{1,2})([\\w-]+)";
|
||||||
QRegExp dashedKeyRegex(DASHED_KEY_REGEX_STRING);
|
QRegExp dashedKeyRegex(DASHED_KEY_REGEX_STRING);
|
||||||
|
|
||||||
int keyIndex = argumentList.indexOf(dashedKeyRegex);
|
int keyIndex = argumentList.indexOf(dashedKeyRegex);
|
||||||
int nextKeyIndex = 0;
|
int nextKeyIndex = 0;
|
||||||
|
|
||||||
// check if there is a config file to read where we can pull config info not passed on command line
|
// check if there is a config file to read where we can pull config info not passed on command line
|
||||||
const QString CONFIG_FILE_OPTION = "--config";
|
const QString CONFIG_FILE_OPTION = "--config";
|
||||||
|
|
||||||
while (keyIndex != -1) {
|
while (keyIndex != -1) {
|
||||||
if (argumentList[keyIndex] != CONFIG_FILE_OPTION) {
|
if (argumentList[keyIndex] != CONFIG_FILE_OPTION) {
|
||||||
// we have a key - look forward to see how many values associate to it
|
// we have a key - look forward to see how many values associate to it
|
||||||
QString key = dashedKeyRegex.cap(2);
|
QString key = dashedKeyRegex.cap(2);
|
||||||
|
|
||||||
nextKeyIndex = argumentList.indexOf(dashedKeyRegex, keyIndex + 1);
|
nextKeyIndex = argumentList.indexOf(dashedKeyRegex, keyIndex + 1);
|
||||||
|
|
||||||
if (nextKeyIndex == keyIndex + 1 || keyIndex == argumentList.size() - 1) {
|
if (nextKeyIndex == keyIndex + 1 || keyIndex == argumentList.size() - 1) {
|
||||||
// there's no value associated with this option, it's a boolean
|
// this option is simply a switch, so add it to the map with a value of `true`
|
||||||
// so add it to the variant map with NULL as value
|
mergedMap.insertMulti(key, QVariant(true));
|
||||||
mergedMap.insertMulti(key, QVariant());
|
|
||||||
} else {
|
} else {
|
||||||
int maxIndex = (nextKeyIndex == -1) ? argumentList.size() - 1: nextKeyIndex;
|
int maxIndex = (nextKeyIndex == -1) ? argumentList.size() : nextKeyIndex;
|
||||||
|
|
||||||
// there's at least one value associated with the option
|
// there's at least one value associated with the option
|
||||||
// pull the first value to start
|
// pull the first value to start
|
||||||
QString value = argumentList[keyIndex + 1];
|
QString value = argumentList[keyIndex + 1];
|
||||||
|
|
||||||
// for any extra values, append them, with a space, to the value string
|
// for any extra values, append them, with a space, to the value string
|
||||||
for (int i = keyIndex + 2; i <= maxIndex; i++) {
|
for (int i = keyIndex + 2; i < maxIndex; i++) {
|
||||||
value += " " + argumentList[i];
|
value += " " + argumentList[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the finalized value to the merged map
|
// add the finalized value to the merged map
|
||||||
mergedMap.insert(key, value);
|
mergedMap.insert(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
keyIndex = nextKeyIndex;
|
keyIndex = nextKeyIndex;
|
||||||
} else {
|
} else {
|
||||||
keyIndex = argumentList.indexOf(dashedKeyRegex, keyIndex + 1);
|
keyIndex = argumentList.indexOf(dashedKeyRegex, keyIndex + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int configIndex = argumentList.indexOf(CONFIG_FILE_OPTION);
|
int configIndex = argumentList.indexOf(CONFIG_FILE_OPTION);
|
||||||
|
|
||||||
if (configIndex != -1) {
|
if (configIndex != -1) {
|
||||||
// we have a config file - try and read it
|
// we have a config file - try and read it
|
||||||
QString configFilePath = argumentList[configIndex + 1];
|
QString configFilePath = argumentList[configIndex + 1];
|
||||||
QFile configFile(configFilePath);
|
QFile configFile(configFilePath);
|
||||||
|
|
||||||
if (configFile.exists()) {
|
if (configFile.exists()) {
|
||||||
qDebug() << "Reading JSON config file at" << configFilePath;
|
qDebug() << "Reading JSON config file at" << configFilePath;
|
||||||
configFile.open(QIODevice::ReadOnly);
|
configFile.open(QIODevice::ReadOnly);
|
||||||
|
|
||||||
QJsonDocument configDocument = QJsonDocument::fromJson(configFile.readAll());
|
QJsonDocument configDocument = QJsonDocument::fromJson(configFile.readAll());
|
||||||
QJsonObject rootObject = configDocument.object();
|
QJsonObject rootObject = configDocument.object();
|
||||||
|
|
||||||
// enumerate the keys of the configDocument object
|
// enumerate the keys of the configDocument object
|
||||||
foreach(const QString& key, rootObject.keys()) {
|
foreach(const QString& key, rootObject.keys()) {
|
||||||
|
|
||||||
if (!mergedMap.contains(key)) {
|
if (!mergedMap.contains(key)) {
|
||||||
// no match in existing list, add it
|
// no match in existing list, add it
|
||||||
mergedMap.insert(key, QVariant(rootObject[key]));
|
mergedMap.insert(key, QVariant(rootObject[key]));
|
||||||
|
@ -93,6 +92,6 @@ QVariantMap HifiConfigVariantMap::mergeCLParametersWithJSONConfig(const QStringL
|
||||||
qDebug() << "Could not find JSON config file at" << configFilePath;
|
qDebug() << "Could not find JSON config file at" << configFilePath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return mergedMap;
|
return mergedMap;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue