mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-08 20:50:19 -06:00
Improved exceptions and added error message dialog UI
This commit is contained in:
@@ -27,6 +27,7 @@ set(HEADER_FILES
|
||||
include/assettreemodel.h
|
||||
include/camera.h
|
||||
include/deltatimes.h
|
||||
include/errordialog.h
|
||||
include/filesystemaccess.h
|
||||
include/keybindings.h
|
||||
include/launcherwindow.h
|
||||
@@ -40,6 +41,7 @@ set(HEADER_FILES
|
||||
include/ui_assets.h
|
||||
include/ui_camera.h
|
||||
include/ui_deltatimes.h
|
||||
include/ui_errordialog.h
|
||||
include/ui_keybindings.h
|
||||
include/ui_launcherwindow.h
|
||||
include/ui_marknodes.h
|
||||
@@ -57,6 +59,7 @@ set(SOURCE_FILES
|
||||
src/assettreemodel.cpp
|
||||
src/camera.cpp
|
||||
src/deltatimes.cpp
|
||||
src/errordialog.cpp
|
||||
src/filesystemaccess.cpp
|
||||
src/keybindings.cpp
|
||||
src/launcherwindow.cpp
|
||||
|
||||
@@ -23,7 +23,7 @@ public slots:
|
||||
void parseSelections();
|
||||
|
||||
public:
|
||||
explicit assets(openspace::Profile* imported, std::string& reportAssets,
|
||||
explicit assets(openspace::Profile* imported, const std::string reportAssets,
|
||||
QWidget *parent = nullptr);
|
||||
~assets();
|
||||
std::string createTextSummary();
|
||||
|
||||
@@ -25,8 +25,11 @@ struct DeltaTimes {
|
||||
std::vector<double> _times;
|
||||
DeltaTimes() {
|
||||
_times.resize(sizeof(_defaultDeltaTimes)/sizeof(double));
|
||||
zeroValues();
|
||||
};
|
||||
DeltaTimes(std::vector<double> dt) {
|
||||
_times.resize(sizeof(_defaultDeltaTimes)/sizeof(double));
|
||||
zeroValues();
|
||||
_times = dt;
|
||||
};
|
||||
void loadValues(std::vector<double>& dt) {
|
||||
@@ -39,7 +42,7 @@ struct DeltaTimes {
|
||||
return std::distance(_times.begin(), it);
|
||||
};
|
||||
size_t totalSize() {
|
||||
return sizeof(_defaultDeltaTimes) / sizeof(double);
|
||||
return (sizeof(_defaultDeltaTimes) / sizeof(double));
|
||||
}
|
||||
void zeroValues() {
|
||||
for (size_t i = 0; i < _times.size(); ++i) {
|
||||
|
||||
29
apps/OpenSpace/ext/launcher/include/errordialog.h
Normal file
29
apps/OpenSpace/ext/launcher/include/errordialog.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef ERRORDIALOG_H
|
||||
#define ERRORDIALOG_H
|
||||
|
||||
#include <QDir>
|
||||
#include <QDialog>
|
||||
#include <QLineEdit>
|
||||
#include "ui_errordialog.h"
|
||||
|
||||
namespace Ui {
|
||||
class errordialog;
|
||||
}
|
||||
|
||||
class errordialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public slots:
|
||||
//void accept();
|
||||
|
||||
public:
|
||||
explicit errordialog(QString message, QWidget *parent = nullptr);
|
||||
~errordialog();
|
||||
|
||||
private:
|
||||
Ui::errordialog *ui;
|
||||
QWidget* _parent;
|
||||
};
|
||||
|
||||
#endif // ERRORDIALOG_H
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "marknodes.h"
|
||||
#include "ostime.h"
|
||||
#include <openspace/scene/profile.h>
|
||||
#include <errordialog.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
@@ -22,20 +23,6 @@ class ProfileEdit;
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
|
||||
/*struct ProfileBlock {
|
||||
openspace::Profile::Meta& _metaData;
|
||||
std::vector<openspace::Profile::Module>& _moduleData;
|
||||
std::vector<openspace::Profile::Asset>& _assetData;
|
||||
std::string& _reportAssetsInFilesystem;
|
||||
std::vector<openspace::Profile::Property>& _propsData;
|
||||
std::vector<openspace::Profile::Keybinding>& _keybindingsData;
|
||||
DeltaTimes& _deltaTimesData;
|
||||
openspace::Profile::Time& _timeData;
|
||||
openspace::Profile::CameraType& _cameraData;
|
||||
std::vector<std::string>& _markNodesData;
|
||||
std::string& _addedScriptsData;
|
||||
};*/
|
||||
|
||||
class ProfileEdit : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -51,14 +38,17 @@ public slots:
|
||||
void openDeltaTimes();
|
||||
void openCamera();
|
||||
void openMarkNodes();
|
||||
void cancel();
|
||||
void approved();
|
||||
|
||||
public:
|
||||
explicit ProfileEdit(std::string filename, std::string reportedAssets, QWidget *parent = nullptr);
|
||||
explicit ProfileEdit(std::string filename, const std::string reportedAssets, QWidget *parent = nullptr);
|
||||
~ProfileEdit();
|
||||
//void setProfileName(QString profileToSet);
|
||||
void setProfileName(QString profileToSet);
|
||||
|
||||
private:
|
||||
void loadProfileFromFile(std::string filename);
|
||||
bool loadProfileFromFile(std::string filename);
|
||||
void displayProfileParseErrorDialogThenQuit(std::string msg);
|
||||
void initSummaryTextForEachCategory();
|
||||
QString summarizeText_meta();
|
||||
QString summarizeText_modules();
|
||||
@@ -73,6 +63,7 @@ private:
|
||||
|
||||
Ui::ProfileEdit *ui;
|
||||
QWidget* _parent;
|
||||
errordialog* _myDialog;
|
||||
meta* _meta;
|
||||
properties* _properties;
|
||||
osmodules* _modules;
|
||||
@@ -87,7 +78,7 @@ private:
|
||||
//ProfileBlock _pData;
|
||||
openspace::Profile* _pData = nullptr;
|
||||
std::vector<std::string> _content;
|
||||
std::string& _reportedAssets;
|
||||
const std::string _reportedAssets;
|
||||
};
|
||||
|
||||
#endif // PROFILEEDIT_H
|
||||
|
||||
66
apps/OpenSpace/ext/launcher/include/ui_errordialog.h
Normal file
66
apps/OpenSpace/ext/launcher/include/ui_errordialog.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/********************************************************************************
|
||||
** Form generated from reading UI file 'errordialog.ui'
|
||||
**
|
||||
** Created by: Qt User Interface Compiler version 5.15.0
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost when recompiling UI file!
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef UI_ERRORDIALOG_H
|
||||
#define UI_ERRORDIALOG_H
|
||||
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtWidgets/QDialog>
|
||||
#include <QtWidgets/QDialogButtonBox>
|
||||
#include <QtWidgets/QLabel>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class Ui_errordialog
|
||||
{
|
||||
public:
|
||||
QDialogButtonBox *buttonBox;
|
||||
QLabel *label;
|
||||
|
||||
void setupUi(QDialog *errordialog)
|
||||
{
|
||||
if (errordialog->objectName().isEmpty())
|
||||
errordialog->setObjectName(QString::fromUtf8("errordialog"));
|
||||
errordialog->resize(400, 181);
|
||||
buttonBox = new QDialogButtonBox(errordialog);
|
||||
buttonBox->setObjectName(QString::fromUtf8("buttonBox"));
|
||||
buttonBox->setGeometry(QRect(140, 120, 91, 32));
|
||||
buttonBox->setOrientation(Qt::Horizontal);
|
||||
buttonBox->setStandardButtons(QDialogButtonBox::Ok);
|
||||
label = new QLabel(errordialog);
|
||||
label->setObjectName(QString::fromUtf8("label"));
|
||||
label->setGeometry(QRect(20, 10, 360, 100));
|
||||
QFont font;
|
||||
font.setFamily(QString::fromUtf8("Arial"));
|
||||
font.setPointSize(12);
|
||||
label->setFont(font);
|
||||
label->setWordWrap(true);
|
||||
|
||||
retranslateUi(errordialog);
|
||||
QObject::connect(buttonBox, SIGNAL(accepted()), errordialog, SLOT(accept()));
|
||||
QObject::connect(buttonBox, SIGNAL(rejected()), errordialog, SLOT(reject()));
|
||||
|
||||
QMetaObject::connectSlotsByName(errordialog);
|
||||
} // setupUi
|
||||
|
||||
void retranslateUi(QDialog *errordialog)
|
||||
{
|
||||
errordialog->setWindowTitle(QCoreApplication::translate("errordialog", "Profile Format Error", nullptr));
|
||||
label->setText(QCoreApplication::translate("errordialog", "TextLabel", nullptr));
|
||||
} // retranslateUi
|
||||
|
||||
};
|
||||
|
||||
namespace Ui {
|
||||
class errordialog: public Ui_errordialog {};
|
||||
} // namespace Ui
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // UI_ERRORDIALOG_H
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <string>
|
||||
#include <openspace/scene/profile.h>
|
||||
|
||||
assets::assets(openspace::Profile* imported, std::string& reportAssets, QWidget *parent)
|
||||
assets::assets(openspace::Profile* imported, const std::string reportAssets, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::assets)
|
||||
, _imported(imported)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "deltatimes.h"
|
||||
#include "./ui_deltatimes.h"
|
||||
#include <qevent.h>
|
||||
#include <iostream>
|
||||
|
||||
deltaTimes::deltaTimes(openspace::Profile* imported, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
@@ -10,7 +11,7 @@ deltaTimes::deltaTimes(openspace::Profile* imported, QWidget *parent)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
for (size_t d = 0; d < _data.totalSize(); ++d) {
|
||||
for (size_t d = 0; d < _data.size(); ++d) {
|
||||
QString summary = createSummaryForDeltaTime(d, _data._times.at(d), true);
|
||||
_deltaListItems.push_back(new QListWidgetItem(summary));
|
||||
ui->listWidget->addItem(_deltaListItems[d]);
|
||||
@@ -69,6 +70,9 @@ void deltaTimes::listItemSelected() {
|
||||
}
|
||||
|
||||
int deltaTimes::lastSelectableItem() {
|
||||
if (_data.size() == 0) {
|
||||
return 0;
|
||||
}
|
||||
int i;
|
||||
for (i = _data.size() - 1; i >= 0; --i) {
|
||||
if (_data._times.at(i) != 0) {
|
||||
@@ -112,11 +116,19 @@ QString deltaTimes::checkForTimeDescription(int intervalIndex, double value) {
|
||||
|
||||
void deltaTimes::saveDeltaTimeValue() {
|
||||
QListWidgetItem *item = ui->listWidget->currentItem();
|
||||
int index = ui->listWidget->row(item);
|
||||
if (isNumericalValue(ui->line_seconds) && index <= lastSelectableItem() + 1) {
|
||||
_data._times.at(index) = ui->line_seconds->text().toDouble();
|
||||
QString summary = createSummaryForDeltaTime(index, _data._times.at(index), true);
|
||||
_deltaListItems.at(index)->setText(summary);
|
||||
if (item != nullptr) {
|
||||
int index = ui->listWidget->row(item);
|
||||
if (isNumericalValue(ui->line_seconds) && index <= lastSelectableItem() + 1) {
|
||||
_data._times.at(index) = ui->line_seconds->text().toDouble();
|
||||
QString summary = createSummaryForDeltaTime(index, _data._times.at(index), true);
|
||||
_deltaListItems.at(index)->setText(summary);
|
||||
}
|
||||
}
|
||||
else if (_data.size() == 0) {
|
||||
_data._times.at(0) = ui->line_seconds->text().toDouble();
|
||||
QString summary = createSummaryForDeltaTime(0, _data._times.at(0), true);
|
||||
_deltaListItems.push_back(new QListWidgetItem(summary));
|
||||
ui->listWidget->addItem(_deltaListItems[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
23
apps/OpenSpace/ext/launcher/src/errordialog.cpp
Normal file
23
apps/OpenSpace/ext/launcher/src/errordialog.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "errordialog.h"
|
||||
#include "ui_errordialog.h"
|
||||
#include <QFileSystemModel>
|
||||
#include <QScreen>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
errordialog::errordialog(QString message, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::errordialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->label->setText(message);
|
||||
//connect(ui->buttonBox, SIGNAL(rejected()), this, SLOT(cancel()));
|
||||
}
|
||||
|
||||
errordialog::~errordialog() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
//void errordialog::accept() {
|
||||
// reject();
|
||||
//}
|
||||
87
apps/OpenSpace/ext/launcher/src/errordialog.ui
Normal file
87
apps/OpenSpace/ext/launcher/src/errordialog.ui
Normal file
@@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>errordialog</class>
|
||||
<widget class="QDialog" name="errordialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>181</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Profile Format Error</string>
|
||||
</property>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>140</x>
|
||||
<y>120</y>
|
||||
<width>91</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>60</x>
|
||||
<y>30</y>
|
||||
<width>261</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>errordialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>errordialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -15,17 +15,6 @@ LauncherWindow::LauncherWindow(std::string basePath, QWidget *parent)
|
||||
, _filesystemAccess(".asset", {"scene", "global", "customization", "examples"},
|
||||
true, true)
|
||||
, _basePath(QString::fromUtf8(basePath.c_str()))
|
||||
/*, _pData({_metaData,
|
||||
_moduleData,
|
||||
_assetData,
|
||||
_reportAssetsInFilesystem,
|
||||
_propsData,
|
||||
_keybindingsData,
|
||||
_deltaTimesData,
|
||||
_timeData,
|
||||
_cameraData,
|
||||
_markNodesData,
|
||||
_addedScriptsData})*/
|
||||
{
|
||||
ui->setupUi(this);
|
||||
QString logoPath = _basePath + "/data/openspace-horiz-logo.png";
|
||||
@@ -78,6 +67,7 @@ void LauncherWindow::openWindow_edit() {
|
||||
editProfilePath += profileToSet.toUtf8().constData();
|
||||
editProfilePath += ".profile";
|
||||
myEditorWindow = new ProfileEdit(editProfilePath, _reportAssetsInFilesystem);
|
||||
myEditorWindow->setProfileName(profileToSet);
|
||||
myEditorWindow->exec();
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
template <class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
|
||||
template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
|
||||
|
||||
ProfileEdit::ProfileEdit(std::string filename, std::string reportedAssets, QWidget *parent)
|
||||
ProfileEdit::ProfileEdit(std::string filename, const std::string reportedAssets, QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::ProfileEdit)
|
||||
, _reportedAssets(reportedAssets)
|
||||
@@ -15,7 +15,6 @@ ProfileEdit::ProfileEdit(std::string filename, std::string reportedAssets, QWidg
|
||||
loadProfileFromFile(filename);
|
||||
|
||||
initSummaryTextForEachCategory();
|
||||
|
||||
connect(ui->edit_meta, SIGNAL(clicked()), this, SLOT(openMeta()));
|
||||
connect(ui->edit_properties, SIGNAL(clicked()), this, SLOT(openProperties()));
|
||||
connect(ui->edit_modules, SIGNAL(clicked()), this, SLOT(openModules()));
|
||||
@@ -26,6 +25,8 @@ ProfileEdit::ProfileEdit(std::string filename, std::string reportedAssets, QWidg
|
||||
connect(ui->edit_deltatimes, SIGNAL(clicked()), this, SLOT(openDeltaTimes()));
|
||||
connect(ui->edit_camera, SIGNAL(clicked()), this, SLOT(openCamera()));
|
||||
connect(ui->edit_marknodes, SIGNAL(clicked()), this, SLOT(openMarkNodes()));
|
||||
connect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(approved()));
|
||||
connect(ui->buttonBox, SIGNAL(rejected()), this, SLOT(cancel()));
|
||||
}
|
||||
|
||||
ProfileEdit::~ProfileEdit() {
|
||||
@@ -33,7 +34,7 @@ ProfileEdit::~ProfileEdit() {
|
||||
delete _pData;
|
||||
}
|
||||
|
||||
void ProfileEdit::loadProfileFromFile(std::string filename) {
|
||||
bool ProfileEdit::loadProfileFromFile(std::string filename) {
|
||||
if (filename.length() > 0) {
|
||||
std::ifstream inFile;
|
||||
try {
|
||||
@@ -41,16 +42,53 @@ void ProfileEdit::loadProfileFromFile(std::string filename) {
|
||||
}
|
||||
catch (const std::ifstream::failure& e) {
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"Exception opening profile file for read: {} ({})",
|
||||
filename, e.what())
|
||||
);
|
||||
"Exception opening {} profile for read: ({})",
|
||||
filename,
|
||||
e.what()
|
||||
));
|
||||
}
|
||||
std::string line;
|
||||
while (std::getline(inFile, line)) {
|
||||
_content.push_back(std::move(line));
|
||||
}
|
||||
}
|
||||
_pData = new openspace::Profile(_content);
|
||||
try {
|
||||
_pData = new openspace::Profile(_content);
|
||||
}
|
||||
catch (const ghoul::MissingCaseException& e) {
|
||||
displayProfileParseErrorDialogThenQuit(fmt::format(
|
||||
"Missing case exception in {}: {}",
|
||||
filename,
|
||||
e.what()
|
||||
));
|
||||
return false;
|
||||
}
|
||||
catch (const openspace::Profile::ParsingError& e) {
|
||||
displayProfileParseErrorDialogThenQuit(fmt::format(
|
||||
"ParsingError exception in {}: {}, {}",
|
||||
filename,
|
||||
e.component,
|
||||
e.message
|
||||
));
|
||||
return false;
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
displayProfileParseErrorDialogThenQuit(fmt::format(
|
||||
"RuntimeError exception in {}, component {}: {}",
|
||||
filename,
|
||||
e.component,
|
||||
e.message
|
||||
));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ProfileEdit::displayProfileParseErrorDialogThenQuit(std::string msg) {
|
||||
//New instance of info dialog window
|
||||
_myDialog = new errordialog(QString(msg.c_str()));
|
||||
_myDialog->exec();
|
||||
cancel();
|
||||
}
|
||||
|
||||
void ProfileEdit::initSummaryTextForEachCategory() {
|
||||
@@ -85,9 +123,9 @@ void ProfileEdit::initSummaryTextForEachCategory() {
|
||||
ui->text_additionalscripts->setReadOnly(true);
|
||||
}
|
||||
|
||||
/*void ProfileEdit::setProfileName(QString profileToSet) {
|
||||
void ProfileEdit::setProfileName(QString profileToSet) {
|
||||
ui->line_profile->setText(profileToSet);
|
||||
}*/
|
||||
}
|
||||
|
||||
void ProfileEdit::openMeta() {
|
||||
if (_pData) {
|
||||
@@ -343,3 +381,11 @@ QString ProfileEdit::summarizeText_markNodes() {
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
void ProfileEdit::cancel() {
|
||||
reject();
|
||||
rejected();
|
||||
}
|
||||
|
||||
void ProfileEdit::approved() {
|
||||
}
|
||||
|
||||
@@ -109,6 +109,18 @@ public:
|
||||
std::optional<double> altitude;
|
||||
};
|
||||
using CameraType = std::variant<CameraNavState, CameraGoToGeo>;
|
||||
struct ParsingError : public ghoul::RuntimeError {
|
||||
explicit ParsingError(std::string msg)
|
||||
: ghoul::RuntimeError(std::move(msg), "profileFile")
|
||||
{}
|
||||
|
||||
ParsingError(unsigned int lineNum, std::string msg)
|
||||
: ghoul::RuntimeError(
|
||||
fmt::format("Error @ line {}: {}", lineNum, std::move(msg)),
|
||||
"profileFile"
|
||||
)
|
||||
{}
|
||||
};
|
||||
|
||||
Profile() = default;
|
||||
Profile(const std::vector<std::string>& content);
|
||||
|
||||
@@ -54,19 +54,6 @@ namespace {
|
||||
template <class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
|
||||
template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
|
||||
|
||||
struct ProfileParsingError : public ghoul::RuntimeError {
|
||||
explicit ProfileParsingError(std::string msg)
|
||||
: ghoul::RuntimeError(std::move(msg), "profileFile")
|
||||
{}
|
||||
|
||||
ProfileParsingError(unsigned int lineNum, std::string msg)
|
||||
: ghoul::RuntimeError(
|
||||
fmt::format("Error @ line {}: {}", lineNum, std::move(msg)),
|
||||
"profileFile"
|
||||
)
|
||||
{}
|
||||
};
|
||||
|
||||
std::vector<properties::Property*> changedProperties(
|
||||
const properties::PropertyOwner& po)
|
||||
{
|
||||
@@ -111,7 +98,7 @@ namespace {
|
||||
if (line == headerMarkNodes) { return Section::MarkNodes; }
|
||||
if (line == headerAdditionalScripts) { return Section::AdditionalScripts; }
|
||||
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
fmt::format("Invalid section header: {}", line)
|
||||
);
|
||||
@@ -121,7 +108,7 @@ namespace {
|
||||
{
|
||||
std::vector<std::string> parts = ghoul::tokenizeString(line, '.');
|
||||
if (parts.size() > 2) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
fmt::format("Expected 1-2 version components, got {}", parts.size())
|
||||
);
|
||||
@@ -141,7 +128,7 @@ namespace {
|
||||
return version;
|
||||
}
|
||||
catch (const std::invalid_argument&) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
"Error parsing Version. Version number is not a number"
|
||||
);
|
||||
@@ -151,7 +138,7 @@ namespace {
|
||||
[[ nodiscard ]] Profile::Module parseModule(const std::string& line, int lineNumber) {
|
||||
std::vector<std::string> fields = ghoul::tokenizeString(line, '\t');
|
||||
if (fields.size() != 3) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
fmt::format("Expected 3 fields in a Module entry, got {}", fields.size())
|
||||
);
|
||||
@@ -178,7 +165,7 @@ namespace {
|
||||
{
|
||||
std::vector<std::string> fields = ghoul::tokenizeString(line, '\t');
|
||||
if (fields.size() < 2) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
fmt::format("Expected 2 fields in a Meta line, got {}", fields.size())
|
||||
);
|
||||
@@ -210,7 +197,7 @@ namespace {
|
||||
return { MetaLineType::License, content };
|
||||
}
|
||||
else {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
fmt::format("Unknown meta line type '{}'", type)
|
||||
);
|
||||
@@ -220,7 +207,7 @@ namespace {
|
||||
[[ nodiscard ]] Profile::Asset parseAsset(const std::string& line, int lineNumber) {
|
||||
std::vector<std::string> fields = ghoul::tokenizeString(line, '\t');
|
||||
if (fields.size() != 2) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
fmt::format("Expected 2 fields in an Asset entry, got {}", fields.size())
|
||||
);
|
||||
@@ -235,7 +222,7 @@ namespace {
|
||||
[[ nodiscard ]] Profile::Property parseProperty(const std::string& line, int lineNumber) {
|
||||
std::vector<std::string> fields = ghoul::tokenizeString(line, '\t');
|
||||
if (fields.size() != 3) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
fmt::format("Expected 3 fields in Property entry, got {}", fields.size())
|
||||
);
|
||||
@@ -248,7 +235,7 @@ namespace {
|
||||
if (type == "setPropertyValueSingle") {
|
||||
return Profile::Property::SetType::SetPropertyValueSingle;
|
||||
}
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
fmt::format(
|
||||
"Expected property set type 'setPropertyValue' or "
|
||||
@@ -265,7 +252,7 @@ namespace {
|
||||
[[ nodiscard ]] Profile::Keybinding parseKeybinding(const std::string& line, int lineNumber) {
|
||||
std::vector<std::string> fields = ghoul::tokenizeString(line, '\t');
|
||||
if (fields.size() != 6) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
fmt::format("Expected 6 fields in Keybinding entry, got {}", fields.size())
|
||||
);
|
||||
@@ -275,7 +262,7 @@ namespace {
|
||||
kb.key = stringToKey(fields[0]);
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
throw ProfileParsingError(lineNumber, e.what());
|
||||
throw Profile::ParsingError(lineNumber, e.what());
|
||||
}
|
||||
kb.documentation = fields[1];
|
||||
kb.name = fields[2];
|
||||
@@ -287,7 +274,7 @@ namespace {
|
||||
if (local == "true") {
|
||||
return true;
|
||||
}
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
fmt::format("Expected 'false' or 'true' for the local path, got {}", local)
|
||||
);
|
||||
@@ -299,7 +286,7 @@ namespace {
|
||||
[[ nodiscard ]] Profile::Time parseTime(const std::string& line, int lineNumber) {
|
||||
std::vector<std::string> fields = ghoul::tokenizeString(line, '\t');
|
||||
if (fields.size() != 2) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
fmt::format("Expected 2 fields in Time entry, got {}", fields.size())
|
||||
);
|
||||
@@ -312,7 +299,7 @@ namespace {
|
||||
if (type == "relative") {
|
||||
return Profile::Time::Type::Relative;
|
||||
}
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
fmt::format("Expected 'absolute' or 'relative' for the type, got {}", type)
|
||||
);
|
||||
@@ -326,7 +313,7 @@ namespace {
|
||||
return std::stod(line);
|
||||
}
|
||||
catch (const std::invalid_argument&) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
fmt::format("Expected a number for delta time entry, got '{}'", line)
|
||||
);
|
||||
@@ -340,7 +327,7 @@ namespace {
|
||||
{
|
||||
if (type == Profile::CameraNavState::Type) {
|
||||
if (fields.size() != 8) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
fmt::format(
|
||||
"Expected 8 fields in the Camera entry, got {}", fields.size()
|
||||
@@ -355,7 +342,7 @@ namespace {
|
||||
|
||||
std::vector<std::string> position = ghoul::tokenizeString(fields[4], ' ');
|
||||
if (position.size() != 3) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
fmt::format(
|
||||
"Expected 3 fields for the camera's position, got {}",
|
||||
@@ -371,7 +358,7 @@ namespace {
|
||||
);
|
||||
}
|
||||
catch (const std::invalid_argument&) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
"Camera's position components must be numbers"
|
||||
);
|
||||
@@ -379,7 +366,7 @@ namespace {
|
||||
|
||||
std::vector<std::string> up = ghoul::tokenizeString(fields[5], ' ');
|
||||
if (up.size() != 0 && up.size() != 3) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
fmt::format(
|
||||
"Expected 0 or 3 fields for the camera's up vector, got {}",
|
||||
@@ -396,7 +383,7 @@ namespace {
|
||||
);
|
||||
}
|
||||
catch (const std::invalid_argument&) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
"Camera's up vector components must be numbers"
|
||||
);
|
||||
@@ -408,7 +395,7 @@ namespace {
|
||||
camera.yaw = std::stod(fields[6]);
|
||||
}
|
||||
catch (const std::invalid_argument&) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
"Camera's yaw value must be a number"
|
||||
);
|
||||
@@ -420,7 +407,7 @@ namespace {
|
||||
camera.pitch = std::stod(fields[7]);
|
||||
}
|
||||
catch (const std::invalid_argument&) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
"Camera's pitch value must be a number"
|
||||
);
|
||||
@@ -430,7 +417,7 @@ namespace {
|
||||
}
|
||||
if (type == Profile::CameraGoToGeo::Type) {
|
||||
if (fields.size() != 5) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
fmt::format(
|
||||
"Expected 5 fields in the Camera entry, got {}", fields.size()
|
||||
@@ -447,7 +434,7 @@ namespace {
|
||||
}
|
||||
return camera;
|
||||
}
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNumber,
|
||||
fmt::format(
|
||||
"Expected 'setNavigationState' or 'goToGeo' for the type, got {}",
|
||||
@@ -764,7 +751,7 @@ Profile::Profile(const std::vector<std::string>& content) {
|
||||
}
|
||||
|
||||
if (currentSection != Section::None && line[0] == '#') {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNum,
|
||||
"Sections in profile must be separated by empty lines"
|
||||
);
|
||||
@@ -775,7 +762,7 @@ Profile::Profile(const std::vector<std::string>& content) {
|
||||
currentSection = parseSection(line, lineNum);
|
||||
|
||||
if (!foundVersion && currentSection != Section::Version) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNum,
|
||||
fmt::format(
|
||||
"First header in the file must be Version, but got {}", line
|
||||
@@ -784,7 +771,7 @@ Profile::Profile(const std::vector<std::string>& content) {
|
||||
}
|
||||
|
||||
if (currentSection == Section::Meta && foundMeta) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNum,
|
||||
"Meta section can only appear once per profile"
|
||||
);
|
||||
@@ -792,7 +779,7 @@ Profile::Profile(const std::vector<std::string>& content) {
|
||||
break;
|
||||
case Section::Version:
|
||||
if (foundVersion) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNum,
|
||||
"Version section can only appear once per profile"
|
||||
);
|
||||
@@ -811,7 +798,7 @@ Profile::Profile(const std::vector<std::string>& content) {
|
||||
switch (m.first) {
|
||||
case MetaLineType::Name:
|
||||
if (!_meta->name.empty()) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNum,
|
||||
"Meta information 'Name' specified twice"
|
||||
);
|
||||
@@ -820,7 +807,7 @@ Profile::Profile(const std::vector<std::string>& content) {
|
||||
break;
|
||||
case MetaLineType::Version:
|
||||
if (!_meta->version.empty()) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNum,
|
||||
"Meta information 'Version' specified twice"
|
||||
);
|
||||
@@ -829,7 +816,7 @@ Profile::Profile(const std::vector<std::string>& content) {
|
||||
break;
|
||||
case MetaLineType::Description:
|
||||
if (!_meta->description.empty()) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNum,
|
||||
"Meta information 'Description' specified twice"
|
||||
);
|
||||
@@ -838,7 +825,7 @@ Profile::Profile(const std::vector<std::string>& content) {
|
||||
break;
|
||||
case MetaLineType::Author:
|
||||
if (!_meta->author.empty()) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNum,
|
||||
"Meta information 'Author' specified twice"
|
||||
);
|
||||
@@ -847,7 +834,7 @@ Profile::Profile(const std::vector<std::string>& content) {
|
||||
break;
|
||||
case MetaLineType::URL:
|
||||
if (!_meta->url.empty()) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNum,
|
||||
"Meta information 'URL' specified twice"
|
||||
);
|
||||
@@ -856,7 +843,7 @@ Profile::Profile(const std::vector<std::string>& content) {
|
||||
break;
|
||||
case MetaLineType::License:
|
||||
if (!_meta->license.empty()) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNum,
|
||||
"Meta information 'License' specified twice"
|
||||
);
|
||||
@@ -895,7 +882,7 @@ Profile::Profile(const std::vector<std::string>& content) {
|
||||
}
|
||||
case Section::Time:
|
||||
if (foundTime) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNum,
|
||||
"Time section can only appear once per profile"
|
||||
);
|
||||
@@ -912,7 +899,7 @@ Profile::Profile(const std::vector<std::string>& content) {
|
||||
}
|
||||
case Section::Camera:
|
||||
if (foundCamera) {
|
||||
throw ProfileParsingError(
|
||||
throw Profile::ParsingError(
|
||||
lineNum,
|
||||
"Camera section can only appear once per profile"
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user