Thu, 03 Oct 2019 23:44:28 +0300
language support
--- a/CMakeLists.txt Thu Oct 03 11:45:44 2019 +0300 +++ b/CMakeLists.txt Thu Oct 03 23:44:28 2019 +0300 @@ -3,12 +3,13 @@ #set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMake") #include(cotire) find_package(Qt5Widgets REQUIRED) +if (Qt5Widgets_VERSION VERSION_LESS 5.5.0) + message(FATAL_ERROR "Qt5 version 5.5 required") +endif() find_package(Qt5Core REQUIRED) find_package(Qt5OpenGL REQUIRED) find_package(Qt5Network REQUIRED) -if (Qt5Widgets_VERSION VERSION_LESS 5.5.0) - message(FATAL_ERROR "Qt5 version 5.5 required") -endif() +find_package(Qt5LinguistTools REQUIRED) set (CMAKE_AUTOMOC ON) find_package (OpenGL REQUIRED) add_custom_target (revision_check ALL @@ -23,8 +24,7 @@ src/mainwindow.cpp src/model.cpp src/modeleditcontext.cpp - src/parser.cpp - src/uuid.cpp + src/parser.cpp src/version.cpp src/vertex.cpp src/objecttypes/comment.cpp @@ -43,8 +43,7 @@ src/mainwindow.h src/model.h src/modeleditcontext.h - src/parser.h - src/uuid.h + src/parser.h src/version.h src/vertex.h src/objecttypes/comment.h @@ -62,6 +61,19 @@ # src/configurationoptions.txt # data/primitive-categories.cfg # ) + +set(LDFORGE_LOCALES + locale/fi.ts + locale/sv.ts + locale/ru.ts +) + +# Qt5LinguistTools +qt5_create_translation(QM_FILES ${LDFORGE_SOURCES} ${LDFORGE_HEADERS} ${LDFORGE_FORMS} ${LDFORGE_LOCALES}) +add_custom_target(translations ALL DEPENDS ${QM_FILES}) +add_custom_target(resources ALL DEPENDS ${RESOURCE_FILES}) +add_dependencies(resources translations) + set (LDFORGE_RESOURCES ldforge.qrc) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -79,16 +91,28 @@ endif() # qt5_add_resources (LDFORGE_QRC ${LDFORGE_RESOURCES}) qt5_wrap_ui (LDFORGE_FORMS_HEADERS ${LDFORGE_FORMS}) + +# Move languages.qrc into the build directory to bake the .qm-files into LDForge +# so that they don't have to be shipped separately +# https://stackoverflow.com/a/34798124 +set(LANGUAGES_QRC "languages.qrc") +configure_file(${LANGUAGES_QRC} ${LANGUAGES_QRC} COPYONLY) +qt5_add_resources(LDFORGE_QM_RC_FILE ${CMAKE_CURRENT_BINARY_DIR}/${LANGUAGES_QRC}) + add_executable (ldforge WIN32 ${LDFORGE_SOURCES} ${LDFORGE_HEADERS} # ${LDFORGE_OTHER_FILES} -# ${LDFORGE_QRC} + ${LDFORGE_RESOURCES} + ${LDFORGE_QRC} + ${LDFORGE_QM_RC_FILE} ${LDFORGE_FORMS_HEADERS} # ${CMAKE_BINARY_DIR}/configuration.cpp ) + set_source_files_properties(${LDFORGE_HEADERS} PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties(${LDFORGE_OTHER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) +set_source_files_properties(${LDFORGE_RESOURCES} PROPERTIES HEADER_FILE_ONLY TRUE) set_target_properties(ldforge PROPERTIES AUTOMOC 1) target_link_libraries(ldforge Qt5::Widgets Qt5::Network Qt5::OpenGL ${OPENGL_LIBRARIES}) # cotire(ldforge)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flags/en.svg Thu Oct 03 23:44:28 2019 +0300 @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1280" height="640" viewBox="0 0 10080 5040"> +<defs> +<clipPath id="c"> +<path d="M0,0V1.5H7V3H6zM6,0H3V3.5H0V3z"/> +</clipPath> +<path id="Star7" d="M0,-360 69.421398,-144.155019 281.459334,-224.456329 155.988466,-35.603349 350.974048,80.107536 125.093037,99.758368 156.198146,324.348792 0,160 -156.198146,324.348792 -125.093037,99.758368 -350.974048,80.107536 -155.988466,-35.603349 -281.459334,-224.456329 -69.421398,-144.155019z"/> +<path id="Star5" d="M0,-210 54.859957,-75.508253 199.721868,-64.893569 88.765275,28.841586 123.434903,169.893569 0,93.333333 -123.434903,169.893569 -88.765275,28.841586 -199.721868,-64.893569 -54.859957,-75.508253z"/> +<use id="Cstar" xlink:href="#Star7" transform="scale(2.1)"/> +</defs> +<g transform="scale(840)"> +<rect width="12" height="6" fill="#00008b"/> +<path d="M0,0 6,3M6,0 0,3" stroke="#fff" stroke-width="0.6"/> +<path d="M0,0 6,3M6,0 0,3" stroke="#f00" stroke-width="0.4" clip-path="url(#c)"/> +<path d="M3,0V3.5M0,1.5H7" stroke="#fff"/> +<path d="M3,0V3.5M0,1.5H7" stroke="#f00" stroke-width="0.6"/> +<path d="M0,3H6V0H8V4H0z" fill="#00008b"/> +</g> +<g fill="#fff"> +<use id="Comwlth" xlink:href="#Cstar" x="2520" y="3780"/> +<use id="αCrucis" xlink:href="#Star7" x="7560" y="4200"/> +<use id="βCrucis" xlink:href="#Star7" x="6300" y="2205"/> +<use id="γCrucis" xlink:href="#Star7" x="7560" y="840"/> +<use id="δCrucis" xlink:href="#Star7" x="8680" y="1869"/> +<use id="εCrucis" xlink:href="#Star5" x="8064" y="2730"/> +</g> +</svg> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flags/fi.svg Thu Oct 03 23:44:28 2019 +0300 @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" width="1800" height="1100"> +<rect width="1800" height="1100" fill="#fff"/> +<rect width="1800" height="300" y="400" fill="#003580"/> +<rect width="300" height="1100" x="500" fill="#003580"/> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flags/make_flags.sh Thu Oct 03 23:44:28 2019 +0300 @@ -0,0 +1,7 @@ +#!/bin/bash +for flag in *.svg +do + flag_png="${flag%.svg}.png" + echo "$flag => $flag_png" + inkscape -z -e ${flag_png} -w 64 $flag +done
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flags/ru.svg Thu Oct 03 23:44:28 2019 +0300 @@ -0,0 +1,1 @@ +<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 9 6" width="900" height="600"><rect fill="#fff" width="9" height="3"/><rect fill="#d52b1e" y="3" width="9" height="3"/><rect fill="#0039a6" y="2" width="9" height="2"/></svg> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/flags/sv.svg Thu Oct 03 23:44:28 2019 +0300 @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="1600" height="1000" viewBox="0 0 16 10"> +<rect width="16" height="10" fill="#006aa7"/> +<rect width="2" height="10" x="5" fill="#fecc00"/> +<rect width="16" height="2" y="4" fill="#fecc00"/> +</svg>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/languages.qrc Thu Oct 03 23:44:28 2019 +0300 @@ -0,0 +1,7 @@ +<RCC> + <qresource prefix="/locale"> + <file>fi.qm</file> + <file>ru.qm</file> + <file>sv.qm</file> + </qresource> +</RCC>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ldforge.qrc Thu Oct 03 23:44:28 2019 +0300 @@ -0,0 +1,8 @@ +<RCC> + <qresource prefix="/"> + <file>flags/en.png</file> + <file>flags/fi.png</file> + <file>flags/ru.png</file> + <file>flags/sv.png</file> + </qresource> +</RCC>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/locale/fi.ts Thu Oct 03 23:44:28 2019 +0300 @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="fi"> +<context> + <name>MainWindow</name> + <message> + <source>MainWindow</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>File</source> + <translation>Tiedosto</translation> + </message> + <message> + <source>Quit</source> + <translation>Poistu</translation> + </message> + <message> + <source>Open…</source> + <translation>Avaa...</translation> + </message> + <message> + <source>Ctrl+O</source> + <translation>Ctrl+O</translation> + </message> + <message> + <source>New</source> + <translation>Uusi</translation> + </message> + <message> + <source>Ctrl+N</source> + <translation>Ctrl+N</translation> + </message> + <message> + <source>Language</source> + <translation>Kieli</translation> + </message> + <message> + <source>Open model</source> + <translation type="unfinished">Avaa malli</translation> + </message> + <message> + <source>LDraw models (*.ldr *.dat)</source> + <translation>LDraw-mallit (*.ldr *.dat)</translation> + </message> + <message> + <source>Problem opening file</source> + <translation>Ongelma tiedoston avaamisessa</translation> + </message> + <message> + <source>Could not open %1: %2</source> + <translation>Ei voitu avata %1: %2</translation> + </message> +</context> +</TS>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/locale/ru.ts Thu Oct 03 23:44:28 2019 +0300 @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="ru"> +<context> + <name>MainWindow</name> + <message> + <source>MainWindow</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>File</source> + <translation>Файл</translation> + </message> + <message> + <source>Quit</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Open…</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+O</source> + <translation>Ctrl+O</translation> + </message> + <message> + <source>New</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>Ctrl+N</source> + <translation>Ctrl+N</translation> + </message> + <message> + <source>Language</source> + <translation>Язык</translation> + </message> + <message> + <source>Open model</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>LDraw models (*.ldr *.dat)</source> + <translation></translation> + </message> + <message> + <source>Problem opening file</source> + <translation></translation> + </message> + <message> + <source>Could not open %1: %2</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/locale/sv.ts Thu Oct 03 23:44:28 2019 +0300 @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="sv"> +<context> + <name>MainWindow</name> + <message> + <source>MainWindow</source> + <translation type="unfinished"></translation> + </message> + <message> + <source>File</source> + <translation>Arkiv</translation> + </message> + <message> + <source>Quit</source> + <translation>Avsluta</translation> + </message> + <message> + <source>Open…</source> + <translation>Öppna...</translation> + </message> + <message> + <source>Ctrl+O</source> + <translation>Ctrl+O</translation> + </message> + <message> + <source>New</source> + <translation>Ny</translation> + </message> + <message> + <source>Ctrl+N</source> + <translation>Ctrl+N</translation> + </message> + <message> + <source>Language</source> + <translation>Språk</translation> + </message> + <message> + <source>Open model</source> + <translation>Öppna modell</translation> + </message> + <message> + <source>LDraw models (*.ldr *.dat)</source> + <translation>LDrawmodeller (*.ldr *.dat)</translation> + </message> + <message> + <source>Problem opening file</source> + <translation>Problem att öppna filen</translation> + </message> + <message> + <source>Could not open %1: %2</source> + <translation>Kunde inte öppna %1: %2</translation> + </message> +</context> +</TS>
--- a/src/basics.h Thu Oct 03 11:45:44 2019 +0300 +++ b/src/basics.h Thu Oct 03 23:44:28 2019 +0300 @@ -86,3 +86,15 @@ { return (x << 20) | ((x >> 12) & 0x000000ff); } + +template<typename T, typename... Rest> +QString format(const QString &format_string, T&& arg, Rest&&... rest) +{ + return format(format_string.arg(arg), std::forward<Rest>(rest)...); +} + +template<typename T> +QString format(const QString &format_string, T&& arg) +{ + return format_string.arg(arg); +}
--- a/src/main.cpp Thu Oct 03 11:45:44 2019 +0300 +++ b/src/main.cpp Thu Oct 03 23:44:28 2019 +0300 @@ -1,4 +1,5 @@ #include <QApplication> +#include <QDir> #include "main.h" #include "mainwindow.h"
--- a/src/mainwindow.cpp Thu Oct 03 11:45:44 2019 +0300 +++ b/src/mainwindow.cpp Thu Oct 03 23:44:28 2019 +0300 @@ -9,10 +9,13 @@ ui{std::make_unique<Ui_MainWindow>()}, documents{this} { - ui->setupUi(this); + this->ui->setupUi(this); connect(ui->actionNew, &QAction::triggered, this, &MainWindow::newModel); + connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::openModel); connect(ui->actionQuit, &QAction::triggered, this, &QMainWindow::close); - updateTitle(); + this->updateTitle(); + this->loadLocales(); + changeLanguage(QLocale::system().name()); } MainWindow::~MainWindow() @@ -30,7 +33,7 @@ void MainWindow::openModel() { const QString path = QFileDialog::getOpenFileName( - this, "Open model", "", "LDraw models (*.ldr *.dat)"); + this, tr("Open model"), "", tr("LDraw models (*.ldr *.dat)")); if (not path.isEmpty()) { QFile file{path}; @@ -41,8 +44,8 @@ } else { - QMessageBox::critical(this, "Problem opening file", - QString{"Could not open %1: %2"} + QMessageBox::critical(this, tr("Problem opening file"), + tr("Could not open %1: %2") .arg(path) .arg(file.errorString())); } @@ -50,6 +53,51 @@ } /** + * @brief Changes the application language to the specified language + * @param localeCode Code of the locale to translate to + */ +void MainWindow::changeLanguage(const QString& localeCode) +{ + if (not localeCode.isEmpty() and localeCode != this->currentLanguage) + { + this->currentLanguage = localeCode; + QLocale::setDefault({localeCode}); + qApp->removeTranslator(&this->translator); + const bool loadSuccessful = this->translator.load(pathToTranslation(localeCode)); + if (loadSuccessful) + { + qApp->installTranslator(&this->translator); + } + } +} + +void MainWindow::languageChangeRequested() +{ + QAction* const senderAction = qobject_cast<QAction*>(sender()); + if (senderAction != nullptr) + { + const QString localeCode = senderAction->data().toString(); + this->changeLanguage(localeCode); + } +} + +void MainWindow::changeEvent(QEvent* event) +{ + if (event != nullptr) + { + switch (event->type()) + { + case QEvent::LanguageChange: + this->ui->retranslateUi(this); + break; + default: + break; + } + } + QMainWindow::changeEvent(event); +} + +/** * @brief Creates a new tab widget for the specified model. * @param model Model to get a new tab widget for * @return widget @@ -105,3 +153,31 @@ title += fullVersionString(); setWindowTitle(title); } + +QString MainWindow::pathToTranslation(const QString& localeCode) +{ + QDir dir {":/locale"}; + return dir.filePath(localeCode + ".qm"); +} + +void MainWindow::loadLocales() +{ + QDir dir {":/locale"}; + this->ui->menuLanguage->clear(); + QVector<QString> localeCodes = {"en"}; + for (const QFileInfo& file : dir.entryInfoList(QDir::Files)) + { + localeCodes.append(file.baseName()); + } + for (const QString& localeCode : localeCodes) + { + const QLocale locale{localeCode}; + const QString languageName = QLocale::languageToString(locale.language()); + const QIcon flag{":/flags/" + localeCode + ".png"}; + QAction* action = new QAction{languageName, this}; + action->setData(localeCode); + action->setIcon(flag); + this->ui->menuLanguage->addAction(action); + connect(action, &QAction::triggered, this, &MainWindow::languageChangeRequested); + } +}
--- a/src/mainwindow.h Thu Oct 03 11:45:44 2019 +0300 +++ b/src/mainwindow.h Thu Oct 03 23:44:28 2019 +0300 @@ -1,5 +1,6 @@ #pragma once #include <QMainWindow> +#include <QTranslator> #include <memory> #include <vector> #include "documentmanager.h" @@ -13,12 +14,20 @@ private slots: void newModel(); void openModel(); + void languageChangeRequested(); +protected: + void changeEvent(QEvent* event); private: std::unique_ptr<class Ui_MainWindow> ui; DocumentManager documents; QMap<Model*, QWidget*> modelWidgets; QWidget* createWidgetForModel(Model* model); QWidget* getWidgetForModel(Model* model); + void loadLocales(); void updateTabs(); void updateTitle(); + void changeLanguage(const QString& localeCode); + static QString pathToTranslation(const QString& localeCode); + QString currentLanguage = "en"; + QTranslator translator; };
--- a/src/mainwindow.ui Thu Oct 03 11:45:44 2019 +0300 +++ b/src/mainwindow.ui Thu Oct 03 23:44:28 2019 +0300 @@ -38,7 +38,13 @@ <addaction name="separator"/> <addaction name="actionQuit"/> </widget> + <widget class="QMenu" name="menuLanguage"> + <property name="title"> + <string>Language</string> + </property> + </widget> <addaction name="menuFile"/> + <addaction name="menuLanguage"/> </widget> <widget class="QStatusBar" name="statusbar"/> <action name="actionQuit">
--- a/src/model.h Thu Oct 03 11:45:44 2019 +0300 +++ b/src/model.h Thu Oct 03 23:44:28 2019 +0300 @@ -13,6 +13,8 @@ Model(const Model&) = delete; int size() const; EditContext edit(); +signals: + void objectAdded(modelobjects::Id id, int position); private: template<typename T, typename... Args> T* append(Args&&... args); @@ -23,18 +25,25 @@ using ModelObjectPointer = std::unique_ptr<modelobjects::BaseObject>; LDHeader header; std::vector<ModelObjectPointer> body; + std::map<modelobjects::Id, modelobjects::BaseObject*> objectsById; }; template<typename T, typename... Args> T* Model::append(Args&&... args) { this->body.push_back(std::make_unique<T>(args...)); - return static_cast<T*>(this->body.back().get()); + T* pointer = static_cast<T*>(this->body.back().get()); + this->objectsById[pointer->id] = pointer; + emit objectAdded(pointer->id, this->body.size() - 1); + return pointer; } template<typename T, typename... Args> T* Model::insert(int position, Args&&... args) { this->body.insert(position, std::make_unique<T>(args...)); - return this->body[position]; + T* pointer = static_cast<T*>(this->body[position]); + this->objectsById[pointer->id] = pointer; + emit objectAdded(pointer->id, position); + return pointer; }
--- a/src/objecttypes/comment.cpp Thu Oct 03 11:45:44 2019 +0300 +++ b/src/objecttypes/comment.cpp Thu Oct 03 23:44:28 2019 +0300 @@ -1,3 +1,4 @@ +#include <QFont> #include "comment.h" modelobjects::Comment::Comment(QStringView text) : @@ -27,3 +28,15 @@ return BaseObject::setProperty(property, value); } } + +QString modelobjects::Comment::textRepresentation() const +{ + return this->storedText; +} + +QFont modelobjects::Comment::textRepresentationFont() const +{ + QFont font; + font.setItalic(true); + return font; +}
--- a/src/objecttypes/comment.h Thu Oct 03 11:45:44 2019 +0300 +++ b/src/objecttypes/comment.h Thu Oct 03 23:44:28 2019 +0300 @@ -15,6 +15,8 @@ SetPropertyResult setProperty( Property property, const QVariant& value) override; + QString textRepresentation() const override; + QFont textRepresentationFont() const override; private: QString storedText = ""; };
--- a/src/objecttypes/conditionaledge.cpp Thu Oct 03 11:45:44 2019 +0300 +++ b/src/objecttypes/conditionaledge.cpp Thu Oct 03 23:44:28 2019 +0300 @@ -40,3 +40,10 @@ return Edge::setProperty(property, value); } } + +QString modelobjects::ConditionalEdge::textRepresentation() const +{ + return Edge::textRepresentation() + format("%1 %2", + vertexToStringParens(controlPoint_1), + vertexToStringParens(controlPoint_2)); +}
--- a/src/objecttypes/conditionaledge.h Thu Oct 03 11:45:44 2019 +0300 +++ b/src/objecttypes/conditionaledge.h Thu Oct 03 23:44:28 2019 +0300 @@ -20,6 +20,7 @@ SetPropertyResult setProperty( Property property, const QVariant& value) override; + QString textRepresentation() const override; private: Vertex controlPoint_1 = {}; Vertex controlPoint_2 = {};
--- a/src/objecttypes/edge.cpp Thu Oct 03 11:45:44 2019 +0300 +++ b/src/objecttypes/edge.cpp Thu Oct 03 23:44:28 2019 +0300 @@ -36,3 +36,8 @@ return BaseClass::setProperty(property, value); } } + +QString modelobjects::Edge::textRepresentation() const +{ + return format("%1 %2", vertexToStringParens(point_1), vertexToStringParens(point_2)); +}
--- a/src/objecttypes/edge.h Thu Oct 03 11:45:44 2019 +0300 +++ b/src/objecttypes/edge.h Thu Oct 03 23:44:28 2019 +0300 @@ -17,6 +17,7 @@ SetPropertyResult setProperty( Property property, const QVariant& value) override; + QString textRepresentation() const override; private: Vertex point_1 = {}; Vertex point_2 = {};
--- a/src/objecttypes/errorline.cpp Thu Oct 03 11:45:44 2019 +0300 +++ b/src/objecttypes/errorline.cpp Thu Oct 03 23:44:28 2019 +0300 @@ -1,3 +1,4 @@ +#include <QBrush> #include "errorline.h" modelobjects::ErrorLine::ErrorLine(QStringView text) : @@ -30,3 +31,18 @@ return BaseObject::setProperty(property, value); } } + +QString modelobjects::ErrorLine::textRepresentation() const +{ + return this->text; +} + +QBrush modelobjects::ErrorLine::textRepresentationForeground() const +{ + return QBrush{Qt::yellow}; +} + +QBrush modelobjects::ErrorLine::textRepresentationBackground() const +{ + return QBrush{Qt::red}; +}
--- a/src/objecttypes/errorline.h Thu Oct 03 11:45:44 2019 +0300 +++ b/src/objecttypes/errorline.h Thu Oct 03 23:44:28 2019 +0300 @@ -14,6 +14,9 @@ SetPropertyResult setProperty( Property property, const QVariant& value) override; + QString textRepresentation() const override; + QBrush textRepresentationForeground() const override; + QBrush textRepresentationBackground() const override; private: QString text; };
--- a/src/objecttypes/modelobject.cpp Thu Oct 03 11:45:44 2019 +0300 +++ b/src/objecttypes/modelobject.cpp Thu Oct 03 23:44:28 2019 +0300 @@ -1,14 +1,25 @@ +#include <QBrush> +#include <QFont> #include "modelobject.h" +/* static Uuid &getUuidForNewObject() { static Uuid running_uuid {0, 0}; incrementUuid(running_uuid); return running_uuid; } +*/ + +static unsigned int getIdForNewObject() +{ + static unsigned int id = 0; + id += 1; + return id; +} modelobjects::BaseObject::BaseObject() : - id {getUuidForNewObject()} + id {getIdForNewObject()} { } @@ -35,6 +46,21 @@ return SetPropertyResult::PropertyNotHandled; } +QBrush modelobjects::BaseObject::textRepresentationForeground() const +{ + return {}; +} + +QBrush modelobjects::BaseObject::textRepresentationBackground() const +{ + return {}; +} + +QFont modelobjects::BaseObject::textRepresentationFont() const +{ + return {}; +} + modelobjects::ColoredBaseObject::ColoredBaseObject(const Color color_index) : color_index{color_index} {
--- a/src/objecttypes/modelobject.h Thu Oct 03 11:45:44 2019 +0300 +++ b/src/objecttypes/modelobject.h Thu Oct 03 23:44:28 2019 +0300 @@ -4,7 +4,6 @@ #include <QStringView> #include "main.h" #include "colors.h" -#include "uuid.h" #include "vertex.h" namespace modelobjects @@ -42,11 +41,15 @@ BaseObject(); BaseObject(const BaseObject&) = delete; virtual ~BaseObject(); - const Uuid id; + const unsigned int id; //virtual void toString(QTextStream &out) = 0; virtual bool hasColor() const; virtual QVariant getProperty(Property id) const; virtual SetPropertyResult setProperty(Property id, const QVariant& value); + virtual QString textRepresentation() const = 0; + virtual QBrush textRepresentationForeground() const; + virtual QBrush textRepresentationBackground() const; + virtual QFont textRepresentationFont() const; }; class modelobjects::ColoredBaseObject : public BaseObject @@ -59,3 +62,8 @@ private: Color color_index = colors::main; }; + +namespace modelobjects +{ + using Id = std::remove_const_t<decltype(BaseObject::id)>; +}
--- a/src/objecttypes/polygon.cpp Thu Oct 03 11:45:44 2019 +0300 +++ b/src/objecttypes/polygon.cpp Thu Oct 03 23:44:28 2019 +0300 @@ -44,6 +44,14 @@ } } +QString modelobjects::Triangle::textRepresentation() const +{ + return format("%1 %2 %3", + vertexToStringParens(points[0]), + vertexToStringParens(points[1]), + vertexToStringParens(points[2])); +} + modelobjects::Quadrilateral::Quadrilateral( const Vertex& point_1, const Vertex& point_2, @@ -95,3 +103,12 @@ return ColoredBaseObject::setProperty(id, value); } } + +QString modelobjects::Quadrilateral::textRepresentation() const +{ + return format("%1 %2 %3 %4", + vertexToStringParens(points[0]), + vertexToStringParens(points[1]), + vertexToStringParens(points[2]), + vertexToStringParens(points[3])); +}
--- a/src/objecttypes/polygon.h Thu Oct 03 11:45:44 2019 +0300 +++ b/src/objecttypes/polygon.h Thu Oct 03 23:44:28 2019 +0300 @@ -18,6 +18,7 @@ Color color_index = colors::main); QVariant getProperty(Property id) const override; SetPropertyResult setProperty(Property id, const QVariant& value) override; + QString textRepresentation() const override; private: Vertex points[3] = {{}}; }; @@ -34,6 +35,7 @@ Color color_index = colors::main); QVariant getProperty(Property id) const override; SetPropertyResult setProperty(Property id, const QVariant& value) override; + QString textRepresentation() const override; private: Vertex points[4] = {{}}; };
--- a/src/objecttypes/subfilereference.cpp Thu Oct 03 11:45:44 2019 +0300 +++ b/src/objecttypes/subfilereference.cpp Thu Oct 03 23:44:28 2019 +0300 @@ -14,3 +14,8 @@ return ColoredBaseObject::getProperty(property); } } + +QString modelobjects::SubfileReference::textRepresentation() const +{ + return referenceName + " " + vertexToStringParens(this->position); +}
--- a/src/objecttypes/subfilereference.h Thu Oct 03 11:45:44 2019 +0300 +++ b/src/objecttypes/subfilereference.h Thu Oct 03 23:44:28 2019 +0300 @@ -11,6 +11,7 @@ public: SubfileReference() = default; QVariant getProperty(Property property) const override; + QString textRepresentation() const override; private: Vertex position; QMatrix3x3 transformation;
--- a/src/uuid.cpp Thu Oct 03 11:45:44 2019 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -#include "uuid.h" -#include <QIODevice> - -void uuidToString(const Uuid &uuid, QTextStream &stream) -{ - stream << "0x"; - stream << QString::number(uuid.a, 16); - stream << QString::number(uuid.b, 16); -} - -void incrementUuid(Uuid &uuid) -{ - if (uuid.b == std::numeric_limits<decltype(uuid.b)>::max()) - { - uuid.a += 1; - uuid.b = 0; - } - else - { - uuid.b += 1; - } -}
--- a/src/uuid.h Thu Oct 03 11:45:44 2019 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -#pragma once -#include <QString> -#include <QTextStream> - -struct Uuid -{ - quint64 a; - quint64 b; -}; - -void incrementUuid(Uuid &uuid); -void uuidToString(const Uuid &uuid, QTextStream &stream);
--- a/src/vertex.cpp Thu Oct 03 11:45:44 2019 +0300 +++ b/src/vertex.cpp Thu Oct 03 23:44:28 2019 +0300 @@ -213,3 +213,8 @@ { return qHash(key.x) ^ rotl10(qHash(key.y)) ^ rotl20(qHash(key.z)); } + +QString vertexToStringParens(const Vertex& vertex) +{ + return format("(%1, %2, %3)", vertex.x, vertex.y, vertex.z); +}
--- a/src/vertex.h Thu Oct 03 11:45:44 2019 +0300 +++ b/src/vertex.h Thu Oct 03 23:44:28 2019 +0300 @@ -54,6 +54,7 @@ qreal distance(const Vertex& one, const Vertex& other); Vertex vertexFromVector(const QVector3D& vector); QVector3D vertexToVector(const Vertex &vertex); +QString vertexToStringParens(const Vertex& vertex); unsigned int qHash(const Vertex& key); Vertex operator-(const Vertex& vertex); QDataStream& operator<<(QDataStream& out, const Vertex& vertex);