# HG changeset patch # User Teemu Piippo # Date 1654710081 -10800 # Node ID 1a4342d80de7d6fd36ed7667f38e90b8b7d47500 # Parent 52e10e8d88cc391e9dd3fd4ab9ef0433e58bcd73 Refactor colors.cpp/.h diff -r 52e10e8d88cc -r 1a4342d80de7 src/colors.cpp --- a/src/colors.cpp Wed Jun 08 19:33:00 2022 +0300 +++ b/src/colors.cpp Wed Jun 08 20:41:21 2022 +0300 @@ -1,115 +1,72 @@ -/* - * LDForge: LDraw parts authoring CAD - * Copyright (C) 2013 - 2020 Teemu Piippo - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - #include "colors.h" -const ldraw::ColorDefinition ldraw::ColorTable::unknownColor{{}, {}, "Unknown", "???"}; +const ColorDefinition unknownColor{{}, {}, "Unknown", "???"}; -/** - * @brief Clears the color table - */ -void ldraw::ColorTable::clear() -{ - this->definitions = {}; -} - -/** - * @brief Loads colors from LDConfig.ldr - * @param device Opened LDConfig.ldr I/O device - * @param errors Where to write any errors into - * @returns whether or not it succeeded. - */ -Result ldraw::ColorTable::load(QIODevice& device, QTextStream& errors) +template +static QString replaced(QString text, Args&&... args) { - this->clear(); - if (device.isReadable()) - { - QTextStream stream{&device}; - QString line; - while (stream.readLineInto(&line)) - { - this->loadColorFromString(line); - } - return Success; - } - else - { - errors << "could not read colors"; - return Failure; - } -} - -/** - * @brief Gets color information by color index. - * @param color - * @returns color table information - */ -const ldraw::ColorDefinition& ldraw::ColorTable::operator[](Color color) const -{ - auto it = this->definitions.find(color.index); - if (it != this->definitions.end()) - { - return it->second; - } - else - { - return unknownColor; - } -} - -/** - * @brief Gets the amount of elements in the color table - * @returns int - */ -int ldraw::ColorTable::size() const -{ - return this->definitions.size(); + text.replace(args...); + return text; } /** * @brief Parses an LDConfig.ldr line from a string * @param string LDConfig.ldr line to parse */ -void ldraw::ColorTable::loadColorFromString(const QString& string) +static auto loadColorFromString(const QString& string) { - const QRegExp pattern{ - R"(^\s*0 \!COLOUR\s+([^\s]+)\s+)"_q + - R"(CODE\s+(\d+)\s+)"_q + - R"(VALUE\s+(\#[0-9a-fA-F]{3,6})\s+)"_q + - R"(EDGE\s+(\#[0-9a-fA-F]{3,6}))"_q + - R"((?:\s+ALPHA\s+(\d+))?)"_q - }; + std::optional> result; + static const QRegExp pattern{QStringLiteral( + R"(^\s*0 \!COLOUR\s+([^\s]+)\s+)" + R"(CODE\s+(\d+)\s+)" + R"(VALUE\s+(\#[0-9a-fA-F]{3,6})\s+)" + R"(EDGE\s+(\#[0-9a-fA-F]{3,6}))" + R"((?:\s+ALPHA\s+(\d+))?)" + )}; if (pattern.indexIn(string) != -1) { const int code = pattern.cap(2).toInt(); - ColorDefinition& definition = this->definitions[code]; - definition = {}; // in case there's an existing definition - definition.name = pattern.cap(1); - definition.displayName = definition.name; - definition.displayName.replace("_", " "); - definition.faceColor = pattern.cap(3); - definition.edgeColor = pattern.cap(4); + const QString name = pattern.cap(1); + ColorDefinition definition = { + .faceColor = pattern.cap(3), + .edgeColor = pattern.cap(4), + .name = name, + .displayName = replaced(name, "_", " "), + }; if (not pattern.cap(5).isEmpty()) { const int alpha = pattern.cap(5).toInt(); definition.faceColor.setAlpha(alpha); } + result = std::make_pair(ColorIndex{code}, definition); } + return result; +} + +/** + * @brief Loads colors from LDConfig.ldr + */ +std::optional loadColorTable(QIODevice &device, QTextStream &errors) +{ + std::optional result; + if (device.isReadable()) + { + result.emplace(); + QTextStream stream{&device}; + QString line; + while (stream.readLineInto(&line)) + { + const auto pair = loadColorFromString(line); + if (pair.has_value()) { + (*result)[pair->first] = pair->second; + } + } + } + else + { + errors << "could not read colors"; + } + return result; } /** @@ -118,109 +75,67 @@ * @param color * @returns luma value [0, 1] */ -double luma(const QColor& color) +qreal luma(const QColor& color) { - return 0.2126 * color.redF() + 0.7152 * color.greenF() + 0.0722 * color.blueF(); + return luma(color.redF(), color.greenF(), color.blueF()); } -/** - * @brief Returns a direct color index that codes the specified color value - * @param color - * @returns direct color index - */ -ldraw::Color ldraw::directColor(const QColor& color) +//! @brief Returns a direct color index that codes the specified color value +ColorIndex directColor(const QColor& color) { - return ldraw::Color{0x2000000 | (color.red() << 16) | (color.green() << 8) | color.blue()}; + return directColor(color.red(), color.green(), color.blue()); } -/** - * @brief Checks whether or not the specified color index is a direct color - * @param color Color to check - * @returns bool - */ -bool ldraw::isDirectColor(ldraw::Color color) +//! @brief Returns a face color for @param color, taking direct colors into account +std::optional colorFace(ColorIndex color, const ColorTable& colorTable) { - return color.index >= 0x2000000; + std::optional result; + if (isDirectColor(color)) { + const std::array rgb = directColorRgb(color); + result = QColor{rgb[0], rgb[1], rgb[2]}; + } + else { + const ColorDefinition* def = findInMap(colorTable, color); + if (def != nullptr) { + result = def->faceColor; + } + } + return result; } -/** - * @brief Extracts the color value from a direct color index - * @param color Direct color index - * @returns color value. Returns a default-constructed QColor in case a non-direct color is given. - */ -QColor ldraw::directColorFace(ldraw::Color color) +//! @brief Returns an edge color for @param color, taking direct colors into account +std::optional colorEdge(ColorIndex color, const ColorTable& colorTable) { - if (isDirectColor(color)) - { - return {(color.index >> 16) & 0xff, (color.index >> 8) & 0xff, color.index & 0xff}; + if (isDirectColor(color)) { + const std::array rgb = directColorRgb(color); + return (luma(rgb[0], rgb[1], rgb[2]) < 0.4) ? Qt::white : Qt::black; } - else - { - return {}; + else { + return colorFace(color, colorTable); } } -/** - * @brief Gets the face color for the specified color index - * @param color Color index to get face color for - * @param colorTable Color table to use for lookup - * @returns QColor - */ -QColor ldraw::colorFace(ldraw::Color color, const ldraw::ColorTable& colorTable) -{ - if (isDirectColor(color)) - { - return directColorFace(color); - } - else - { - return colorTable[color].faceColor; - } -} - -QColor ldraw::colorEdge(ldraw::Color color, const ldraw::ColorTable& colorTable) -{ - if (isDirectColor(color)) - { - QColor const faceColor = directColorFace(color); - return (luma(faceColor) < 0.4) ? Qt::white : Qt::black; - } - else - { - return colorTable[color].faceColor; - } -} - -/** - * @brief Writes a color index into a @c QDataStream - * @param stream - * @param color - * @returns stream - */ -QDataStream& operator<<(QDataStream& stream, ldraw::Color color) +QDataStream& operator<<(QDataStream& stream, ColorIndex color) { return stream << color.index; } -/** - * @brief Reads a color index from a @c QDataStream - * @param stream - * @param color - * @returns stream - */ -QDataStream& operator>>(QDataStream& stream, ldraw::Color& color) +QDataStream& operator>>(QDataStream& stream, ColorIndex& color) { return stream >> color.index; } -QString ldraw::colorDisplayName(ldraw::Color color, const ldraw::ColorTable &colorTable) +std::optional colorDisplayName(ColorIndex color, const ColorTable &colorTable) { - if (isDirectColor(color)) - { - return directColorFace(color).name(); + std::optional result; + if (isDirectColor(color)) { + result = colorFace(color, colorTable).value_or(QColor{}).name(); } - else - { - return colorTable[color].displayName; + else { + const ColorDefinition* def = findInMap(colorTable, color); + if (def != nullptr) { + result = def->displayName; + } } + return result; } diff -r 52e10e8d88cc -r 1a4342d80de7 src/colors.h --- a/src/colors.h Wed Jun 08 19:33:00 2022 +0300 +++ b/src/colors.h Wed Jun 08 20:41:21 2022 +0300 @@ -20,19 +20,6 @@ #include #include "main.h" -namespace ldraw -{ - struct Color; - struct ColorDefinition; - class ColorTable; - Color directColor(const QColor& color); - bool isDirectColor(Color color); - QColor directColorFace(Color color); - QColor colorFace(Color color, const ColorTable& colorTable); - QColor colorEdge(Color color, const ColorTable& colorTable); - QString colorDisplayName(Color color, const ColorTable& colorTable); -} - /** * @brief Represents an LDraw color index (e.g 16, 24, ...) * @@ -52,64 +39,77 @@ * LDConfig.ldr). Since this structure only contains an integer, it should be * passed by value to functions instead of l-value reference. */ -struct ldraw::Color +struct ColorIndex { qint32 index = 0; - constexpr auto operator<=>(const Color&) const = default; + constexpr auto operator<=>(const ColorIndex&) const = default; }; -Q_DECLARE_METATYPE(ldraw::Color) -QDataStream& operator<<(QDataStream&, ldraw::Color); -QDataStream& operator>>(QDataStream&, ldraw::Color&); - -namespace ldraw -{ - static constexpr Color MAIN_COLOR {16}; - static constexpr Color EDGE_COLOR {24}; -} +Q_DECLARE_METATYPE(ColorIndex) +static constexpr ColorIndex MAIN_COLOR {16}; +static constexpr ColorIndex EDGE_COLOR {24}; /** * @brief Contains the information about a specific color */ -struct ldraw::ColorDefinition +struct ColorDefinition { - /** - * @brief The face color. This is the color used for most objects. - * This is also used for the polygons of a subfile reference. - */ + //! @brief The face color. This is the color used for most objects. QColor faceColor; - /** - * @brief The edge color, used for the edge lines of a subfile reference. - * Note that edges using a color actually use the face color. LDraw standards - * require edges to use color 24, however. - */ + //! @brief The edge color, used for the edge lines of a subfile reference. + //! Note that edges using a color actually use the face color. LDraw standards + //! require edges to use color 24, however. QColor edgeColor; - /** - * @brief Name of the color - */ + //! @brief Name of the color QString name; - /** - * @brief A version of the name that can be shown to the user. - */ + //! @brief A version of the name that can be shown to the user. QString displayName; }; -/** - * @brief Reads LDConfig.ldr and contains color table information for lookup purposes. - */ -class ldraw::ColorTable +//extern const ColorDefinition unknownColor; +using ColorTable = std::map; +std::optional loadColorTable(QIODevice& device, QTextStream& errors); +qreal luma(const QColor& color); +ColorIndex directColor(const QColor& color); +std::optional colorFace(ColorIndex color, const ColorTable& colorTable); +std::optional colorEdge(ColorIndex color, const ColorTable& colorTable); +std::optional colorDisplayName(ColorIndex color, const ColorTable& colorTable); +QDataStream& operator<<(QDataStream&, ColorIndex); +QDataStream& operator>>(QDataStream&, ColorIndex&); + +//! @brief Calculates the luma-value for the given color. +//! @details c.f. https://en.wikipedia.org/wiki/Luma_(video) +template +constexpr T luma(T r, T g, T b) +{ + return 0.2126 * r + 0.7152 * g + 0.0722 * b; +} + +//! @brief Checks whether or not the specified color index is a direct color +constexpr bool isDirectColor(ColorIndex color) { -public: - void clear(); - Result load(QIODevice& device, QTextStream& errors); - const ColorDefinition& operator[](Color index) const; - static const ColorDefinition unknownColor; - auto begin() const { return this->definitions.begin(); } - auto end() const { return this->definitions.end(); } - int size() const; -private: - void loadColorFromString(const QString& string); - std::map definitions; -}; + return color.index >= 0x2000000; +} + +//! @brief Returns a direct color index that codes the specified color value +constexpr ColorIndex directColor(int r, int g, int b) +{ + return ColorIndex{0x2000000 | (r << 16) | (g << 8) | b}; +} -double luma(const QColor& color); +//! @brief Extracts the r, g and b color channel values from a direct color +//! index. Returns a default-constructed QColor in case a non-direct color is +//! given. +constexpr std::array directColorRgb(ColorIndex color) +{ + return { + (color.index >> 16) & 0xff, + (color.index >> 8) & 0xff, + color.index & 0xff + }; +} + +namespace ldraw +{ + using Color = ColorIndex; +} diff -r 52e10e8d88cc -r 1a4342d80de7 src/document.cpp --- a/src/document.cpp Wed Jun 08 19:33:00 2022 +0300 +++ b/src/document.cpp Wed Jun 08 20:41:21 2022 +0300 @@ -26,7 +26,7 @@ EditorTabWidget::EditorTabWidget( Model* model, DocumentManager* documents, - const ldraw::ColorTable& colorTable, + const ColorTable& colorTable, QWidget* parent) : QWidget{parent}, colorTable{colorTable}, @@ -188,7 +188,7 @@ .p1 = this->drawState.polygon[0], .p2 = this->drawState.polygon[1], }, - ldraw::EDGE_COLOR, + EDGE_COLOR, } }); break; @@ -200,7 +200,7 @@ .p2 = this->drawState.polygon[1], .p3 = this->drawState.polygon[2], }, - ldraw::MAIN_COLOR, + MAIN_COLOR, } }); break; @@ -213,7 +213,7 @@ .p3 = this->drawState.polygon[2], .p4 = this->drawState.polygon[3], }, - ldraw::MAIN_COLOR, + MAIN_COLOR, } }); break; diff -r 52e10e8d88cc -r 1a4342d80de7 src/document.h --- a/src/document.h Wed Jun 08 19:33:00 2022 +0300 +++ b/src/document.h Wed Jun 08 20:41:21 2022 +0300 @@ -45,12 +45,12 @@ explicit EditorTabWidget( Model* model, DocumentManager* documents, - const ldraw::ColorTable& colorTable, + const ColorTable& colorTable, QWidget *parent = nullptr); ~EditorTabWidget() override; void applyToVertices(VertexMap::ApplyFunction fn) const; const QSet selectedObjects() const; - const ldraw::ColorTable& colorTable; + const ColorTable& colorTable; Canvas* const canvas; Model* const model; EditingMode currentEditingMode() const; diff -r 52e10e8d88cc -r 1a4342d80de7 src/gl/compiler.cpp --- a/src/gl/compiler.cpp Wed Jun 08 19:33:00 2022 +0300 +++ b/src/gl/compiler.cpp Wed Jun 08 20:41:21 2022 +0300 @@ -232,15 +232,15 @@ static QColor getColorForPolygon( const gl::Polygon& polygon, const gl::RenderPreferences& preferences, - const ldraw::ColorTable& colorTable) + const ColorTable& colorTable) { QColor color; // For normal colors, use the polygon's color. - if (polygon.color == ldraw::MAIN_COLOR) + if (polygon.color == MAIN_COLOR) { color = preferences.mainColor; } - else if (polygon.color == ldraw::EDGE_COLOR) + else if (polygon.color == EDGE_COLOR) { // Edge color is black, unless we have a dark background, in which case lines need to be bright. color = luma(preferences.backgroundColor) > (40.0 / 256.0) ? Qt::black : Qt::white; @@ -248,7 +248,7 @@ else { // Not main or edge color, use the polygon's color as is. - color = colorTable[polygon.color].faceColor; + color = colorFace(polygon.color, colorTable).value_or(Qt::black); } return color; } @@ -275,7 +275,7 @@ void gl::build( gl::ModelShaders* shaders, Model* model, - const ldraw::ColorTable& colorTable, + const ColorTable& colorTable, DocumentManager* context, const gl::RenderPreferences& preferences) { diff -r 52e10e8d88cc -r 1a4342d80de7 src/gl/compiler.h --- a/src/gl/compiler.h Wed Jun 08 19:33:00 2022 +0300 +++ b/src/gl/compiler.h Wed Jun 08 20:41:21 2022 +0300 @@ -59,7 +59,7 @@ void build( ModelShaders* shaders, Model *model, - const ldraw::ColorTable& colorTable, + const ColorTable& colorTable, DocumentManager* context, const RenderPreferences& preferences); void initializeModelShaders(ModelShaders* modelShaders); diff -r 52e10e8d88cc -r 1a4342d80de7 src/gl/partrenderer.cpp --- a/src/gl/partrenderer.cpp Wed Jun 08 19:33:00 2022 +0300 +++ b/src/gl/partrenderer.cpp Wed Jun 08 20:41:21 2022 +0300 @@ -34,7 +34,7 @@ PartRenderer::PartRenderer( Model* model, DocumentManager* documents, - const ldraw::ColorTable& colorTable, + const ColorTable& colorTable, QWidget* parent) : QOpenGLWidget{parent}, model{model}, diff -r 52e10e8d88cc -r 1a4342d80de7 src/gl/partrenderer.h --- a/src/gl/partrenderer.h Wed Jun 08 19:33:00 2022 +0300 +++ b/src/gl/partrenderer.h Wed Jun 08 20:41:21 2022 +0300 @@ -13,7 +13,7 @@ PartRenderer( Model* model, DocumentManager* documents, - const ldraw::ColorTable& colorTable, + const ColorTable& colorTable, QWidget* parent = nullptr); ~PartRenderer() override; void setRenderPreferences(const gl::RenderPreferences& newPreferences); @@ -27,7 +27,7 @@ void wheelEvent(QWheelEvent* event) override; Model* const model; DocumentManager* const documents; - const ldraw::ColorTable& colorTable; + const ColorTable& colorTable; BoundingBox boundingBox; gl::ModelShaders shaders; ModelId highlighted = {0}; diff -r 52e10e8d88cc -r 1a4342d80de7 src/libraries.cpp --- a/src/libraries.cpp Wed Jun 08 19:33:00 2022 +0300 +++ b/src/libraries.cpp Wed Jun 08 20:41:21 2022 +0300 @@ -220,16 +220,20 @@ * @param errors Where to stream any encountered errors * @return color table */ -ldraw::ColorTable LibraryManager::loadColorTable(QTextStream& errors) const +ColorTable LibraryManager::loadColorTable(QTextStream& errors) const { - ldraw::ColorTable result; + ColorTable result; for (const Library& library : this->libraries) { const QString path = library.path.filePath("LDConfig.ldr"); QFile file{path}; if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { - (void) result.load(file, errors); + const auto loadedTable = ::loadColorTable(file, errors); + if (loadedTable) { + result = std::move(*loadedTable); + } + break; } } return result; diff -r 52e10e8d88cc -r 1a4342d80de7 src/libraries.h --- a/src/libraries.h Wed Jun 08 19:33:00 2022 +0300 +++ b/src/libraries.h Wed Jun 08 20:41:21 2022 +0300 @@ -78,7 +78,7 @@ int rowCount(const QModelIndex&) const override; int columnCount(const QModelIndex&) const override; bool isValidIndex(const int libraryIndex) const; - ldraw::ColorTable loadColorTable(QTextStream& errors) const; + ColorTable loadColorTable(QTextStream& errors) const; private: enum Column { diff -r 52e10e8d88cc -r 1a4342d80de7 src/main.cpp --- a/src/main.cpp Wed Jun 08 19:33:00 2022 +0300 +++ b/src/main.cpp Wed Jun 08 20:41:21 2022 +0300 @@ -170,7 +170,7 @@ return title; } -static ldraw::ColorTable loadColors(const LibraryManager* libraries) +static ColorTable loadColors(const LibraryManager* libraries) { QTextStream errors; return libraries->loadColorTable(errors); @@ -292,7 +292,7 @@ LibraryManager libraries{&mainWindow}; QByteArray documentSplitterState; QStringList recentlyOpenedFiles; - ldraw::ColorTable colorTable; + ColorTable colorTable; gl::RenderPreferences renderPreferences; QMap itemSelectionModels; ui.setupUi(&mainWindow); diff -r 52e10e8d88cc -r 1a4342d80de7 src/main.h --- a/src/main.h Wed Jun 08 19:33:00 2022 +0300 +++ b/src/main.h Wed Jun 08 20:41:21 2022 +0300 @@ -265,6 +265,9 @@ } } +template +using opt = std::optional; + // some magic code from https://en.cppreference.com/w/cpp/utility/variant/visit // for use with std::visit template struct overloaded : Ts... { using Ts::operator()...; }; diff -r 52e10e8d88cc -r 1a4342d80de7 src/polygoncache.cpp --- a/src/polygoncache.cpp Wed Jun 08 19:33:00 2022 +0300 +++ b/src/polygoncache.cpp Wed Jun 08 20:41:21 2022 +0300 @@ -61,7 +61,7 @@ { gl::invert(polygon); } - if (polygon.color == ldraw::MAIN_COLOR) + if (polygon.color == MAIN_COLOR) { polygon.color = ref.color; } diff -r 52e10e8d88cc -r 1a4342d80de7 src/ui/canvas.cpp --- a/src/ui/canvas.cpp Wed Jun 08 19:33:00 2022 +0300 +++ b/src/ui/canvas.cpp Wed Jun 08 20:41:21 2022 +0300 @@ -7,7 +7,7 @@ Model* model, EditorTabWidget *document, DocumentManager* documents, - const ldraw::ColorTable& colorTable, + const ColorTable& colorTable, QWidget* parent) : PartRenderer{model, documents, colorTable, parent}, document{document} diff -r 52e10e8d88cc -r 1a4342d80de7 src/ui/canvas.h --- a/src/ui/canvas.h Wed Jun 08 19:33:00 2022 +0300 +++ b/src/ui/canvas.h Wed Jun 08 20:41:21 2022 +0300 @@ -32,7 +32,7 @@ Model* model, EditorTabWidget* document, DocumentManager* documents, - const ldraw::ColorTable& colorTable, + const ColorTable& colorTable, QWidget* parent = nullptr); void setOverpaintCallback(OverpaintCallback fn); void drawWorldPoint(QPainter* painter, const glm::vec3& worldPoint) const; diff -r 52e10e8d88cc -r 1a4342d80de7 src/widgets/colorindexinput.cpp --- a/src/widgets/colorindexinput.cpp Wed Jun 08 19:33:00 2022 +0300 +++ b/src/widgets/colorindexinput.cpp Wed Jun 08 20:41:21 2022 +0300 @@ -3,7 +3,7 @@ #include "colorselectdialog.h" #include "uiutilities.h" -ColorIndexInput::ColorIndexInput(EditorTabWidget *document, ldraw::Color color, QWidget *parent) : +ColorIndexInput::ColorIndexInput(EditorTabWidget *document, ColorIndex color, QWidget *parent) : QWidget{parent}, document{document}, ui{*new Ui_ColorIndexInput} @@ -20,8 +20,11 @@ }); connect(this->ui.index, qOverload(&QSpinBox::valueChanged), [this](int value) { - this->ui.button->setText(ldraw::colorDisplayName({value}, this->document->colorTable)); - uiutilities::colorizeWidget(this->ui.button, ldraw::colorFace({value}, this->document->colorTable)); + this->ui.button->setText(colorDisplayName({value}, this->document->colorTable).value_or("???")); + const opt face = colorFace({value}, this->document->colorTable); + if (face.has_value()) { + uiutilities::colorizeWidget(this->ui.button, *face); + } Q_EMIT this->colorChanged({value}); }); this->ui.index->setValue(color.index); diff -r 52e10e8d88cc -r 1a4342d80de7 src/widgets/colorindexinput.h --- a/src/widgets/colorindexinput.h Wed Jun 08 19:33:00 2022 +0300 +++ b/src/widgets/colorindexinput.h Wed Jun 08 20:41:21 2022 +0300 @@ -5,7 +5,7 @@ { Q_OBJECT public: - ColorIndexInput(EditorTabWidget *document, ldraw::Color color = ldraw::MAIN_COLOR, QWidget *parent = nullptr); + ColorIndexInput(EditorTabWidget *document, ColorIndex color = MAIN_COLOR, QWidget *parent = nullptr); ~ColorIndexInput(); ldraw::Color selectedColor() const; void setSelectedColor(ldraw::Color color); diff -r 52e10e8d88cc -r 1a4342d80de7 src/widgets/colorselectdialog.cpp --- a/src/widgets/colorselectdialog.cpp Wed Jun 08 19:33:00 2022 +0300 +++ b/src/widgets/colorselectdialog.cpp Wed Jun 08 20:41:21 2022 +0300 @@ -5,7 +5,7 @@ #include "ui_colorselectdialog.h" #include "uiutilities.h" -ColorSelectDialog::ColorSelectDialog(const ldraw::ColorTable& colorTable, QWidget *parent) : +ColorSelectDialog::ColorSelectDialog(const ColorTable& colorTable, QWidget *parent) : QDialog{parent}, ui{*new Ui_ColorSelectDialog}, colorTable{colorTable} @@ -39,12 +39,13 @@ iterator != std::end(this->colorTable); ++iterator ) { - const qint32 index = iterator->first; - const ldraw::ColorDefinition& colordef = iterator->second; + const qint32 index = iterator->first.index; + const ColorDefinition& colordef = iterator->second; QPushButton* const button = new QPushButton{QString::number(index), this}; button->setMinimumSize({40, 40}); button->setToolTip(colordef.displayName); - uiutilities::colorizeWidget(button, ldraw::colorFace({index}, colorTable)); + const QColor face = colorFace({index}, colorTable).value_or(QColor{}); + uiutilities::colorizeWidget(button, face); button->setProperty("_colorIndex", index); button->setCheckable(true); connect(button, &QAbstractButton::clicked, this, &ColorSelectDialog::handleButtonClick); @@ -90,8 +91,10 @@ void ColorSelectDialog::updateSelectedColorTexts() { - this->ui.selectedColorName->setText(ldraw::colorDisplayName(this->selectedColor, this->colorTable)); - uiutilities::colorizeWidget(this->ui.selectedColorName, ldraw::colorFace(this->selectedColor, colorTable)); + const QString displayName = colorDisplayName(this->selectedColor, this->colorTable).value_or(QStringLiteral("???")); + this->ui.selectedColorName->setText(displayName); + const QColor face = colorFace(this->selectedColor, colorTable).value_or(QColor{}); + uiutilities::colorizeWidget(this->ui.selectedColorName, face); this->ui.colorIndex->setValue(this->selectedColor.index); for (QPushButton* button : this->buttons) { @@ -117,10 +120,13 @@ void ColorSelectDialog::chooseDirectColor() { QColorDialog dialog; - dialog.setCurrentColor(ldraw::colorFace(this->selectedColor, this->colorTable)); + const std::optional face = colorFace(this->selectedColor, this->colorTable); + if (face.has_value()) { + dialog.setCurrentColor(*face); + } if (dialog.exec()) { - this->setCurrentColor(ldraw::directColor(dialog.selectedColor())); + this->setCurrentColor(directColor(dialog.selectedColor())); } } @@ -133,12 +139,12 @@ } else { - const ldraw::ColorDefinition& colordef = this->colorTable[color]; - return colordef.displayName.contains(filterText, Qt::CaseInsensitive); + const std::optional name = colorDisplayName(color, colorTable); + return name.value_or(QString{}).contains(filterText, Qt::CaseInsensitive); } } -void ColorSelectDialog::setCurrentColor(ldraw::Color color) +void ColorSelectDialog::setCurrentColor(ColorIndex color) { this->selectedColor = color; this->updateSelectedColorTexts(); diff -r 52e10e8d88cc -r 1a4342d80de7 src/widgets/colorselectdialog.h --- a/src/widgets/colorselectdialog.h Wed Jun 08 19:33:00 2022 +0300 +++ b/src/widgets/colorselectdialog.h Wed Jun 08 20:41:21 2022 +0300 @@ -10,9 +10,9 @@ { Q_OBJECT public: - explicit ColorSelectDialog(const ldraw::ColorTable& colorTable, QWidget* parent = nullptr); + explicit ColorSelectDialog(const ColorTable& colorTable, QWidget* parent = nullptr); ~ColorSelectDialog(); - void setCurrentColor(ldraw::Color color); + void setCurrentColor(ColorIndex color); ldraw::Color currentColor() const; private Q_SLOTS: void populateColors(); @@ -24,7 +24,7 @@ void makeColorButtons(); bool filterColor(ldraw::Color color) const; class Ui_ColorSelectDialog& ui; - const ldraw::ColorTable& colorTable; + const ColorTable& colorTable; std::vector buttons; - ldraw::Color selectedColor = ldraw::MAIN_COLOR; + ColorIndex selectedColor = MAIN_COLOR; };