Thu, 03 Oct 2019 11:45:44 +0300
stuff
src/documentmanager.cpp | file | annotate | diff | comparison | revisions | |
src/documentmanager.h | file | annotate | diff | comparison | revisions | |
src/mainwindow.cpp | file | annotate | diff | comparison | revisions | |
src/mainwindow.h | file | annotate | diff | comparison | revisions | |
src/mainwindow.ui | file | annotate | diff | comparison | revisions | |
src/model.h | file | annotate | diff | comparison | revisions | |
src/modeleditcontext.h | file | annotate | diff | comparison | revisions | |
src/parser.cpp | file | annotate | diff | comparison | revisions | |
src/parser.h | file | annotate | diff | comparison | revisions | |
src/vertex.cpp | file | annotate | diff | comparison | revisions | |
src/vertex.h | file | annotate | diff | comparison | revisions |
--- a/src/documentmanager.cpp Mon Sep 23 14:06:36 2019 +0300 +++ b/src/documentmanager.cpp Thu Oct 03 11:45:44 2019 +0300 @@ -1,5 +1,10 @@ #include "documentmanager.h" +DocumentManager::DocumentManager(QObject* parent) : + QObject{parent} +{ +} + Model* DocumentManager::newModel() { openModels.emplace_back();
--- a/src/documentmanager.h Mon Sep 23 14:06:36 2019 +0300 +++ b/src/documentmanager.h Thu Oct 03 11:45:44 2019 +0300 @@ -2,10 +2,11 @@ #include "main.h" #include "model.h" -class DocumentManager +class DocumentManager : public QObject { + Q_OBJECT public: - DocumentManager() = default; + DocumentManager(QObject* parent = nullptr); DocumentManager(const DocumentManager&) = delete; DocumentManager(DocumentManager&&) = default; DocumentManager& operator=(const DocumentManager&) = delete;
--- a/src/mainwindow.cpp Mon Sep 23 14:06:36 2019 +0300 +++ b/src/mainwindow.cpp Thu Oct 03 11:45:44 2019 +0300 @@ -1,20 +1,107 @@ #include "mainwindow.h" #include "ui_mainwindow.h" #include "version.h" -#include <QQuaternion> +#include <QLabel> +#include <QVBoxLayout> MainWindow::MainWindow(QWidget *parent) : QMainWindow{parent}, - ui{std::make_unique<Ui_MainWindow>()} + ui{std::make_unique<Ui_MainWindow>()}, + documents{this} { ui->setupUi(this); + connect(ui->actionNew, &QAction::triggered, this, &MainWindow::newModel); connect(ui->actionQuit, &QAction::triggered, this, &QMainWindow::close); + updateTitle(); +} + +MainWindow::~MainWindow() +{ +} + +void MainWindow::newModel() +{ + documents.newModel(); + this->updateTabs(); +} + +#include <QFileDialog> +#include <QMessageBox> +void MainWindow::openModel() +{ + const QString path = QFileDialog::getOpenFileName( + this, "Open model", "", "LDraw models (*.ldr *.dat)"); + if (not path.isEmpty()) + { + QFile file{path}; + const bool open_result = file.open(QIODevice::ReadOnly); + if (open_result) + { + + } + else + { + QMessageBox::critical(this, "Problem opening file", + QString{"Could not open %1: %2"} + .arg(path) + .arg(file.errorString())); + } + } +} + +/** + * @brief Creates a new tab widget for the specified model. + * @param model Model to get a new tab widget for + * @return widget + */ +QWidget* MainWindow::createWidgetForModel(Model* model) +{ + Q_UNUSED(model); + QWidget* widget = new QWidget(ui->tabs); + QLabel* label = new QLabel("asdf", widget); + QVBoxLayout* layout = new QVBoxLayout; + layout->addWidget(label); + widget->setLayout(layout); + return widget; +} + +/** + * @brief Gets a tab widget for the specified model. If it does not exist, + * it will be created. + * @param model Model to get a tab widget for + * @return widget + */ +QWidget* MainWindow::getWidgetForModel(Model* model) +{ + QWidget* widget = this->modelWidgets.value(model); + if (widget == nullptr) + { + QWidget* const new_widget = createWidgetForModel(model); + this->modelWidgets[model] = new_widget; + return new_widget; + } + else + { + return widget; + } +} + +/** + * @brief Updates the tab widget + */ +void MainWindow::updateTabs() +{ + +} + +/** + * @brief Updates the title of the main window so to contain the app's name + * and version as well as the open document name. + */ +void MainWindow::updateTitle() +{ QString title = ::appName; title += " "; title += fullVersionString(); setWindowTitle(title); } - -MainWindow::~MainWindow() -{ -}
--- a/src/mainwindow.h Mon Sep 23 14:06:36 2019 +0300 +++ b/src/mainwindow.h Thu Oct 03 11:45:44 2019 +0300 @@ -2,6 +2,7 @@ #include <QMainWindow> #include <memory> #include <vector> +#include "documentmanager.h" class MainWindow : public QMainWindow { @@ -9,6 +10,15 @@ public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); +private slots: + void newModel(); + void openModel(); private: std::unique_ptr<class Ui_MainWindow> ui; + DocumentManager documents; + QMap<Model*, QWidget*> modelWidgets; + QWidget* createWidgetForModel(Model* model); + QWidget* getWidgetForModel(Model* model); + void updateTabs(); + void updateTitle(); };
--- a/src/mainwindow.ui Mon Sep 23 14:06:36 2019 +0300 +++ b/src/mainwindow.ui Thu Oct 03 11:45:44 2019 +0300 @@ -26,14 +26,14 @@ <x>0</x> <y>0</y> <width>800</width> - <height>25</height> + <height>27</height> </rect> </property> <widget class="QMenu" name="menuFile"> <property name="title"> <string>File</string> </property> - <addaction name="actionNewFile"/> + <addaction name="actionNew"/> <addaction name="actionOpen"/> <addaction name="separator"/> <addaction name="actionQuit"/> @@ -54,9 +54,9 @@ <string>Ctrl+O</string> </property> </action> - <action name="actionNewFile"> + <action name="actionNew"> <property name="text"> - <string>New File</string> + <string>New</string> </property> <property name="shortcut"> <string>Ctrl+N</string>
--- a/src/model.h Mon Sep 23 14:06:36 2019 +0300 +++ b/src/model.h Thu Oct 03 11:45:44 2019 +0300 @@ -10,7 +10,7 @@ public: class EditContext; Model(); - Model(const Model &) = delete; + Model(const Model&) = delete; int size() const; EditContext edit(); private:
--- a/src/modeleditcontext.h Mon Sep 23 14:06:36 2019 +0300 +++ b/src/modeleditcontext.h Thu Oct 03 11:45:44 2019 +0300 @@ -6,9 +6,9 @@ { public: template<typename T, typename... Args> - modelobjects::BaseObject* append(Args&&... args); + T* append(Args&&... args); template<typename T, typename... Args> - modelobjects::BaseObject* insert(int position, Args&&... args); + T* insert(int position, Args&&... args); void setObjectProperty( modelobjects::BaseObject* object, modelobjects::Property property, @@ -20,13 +20,13 @@ }; template<typename T, typename... Args> -modelobjects::BaseObject* Model::EditContext::append(Args&&... args) +T* Model::EditContext::append(Args&&... args) { return this->model.append<T>(args...); } template<typename T, typename... Args> -modelobjects::BaseObject* Model::EditContext::insert(int position, Args&&... args) +T* Model::EditContext::insert(int position, Args&&... args) { return this->model.insert<T>(position, args...); }
--- a/src/parser.cpp Mon Sep 23 14:06:36 2019 +0300 +++ b/src/parser.cpp Thu Oct 03 11:45:44 2019 +0300 @@ -41,7 +41,7 @@ return QString::fromUtf8(this->device.readLine()).trimmed(); } -const QMap<QString, decltype(LDHeader::type)> Parser::typeStrings { +static const QMap<QString, decltype(LDHeader::type)> typeStrings { {"Part", LDHeader::Part}, {"Subpart", LDHeader::Subpart}, {"Shortcut", LDHeader::Shortcut}, @@ -76,7 +76,6 @@ QStringList tokens = line .mid(strlen("0 !LDRAW_ORG ")) .split(" ", QString::SkipEmptyParts); - if (not tokens.isEmpty()) { QString partTypeString = tokens[0]; @@ -85,7 +84,7 @@ // consideration. if (partTypeString.startsWith("Unofficial_")) partTypeString = partTypeString.mid(strlen("Unofficial_")); - header.type = Parser::typeStrings.value(partTypeString, LDHeader::Part); + header.type = typeStrings.value(partTypeString, LDHeader::Part); header.qualfiers = 0; if (tokens.contains("Alias")) header.qualfiers |= LDHeader::Alias; @@ -200,7 +199,6 @@ LDHeader Parser::parseHeader(Winding& winding) { LDHeader header = {}; - if (not this->device.atEnd()) { // Parse the description @@ -208,13 +206,11 @@ if (descriptionLine.startsWith("0 ")) { header.description = descriptionLine.mid(strlen("0 ")).trimmed(); - // Parse the rest of the header while (not this->device.atEnd()) { const QString& line = this->readLine(); auto result = parseHeaderLine(header, winding, line); - if (result == ParseFailure) { // Failed to parse this header line, add it as a comment into the body later. @@ -233,7 +229,6 @@ this->bag.append(descriptionLine); } } - return header; } @@ -308,9 +303,49 @@ } } +static Vertex vertexFromString(const QString& vertex_string) +{ + static const QRegExp pattern {R"(^\s*([^\s]+)\s+([^\s]+)\s+([^\s]+)\s*$)"}; + const bool succeeded = pattern.exactMatch(vertex_string); + if (succeeded) + { + const float x = pattern.cap(1).toFloat(nullptr); + const float y = pattern.cap(2).toFloat(nullptr); + const float z = pattern.cap(3).toFloat(nullptr); + return {x, y, z}; + } + else + { + return {}; + } +} + +static modelobjects::Edge* parseEdgeline( + Model::EditContext& editor, + const QString& line) +{ + const bool succeeded = regexes::edgeline.exactMatch(line); + if (succeeded) + { + const Color colour = {regexes::edgeline.cap(1).toInt(nullptr)}; + const Vertex v_1 = vertexFromString(regexes::edgeline.cap(2)); + const Vertex v_2 = vertexFromString(regexes::edgeline.cap(3)); + return editor.append<modelobjects::Edge>(v_1, v_2, colour); + } + else + { + return nullptr; + } +} + modelobjects::BaseObject* Parser::parseFromString( Model::EditContext& editor, const QString& line) { - return editor.append<modelobjects::Comment>(line); + modelobjects::Edge* edge = parseEdgeline(editor, line); + if (edge) + { + return edge; + } + return editor.append<modelobjects::ErrorLine>(line); }
--- a/src/parser.h Mon Sep 23 14:06:36 2019 +0300 +++ b/src/parser.h Thu Oct 03 11:45:44 2019 +0300 @@ -33,7 +33,6 @@ void parseBody(Model::EditContext& editor); static modelobjects::BaseObject* parseFromString(Model::EditContext& editor, const QString& line); - static const QMap<QString, decltype(LDHeader::type)> typeStrings; private: enum HeaderParseResult {ParseSuccess, ParseFailure, StopParsing}; QString readLine();
--- a/src/vertex.cpp Mon Sep 23 14:06:36 2019 +0300 +++ b/src/vertex.cpp Thu Oct 03 11:45:44 2019 +0300 @@ -31,7 +31,7 @@ } */ -double& Vertex::operator[](Axis axis) +Vertex::ValueType& Vertex::operator[](Axis axis) { switch (axis) { @@ -46,7 +46,7 @@ } } -double Vertex::operator[](Axis axis) const +Vertex::ValueType Vertex::operator[](Axis axis) const { switch (axis) { @@ -57,11 +57,11 @@ case Z: return this->z; default: - return 0.0; + return 0; } } -void Vertex::setCoordinate(Axis axis, qreal value) +void Vertex::setCoordinate(Axis axis, ValueType value) { (*this)[axis] = value; } @@ -71,7 +71,7 @@ return {vector.x(), vector.y(), vector.z()}; } -Vertex Vertex::operator*(qreal scalar) const +Vertex Vertex::operator*(ValueType scalar) const { return {this->x * scalar, this->y * scalar, this->z * scalar}; } @@ -125,7 +125,7 @@ }; } -Vertex& Vertex::operator*=(qreal scalar) +Vertex& Vertex::operator*=(ValueType scalar) { x *= scalar; y *= scalar;
--- a/src/vertex.h Mon Sep 23 14:06:36 2019 +0300 +++ b/src/vertex.h Thu Oct 03 11:45:44 2019 +0300 @@ -23,22 +23,23 @@ struct Vertex { - qreal x; - qreal y; - qreal z; + using ValueType = float; + ValueType x; + ValueType y; + ValueType z; // void transform(const class Matrix& matrix, const Vertex& pos); Vertex transformed(const GLRotationMatrix& matrix) const; - void setCoordinate(Axis ax, qreal value); + void setCoordinate(Axis ax, ValueType value); Vertex& operator+=(const QVector3D& other); Vertex operator+(const QVector3D& other) const; QVector3D operator-(const Vertex& other) const; Vertex operator-(const QVector3D& vector) const; Vertex& operator-=(const QVector3D& vector); - Vertex& operator*=(qreal scalar); - Vertex operator*(qreal scalar) const; + Vertex& operator*=(ValueType scalar); + Vertex operator*(ValueType scalar) const; bool operator<(const Vertex& other) const; - double& operator[](Axis ax); - double operator[](Axis ax) const; + ValueType& operator[](Axis ax); + ValueType operator[](Axis ax) const; bool operator==(const Vertex& other) const; bool operator!=(const Vertex& other) const; operator QVariant() const;