mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-29 19:22:57 +02:00
Merge pull request #933 from birarda/assignment
add handling of Agent assignments to Assignment, DS, AC
This commit is contained in:
commit
bc95f94157
19 changed files with 88 additions and 30 deletions
|
@ -8,9 +8,17 @@ set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||||
# setup for find modules
|
# setup for find modules
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
|
||||||
|
|
||||||
|
find_package(Qt5Network REQUIRED)
|
||||||
|
|
||||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||||
setup_hifi_project(${TARGET_NAME} TRUE)
|
setup_hifi_project(${TARGET_NAME} TRUE)
|
||||||
|
|
||||||
|
qt5_use_modules(${TARGET_NAME} Network)
|
||||||
|
|
||||||
|
# include glm
|
||||||
|
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||||
|
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||||
|
|
||||||
# link in the shared library
|
# link in the shared library
|
||||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||||
|
|
|
@ -25,11 +25,11 @@ void Agent::run(QUrl scriptURL) {
|
||||||
NodeList::getInstance()->setOwnerType(NODE_TYPE_AGENT);
|
NodeList::getInstance()->setOwnerType(NODE_TYPE_AGENT);
|
||||||
NodeList::getInstance()->setNodeTypesOfInterest(&NODE_TYPE_AVATAR_MIXER, 1);
|
NodeList::getInstance()->setNodeTypesOfInterest(&NODE_TYPE_AVATAR_MIXER, 1);
|
||||||
|
|
||||||
QNetworkAccessManager* manager = new QNetworkAccessManager();
|
QNetworkAccessManager manager;
|
||||||
|
|
||||||
qDebug() << "Attemping download of " << scriptURL;
|
qDebug() << "Attemping download of " << scriptURL << "\n";
|
||||||
|
|
||||||
QNetworkReply* reply = manager->get(QNetworkRequest(scriptURL));
|
QNetworkReply* reply = manager.get(QNetworkRequest(scriptURL));
|
||||||
|
|
||||||
QEventLoop loop;
|
QEventLoop loop;
|
||||||
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
|
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||||
|
@ -47,15 +47,14 @@ void Agent::run(QUrl scriptURL) {
|
||||||
QScriptValue agentValue = engine.newQObject(this);
|
QScriptValue agentValue = engine.newQObject(this);
|
||||||
engine.globalObject().setProperty("Agent", agentValue);
|
engine.globalObject().setProperty("Agent", agentValue);
|
||||||
|
|
||||||
qDebug() << "Downloaded script:" << scriptString;
|
qDebug() << "Downloaded script:" << scriptString << "\n";
|
||||||
|
qDebug() << "Evaluated script:" << engine.evaluate(scriptString).toString() << "\n";
|
||||||
qDebug() << "Evaluated script:" << engine.evaluate(scriptString).toString();
|
|
||||||
|
|
||||||
timeval thisSend;
|
timeval thisSend;
|
||||||
timeval lastDomainServerCheckIn = {};
|
timeval lastDomainServerCheckIn = {};
|
||||||
int numMicrosecondsSleep = 0;
|
int numMicrosecondsSleep = 0;
|
||||||
|
|
||||||
const float DATA_SEND_INTERVAL_USECS = (1 / 60.0f) * 1000 * 1000;
|
const long long DATA_SEND_INTERVAL_USECS = (1 / 60.0f) * 1000 * 1000;
|
||||||
|
|
||||||
sockaddr_in senderAddress;
|
sockaddr_in senderAddress;
|
||||||
unsigned char receivedData[MAX_PACKET_SIZE];
|
unsigned char receivedData[MAX_PACKET_SIZE];
|
||||||
|
@ -65,6 +64,11 @@ void Agent::run(QUrl scriptURL) {
|
||||||
// update the thisSend timeval to the current time
|
// update the thisSend timeval to the current time
|
||||||
gettimeofday(&thisSend, NULL);
|
gettimeofday(&thisSend, NULL);
|
||||||
|
|
||||||
|
// if we're not hearing from the domain-server we should stop running
|
||||||
|
if (NodeList::getInstance()->getNumNoReplyDomainCheckIns() == MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed
|
// send a check in packet to the domain server if DOMAIN_SERVER_CHECK_IN_USECS has elapsed
|
||||||
if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) {
|
if (usecTimestampNow() - usecTimestamp(&lastDomainServerCheckIn) >= DOMAIN_SERVER_CHECK_IN_USECS) {
|
||||||
gettimeofday(&lastDomainServerCheckIn, NULL);
|
gettimeofday(&lastDomainServerCheckIn, NULL);
|
|
@ -9,9 +9,6 @@
|
||||||
#ifndef __hifi__Agent__
|
#ifndef __hifi__Agent__
|
||||||
#define __hifi__Agent__
|
#define __hifi__Agent__
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
#include <glm/gtc/quaternion.hpp>
|
|
||||||
|
|
||||||
#include "SharedUtil.h"
|
#include "SharedUtil.h"
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
|
@ -12,6 +12,9 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include <QtCore/QCoreApplication>
|
||||||
|
|
||||||
|
#include "Agent.h"
|
||||||
#include <Assignment.h>
|
#include <Assignment.h>
|
||||||
#include <AudioMixer.h>
|
#include <AudioMixer.h>
|
||||||
#include <AvatarMixer.h>
|
#include <AvatarMixer.h>
|
||||||
|
@ -92,8 +95,18 @@ void childClient() {
|
||||||
|
|
||||||
if (deployedAssignment.getType() == Assignment::AudioMixerType) {
|
if (deployedAssignment.getType() == Assignment::AudioMixerType) {
|
||||||
AudioMixer::run();
|
AudioMixer::run();
|
||||||
} else {
|
} else if (deployedAssignment.getType() == Assignment::AvatarMixerType) {
|
||||||
AvatarMixer::run();
|
AvatarMixer::run();
|
||||||
|
} else {
|
||||||
|
// figure out the URL for the script for this agent assignment
|
||||||
|
QString scriptURLString("http://%1:8080/assignment/%2");
|
||||||
|
scriptURLString = scriptURLString.arg(inet_ntoa(domainSocketAddr),
|
||||||
|
deployedAssignment.getUUIDStringWithoutCurlyBraces());
|
||||||
|
|
||||||
|
qDebug() << "Starting an Agent assignment-client with script at" << scriptURLString << "\n";
|
||||||
|
|
||||||
|
Agent scriptAgent;
|
||||||
|
scriptAgent.run(QUrl(scriptURLString));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
qDebug("Received a bad destination socket for assignment.\n");
|
qDebug("Received a bad destination socket for assignment.\n");
|
||||||
|
@ -171,6 +184,8 @@ void parentMonitor() {
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
|
QCoreApplication app(argc, (char**) argv);
|
||||||
|
|
||||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||||
|
|
||||||
// use the verbose message handler in Logging
|
// use the verbose message handler in Logging
|
||||||
|
|
|
@ -11,11 +11,11 @@ setup_hifi_project(${TARGET_NAME} TRUE)
|
||||||
# remove and then copy the files for the webserver
|
# remove and then copy the files for the webserver
|
||||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E remove_directory
|
COMMAND ${CMAKE_COMMAND} -E remove_directory
|
||||||
$<TARGET_FILE_DIR:${TARGET_NAME}>/web)
|
$<TARGET_FILE_DIR:${TARGET_NAME}>/resources/web)
|
||||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||||
"${PROJECT_SOURCE_DIR}/src/web"
|
"${PROJECT_SOURCE_DIR}/resources/web"
|
||||||
$<TARGET_FILE_DIR:${TARGET_NAME}>/web)
|
$<TARGET_FILE_DIR:${TARGET_NAME}>/resources/web)
|
||||||
|
|
||||||
# link the shared hifi library
|
# link the shared hifi library
|
||||||
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <QtCore/QMutex>
|
||||||
|
|
||||||
#include "Assignment.h"
|
#include "Assignment.h"
|
||||||
#include "NodeList.h"
|
#include "NodeList.h"
|
||||||
#include "NodeTypes.h"
|
#include "NodeTypes.h"
|
||||||
|
@ -40,6 +42,9 @@ unsigned char packetData[MAX_PACKET_SIZE];
|
||||||
|
|
||||||
const int NODE_COUNT_STAT_INTERVAL_MSECS = 5000;
|
const int NODE_COUNT_STAT_INTERVAL_MSECS = 5000;
|
||||||
|
|
||||||
|
QMutex assignmentQueueMutex;
|
||||||
|
std::deque<Assignment*> assignmentQueue;
|
||||||
|
|
||||||
unsigned char* addNodeToBroadcastPacket(unsigned char* currentPosition, Node* nodeToAdd) {
|
unsigned char* addNodeToBroadcastPacket(unsigned char* currentPosition, Node* nodeToAdd) {
|
||||||
*currentPosition++ = nodeToAdd->getType();
|
*currentPosition++ = nodeToAdd->getType();
|
||||||
|
|
||||||
|
@ -70,18 +75,25 @@ static int mongooseRequestHandler(struct mg_connection *conn) {
|
||||||
const char ASSIGNMENT_SCRIPT_HOST_LOCATION[] = "web/assignment";
|
const char ASSIGNMENT_SCRIPT_HOST_LOCATION[] = "web/assignment";
|
||||||
|
|
||||||
static void mongooseUploadHandler(struct mg_connection *conn, const char *path) {
|
static void mongooseUploadHandler(struct mg_connection *conn, const char *path) {
|
||||||
// create an assignment for this saved script
|
// create an assignment for this saved script, for now make it local only
|
||||||
Assignment scriptAssignment(Assignment::CreateCommand, Assignment::AgentType);
|
Assignment *scriptAssignment = new Assignment(Assignment::CreateCommand, Assignment::AgentType, Assignment::LocalLocation);
|
||||||
|
|
||||||
QString newPath(ASSIGNMENT_SCRIPT_HOST_LOCATION);
|
QString newPath(ASSIGNMENT_SCRIPT_HOST_LOCATION);
|
||||||
newPath += "/";
|
newPath += "/";
|
||||||
// append the UUID for this script as the new filename, remove the curly braces
|
// append the UUID for this script as the new filename, remove the curly braces
|
||||||
newPath += scriptAssignment.getUUID().toString().mid(1, scriptAssignment.getUUID().toString().length() - 2);
|
newPath += scriptAssignment->getUUIDStringWithoutCurlyBraces();
|
||||||
|
|
||||||
// rename the saved script to the GUID of the assignment and move it to the script host locaiton
|
// rename the saved script to the GUID of the assignment and move it to the script host locaiton
|
||||||
rename(path, newPath.toStdString().c_str());
|
rename(path, newPath.toStdString().c_str());
|
||||||
|
|
||||||
qDebug("Saved a script for assignment at %s\n", newPath.toStdString().c_str());
|
qDebug("Saved a script for assignment at %s\n", newPath.toStdString().c_str());
|
||||||
|
|
||||||
|
// add the script assigment to the assignment queue
|
||||||
|
// lock the assignment queue mutex since we're operating on a different thread than DS main
|
||||||
|
::assignmentQueueMutex.lock();
|
||||||
|
::assignmentQueue.push_back(scriptAssignment);
|
||||||
|
::assignmentQueueMutex.unlock();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
|
@ -121,9 +133,6 @@ int main(int argc, const char* argv[]) {
|
||||||
const long long GLOBAL_ASSIGNMENT_REQUEST_INTERVAL_USECS = 1 * 1000 * 1000;
|
const long long GLOBAL_ASSIGNMENT_REQUEST_INTERVAL_USECS = 1 * 1000 * 1000;
|
||||||
timeval lastGlobalAssignmentRequest = {};
|
timeval lastGlobalAssignmentRequest = {};
|
||||||
|
|
||||||
// setup the assignment queue
|
|
||||||
std::deque<Assignment*> assignmentQueue;
|
|
||||||
|
|
||||||
// as a domain-server we will always want an audio mixer and avatar mixer
|
// as a domain-server we will always want an audio mixer and avatar mixer
|
||||||
// setup the create assignments for those
|
// setup the create assignments for those
|
||||||
Assignment audioMixerAssignment(Assignment::CreateCommand,
|
Assignment audioMixerAssignment(Assignment::CreateCommand,
|
||||||
|
@ -146,7 +155,7 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
// list of options. Last element must be NULL.
|
// list of options. Last element must be NULL.
|
||||||
const char *options[] = {"listening_ports", "8080",
|
const char *options[] = {"listening_ports", "8080",
|
||||||
"document_root", "./web", NULL};
|
"document_root", "./resources/web", NULL};
|
||||||
|
|
||||||
callbacks.begin_request = mongooseRequestHandler;
|
callbacks.begin_request = mongooseRequestHandler;
|
||||||
callbacks.upload = mongooseUploadHandler;
|
callbacks.upload = mongooseUploadHandler;
|
||||||
|
@ -156,19 +165,21 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
||||||
|
::assignmentQueueMutex.lock();
|
||||||
// check if our audio-mixer or avatar-mixer are dead and we don't have existing assignments in the queue
|
// check if our audio-mixer or avatar-mixer are dead and we don't have existing assignments in the queue
|
||||||
// so we can add those assignments back to the front of the queue since they are high-priority
|
// so we can add those assignments back to the front of the queue since they are high-priority
|
||||||
if (!nodeList->soloNodeOfType(NODE_TYPE_AVATAR_MIXER) &&
|
if (!nodeList->soloNodeOfType(NODE_TYPE_AVATAR_MIXER) &&
|
||||||
std::find(assignmentQueue.begin(), assignmentQueue.end(), &avatarMixerAssignment) == assignmentQueue.end()) {
|
std::find(::assignmentQueue.begin(), assignmentQueue.end(), &avatarMixerAssignment) == ::assignmentQueue.end()) {
|
||||||
qDebug("Missing an avatar mixer and assignment not in queue. Adding.\n");
|
qDebug("Missing an avatar mixer and assignment not in queue. Adding.\n");
|
||||||
assignmentQueue.push_front(&avatarMixerAssignment);
|
::assignmentQueue.push_front(&avatarMixerAssignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER) &&
|
if (!nodeList->soloNodeOfType(NODE_TYPE_AUDIO_MIXER) &&
|
||||||
std::find(assignmentQueue.begin(), assignmentQueue.end(), &audioMixerAssignment) == assignmentQueue.end()) {
|
std::find(::assignmentQueue.begin(), ::assignmentQueue.end(), &audioMixerAssignment) == ::assignmentQueue.end()) {
|
||||||
qDebug("Missing an audio mixer and assignment not in queue. Adding.\n");
|
qDebug("Missing an audio mixer and assignment not in queue. Adding.\n");
|
||||||
assignmentQueue.push_front(&audioMixerAssignment);
|
::assignmentQueue.push_front(&audioMixerAssignment);
|
||||||
}
|
}
|
||||||
|
::assignmentQueueMutex.unlock();
|
||||||
|
|
||||||
while (nodeList->getNodeSocket()->receive((sockaddr *)&nodePublicAddress, packetData, &receivedBytes) &&
|
while (nodeList->getNodeSocket()->receive((sockaddr *)&nodePublicAddress, packetData, &receivedBytes) &&
|
||||||
packetVersionMatch(packetData)) {
|
packetVersionMatch(packetData)) {
|
||||||
|
@ -269,11 +280,13 @@ int main(int argc, const char* argv[]) {
|
||||||
|
|
||||||
qDebug("Received a request for assignment.\n");
|
qDebug("Received a request for assignment.\n");
|
||||||
|
|
||||||
|
::assignmentQueueMutex.lock();
|
||||||
|
|
||||||
// this is an unassigned client talking to us directly for an assignment
|
// this is an unassigned client talking to us directly for an assignment
|
||||||
// go through our queue and see if there are any assignments to give out
|
// go through our queue and see if there are any assignments to give out
|
||||||
std::deque<Assignment*>::iterator assignment = assignmentQueue.begin();
|
std::deque<Assignment*>::iterator assignment = ::assignmentQueue.begin();
|
||||||
|
|
||||||
while (assignment != assignmentQueue.end()) {
|
while (assignment != ::assignmentQueue.end()) {
|
||||||
|
|
||||||
// give this assignment out, no conditions stop us from giving it to the local assignment client
|
// give this assignment out, no conditions stop us from giving it to the local assignment client
|
||||||
int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_CREATE_ASSIGNMENT);
|
int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_CREATE_ASSIGNMENT);
|
||||||
|
@ -284,11 +297,18 @@ int main(int argc, const char* argv[]) {
|
||||||
numHeaderBytes + numAssignmentBytes);
|
numHeaderBytes + numAssignmentBytes);
|
||||||
|
|
||||||
// remove the assignment from the queue
|
// remove the assignment from the queue
|
||||||
assignmentQueue.erase(assignment);
|
::assignmentQueue.erase(assignment);
|
||||||
|
|
||||||
|
if ((*assignment)->getType() == Assignment::AgentType) {
|
||||||
|
// if this is a script assignment we need to delete it to avoid a memory leak
|
||||||
|
delete *assignment;
|
||||||
|
}
|
||||||
|
|
||||||
// stop looping, we've handed out an assignment
|
// stop looping, we've handed out an assignment
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::assignmentQueueMutex.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,8 +316,10 @@ int main(int argc, const char* argv[]) {
|
||||||
if (usecTimestampNow() - usecTimestamp(&lastGlobalAssignmentRequest) >= GLOBAL_ASSIGNMENT_REQUEST_INTERVAL_USECS) {
|
if (usecTimestampNow() - usecTimestamp(&lastGlobalAssignmentRequest) >= GLOBAL_ASSIGNMENT_REQUEST_INTERVAL_USECS) {
|
||||||
gettimeofday(&lastGlobalAssignmentRequest, NULL);
|
gettimeofday(&lastGlobalAssignmentRequest, NULL);
|
||||||
|
|
||||||
|
::assignmentQueueMutex.lock();
|
||||||
|
|
||||||
// go through our queue and see if there are any assignments to send to the global assignment server
|
// go through our queue and see if there are any assignments to send to the global assignment server
|
||||||
std::deque<Assignment*>::iterator assignment = assignmentQueue.begin();
|
std::deque<Assignment*>::iterator assignment = ::assignmentQueue.begin();
|
||||||
|
|
||||||
while (assignment != assignmentQueue.end()) {
|
while (assignment != assignmentQueue.end()) {
|
||||||
|
|
||||||
|
@ -308,7 +330,12 @@ int main(int argc, const char* argv[]) {
|
||||||
nodeList->sendAssignment(*(*assignment));
|
nodeList->sendAssignment(*(*assignment));
|
||||||
|
|
||||||
// remove the assignment from the queue
|
// remove the assignment from the queue
|
||||||
assignmentQueue.erase(assignment);
|
::assignmentQueue.erase(assignment);
|
||||||
|
|
||||||
|
if ((*assignment)->getType() == Assignment::AgentType) {
|
||||||
|
// if this is a script assignment we need to delete it to avoid a memory leak
|
||||||
|
delete *assignment;
|
||||||
|
}
|
||||||
|
|
||||||
// stop looping, we've handed out an assignment
|
// stop looping, we've handed out an assignment
|
||||||
break;
|
break;
|
||||||
|
@ -318,6 +345,7 @@ int main(int argc, const char* argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::assignmentQueueMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Logging::shouldSendStats()) {
|
if (Logging::shouldSendStats()) {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
//
|
//
|
||||||
// AudioMixer.cpp
|
// AudioMixer.cpp
|
||||||
// hifi
|
// hifi
|
||||||
|
|
|
@ -89,6 +89,10 @@ Assignment::~Assignment() {
|
||||||
delete _attachedLocalSocket;
|
delete _attachedLocalSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Assignment::getUUIDStringWithoutCurlyBraces() const {
|
||||||
|
return _uuid.toString().mid(1, _uuid.toString().length() - 2);
|
||||||
|
}
|
||||||
|
|
||||||
void Assignment::setAttachedPublicSocket(const sockaddr* attachedPublicSocket) {
|
void Assignment::setAttachedPublicSocket(const sockaddr* attachedPublicSocket) {
|
||||||
if (_attachedPublicSocket) {
|
if (_attachedPublicSocket) {
|
||||||
// delete the old socket if it exists
|
// delete the old socket if it exists
|
||||||
|
|
|
@ -49,6 +49,7 @@ public:
|
||||||
~Assignment();
|
~Assignment();
|
||||||
|
|
||||||
const QUuid& getUUID() const { return _uuid; }
|
const QUuid& getUUID() const { return _uuid; }
|
||||||
|
QString getUUIDStringWithoutCurlyBraces() const;
|
||||||
Assignment::Command getCommand() const { return _command; }
|
Assignment::Command getCommand() const { return _command; }
|
||||||
Assignment::Type getType() const { return _type; }
|
Assignment::Type getType() const { return _type; }
|
||||||
Assignment::Location getLocation() const { return _location; }
|
Assignment::Location getLocation() const { return _location; }
|
||||||
|
|
Loading…
Reference in a new issue