Mon, 21 Sep 2020 19:48:18 +0300
added a color select dialog
CMakeLists.txt | file | annotate | diff | comparison | revisions | |
src/colors.cpp | file | annotate | diff | comparison | revisions | |
src/colors.h | file | annotate | diff | comparison | revisions | |
src/document.ui | file | annotate | diff | comparison | revisions | |
src/mainwindow.cpp | file | annotate | diff | comparison | revisions | |
src/widgets/colorselectdialog.cpp | file | annotate | diff | comparison | revisions |
--- a/CMakeLists.txt Mon Aug 24 23:02:30 2020 +0300 +++ b/CMakeLists.txt Mon Sep 21 19:48:18 2020 +0300 @@ -18,13 +18,13 @@ find_package(OpenGL REQUIRED) include_directories(${QT_INCLUDES} ${CMAKE_CURRENT_BINARY_DIR}) include_directories(${GLM_INCLUDE_DIR}) -source_group("1 Foundation code" REGULAR_EXPRESSION "src/.+\\.(cpp|h)") -source_group("4 OpenGL renderer" REGULAR_EXPRESSION "src/gl/.+\\.(cpp|h)") -source_group("5 LDraw line types" REGULAR_EXPRESSION "src/linetypes/.+\\.(cpp|h)") -source_group("3 UI and widgets" REGULAR_EXPRESSION "src/(ui|widgets)/.+\\.(cpp|h)") -source_group("3.1 Settings editor" REGULAR_EXPRESSION "src/settingseditor/.+\\.(cpp|h)") -source_group("3.2 Main UI" REGULAR_EXPRESSION "src/(mainwindow|document|documentmanager|uiutilities)\\.(cpp|h)") -source_group("2 Model handling" REGULAR_EXPRESSION "src/(model|modeleditcontext|libraries|colors|parser)\\.(cpp|h)") +source_group("1 Foundation code" REGULAR_EXPRESSION "src/.+\\.(cpp|h|ui)") +source_group("4 OpenGL renderer" REGULAR_EXPRESSION "src/gl/.+\\.(cpp|h|ui)") +source_group("5 LDraw line types" REGULAR_EXPRESSION "src/linetypes/.+\\.(cpp|h|ui)") +source_group("3.2 Widgets" REGULAR_EXPRESSION "src/(ui|widgets)/.+\\.(cpp|h|ui)") +source_group("3.1 Settings editor" REGULAR_EXPRESSION "src/settingseditor/.+\\.(cpp|h|ui)") +source_group("3 User interface" REGULAR_EXPRESSION "src/(mainwindow|document|documentmanager|uiutilities)\\.(cpp|h|ui)") +source_group("2 Model handling" REGULAR_EXPRESSION "src/(model|modeleditcontext|libraries|colors|parser)\\.(cpp|h|ui)") set (LDFORGE_SOURCES src/colors.cpp @@ -63,6 +63,7 @@ src/ui/objecteditor.cpp src/ui/polygonobjecteditor.cpp src/widgets/colorbutton.cpp + src/widgets/colorselectdialog.cpp src/widgets/doublespinbox.cpp src/widgets/matrixeditor.cpp src/widgets/vec3editor.cpp @@ -113,6 +114,7 @@ src/ui/objecteditor.h src/ui/polygonobjecteditor.h src/widgets/colorbutton.h + src/widgets/colorselectdialog.h src/widgets/doublespinbox.h src/widgets/matrixeditor.h src/widgets/vec3editor.h @@ -123,6 +125,7 @@ src/settingseditor/librarieseditor.ui src/settingseditor/settingseditor.ui src/ui/multiplyfactordialog.ui + src/widgets/colorselectdialog.ui src/widgets/matrixeditor.ui src/widgets/vec3editor.ui )
--- a/src/colors.cpp Mon Aug 24 23:02:30 2020 +0300 +++ b/src/colors.cpp Mon Sep 21 19:48:18 2020 +0300 @@ -18,7 +18,7 @@ #include "colors.h" -const ldraw::ColorTable::ColorDefinition ldraw::ColorTable::unknownColor{{}, {}, "Unknown"}; +const ldraw::ColorTable::ColorDefinition ldraw::ColorTable::unknownColor{{}, {}, "Unknown", "???"}; void ldraw::ColorTable::clear() { @@ -50,7 +50,7 @@ auto it = this->definitions.find(color.index); if (it != this->definitions.end()) { - return *it; + return it->second; } else { @@ -73,6 +73,8 @@ ColorDefinition& definition = 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); if (not pattern.cap(5).isEmpty()) @@ -91,3 +93,37 @@ { return 0.2126 * color.redF() + 0.7152 * color.greenF() + 0.0722 * color.blueF(); } + +ldraw::Color ldraw::directColor(const QColor& color) +{ + return ldraw::Color{0x2000000 | (color.red() << 16) | (color.green() << 8) | color.blue()}; +} + +bool ldraw::isDirectColor(ldraw::Color color) +{ + return color.index >= 0x2000000; +} + +QColor ldraw::directColorFace(ldraw::Color color) +{ + if (isDirectColor(color)) + { + return {(color.index >> 16) & 0xff, (color.index >> 8) & 0xff, color.index & 0xff}; + } + else + { + return {}; + } +} + +QColor ldraw::colorFace(ldraw::Color color, const ldraw::ColorTable& colorTable) +{ + if (isDirectColor(color)) + { + return directColorFace(color); + } + else + { + return colorTable[color].faceColor; + } +}
--- a/src/colors.h Mon Aug 24 23:02:30 2020 +0300 +++ b/src/colors.h Mon Sep 21 19:48:18 2020 +0300 @@ -24,6 +24,10 @@ { struct Color; class ColorTable; + Color directColor(const QColor& color); + bool isDirectColor(Color color); + QColor directColorFace(Color color); + QColor colorFace(Color color, const ColorTable& colorTable); } struct ldraw::Color @@ -41,14 +45,18 @@ QColor faceColor; QColor edgeColor; QString name; + QString displayName; }; 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 { return this->definitions.size(); } private: void loadColorFromString(const QString& string); - QMap<qint32, ColorDefinition> definitions; + std::map<qint32, ColorDefinition> definitions; }; namespace ldraw
--- a/src/document.ui Mon Aug 24 23:02:30 2020 +0300 +++ b/src/document.ui Mon Sep 21 19:48:18 2020 +0300 @@ -15,28 +15,33 @@ </property> <layout class="QVBoxLayout" name="verticalLayout"> <item> - <widget class="QSplitter" name="splitter"> + <widget class="QSplitter" name="splitter_2"> <property name="orientation"> - <enum>Qt::Horizontal</enum> + <enum>Qt::Vertical</enum> </property> - <widget class="QFrame" name="viewportFrame"> - <property name="frameShape"> - <enum>QFrame::StyledPanel</enum> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> + <widget class="QSplitter" name="splitter"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> </property> - </widget> - <widget class="QListView" name="listView"> - <property name="alternatingRowColors"> - <bool>true</bool> - </property> - <property name="selectionMode"> - <enum>QAbstractItemView::ExtendedSelection</enum> - </property> - <property name="selectionBehavior"> - <enum>QAbstractItemView::SelectRows</enum> - </property> + <widget class="QFrame" name="viewportFrame"> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + </widget> + <widget class="QListView" name="listView"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::ExtendedSelection</enum> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectRows</enum> + </property> + </widget> </widget> <widget class="QFrame" name="objectEditorFrame"> <property name="frameShape">
--- a/src/mainwindow.cpp Mon Aug 24 23:02:30 2020 +0300 +++ b/src/mainwindow.cpp Mon Sep 21 19:48:18 2020 +0300 @@ -27,6 +27,7 @@ #include "version.h" #include "document.h" #include "uiutilities.h" +#include "widgets/colorselectdialog.h" template<typename BaseType, typename MemberType, typename DataType> struct MemberData
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/widgets/colorselectdialog.cpp Mon Sep 21 19:48:18 2020 +0300 @@ -0,0 +1,158 @@ +#include <QColorDialog> +#include <QTableView> +#include "colorselectdialog.h" +#include "ui_colorselectdialog.h" + +ColorSelectDialog::ColorSelectDialog(const ldraw::ColorTable& colorTable, QWidget *parent) : + QDialog{parent}, + ui{*new Ui_ColorSelectDialog}, + colorTable{colorTable} +{ + this->ui.setupUi(this); + this->makeColorButtons(); + connect(this->ui.filter, &QLineEdit::textEdited, this, &ColorSelectDialog::populateColors); + this->updateSelectedColorTexts(); + connect(this->ui.colorIndex, qOverload<int>(&QSpinBox::valueChanged), this, &ColorSelectDialog::spinboxEdited); + connect(this->ui.directColorButton, &QPushButton::clicked, this, &ColorSelectDialog::chooseDirectColor); + connect(this->ui.buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(this->ui.buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + this->populateColors(); +} + +ColorSelectDialog::~ColorSelectDialog() +{ + delete &this->ui; +} + +ldraw::Color colorFromButton(QAbstractButton* button) +{ + return {button->property("_colorIndex").value<qint32>()}; +} + +QString styleSheetForColor(const QColor& color) +{ + QColor const textColor = (luma(color) < 0.4) ? Qt::white : Qt::black; + return QString{"background-color: %1; color: %2;"} + .arg(color.name()) + .arg(textColor.name()); +} + +void ColorSelectDialog::makeColorButtons() +{ + this->buttons.reserve(this->colorTable.size()); + for ( + auto iterator = std::begin(this->colorTable); + iterator != std::end(this->colorTable); + ++iterator + ) { + const qint32 index = iterator->first; + const ldraw::ColorTable::ColorDefinition& colordef = iterator->second; + QPushButton* const button = new QPushButton{QString::number(index), this}; + button->setToolTip(colordef.displayName); + button->setStyleSheet(styleSheetForColor(colordef.faceColor)); + button->setProperty("_colorIndex", index); + button->setCheckable(true); + connect(button, &QAbstractButton::clicked, this, &ColorSelectDialog::handleButtonClick); + this->buttons.push_back(button); + } + std::sort( + std::begin(this->buttons), + std::end(this->buttons), + [](QAbstractButton* button_1, QAbstractButton* button_2) + { + return colorFromButton(button_1) < colorFromButton(button_2); + } + ); +} + +void ColorSelectDialog::populateColors() +{ + delete this->ui.colorFrame->layout(); + if (this->buttons.size() > 0) + { + QGridLayout* gridLayout = new QGridLayout{}; + this->ui.colorFrame->setLayout(gridLayout); + const int columnsPerRow = 8; + int i = 0; + for ( + auto iterator = std::begin(this->buttons); + iterator != std::end(this->buttons); + ++iterator + ) { + QPushButton* const button = *iterator; + const bool filtered = this->filterColor(colorFromButton(button)); + button->setVisible(filtered); + if (filtered) + { + const int row = i / columnsPerRow; + const int column = i % columnsPerRow; + gridLayout->addWidget(button, row, column); + i += 1; + } + } + } +} + +void ColorSelectDialog::updateSelectedColorTexts() +{ + if (ldraw::isDirectColor(this->selectedColor)) + { + this->ui.selectedColorName->setText(ldraw::directColorFace(this->selectedColor).name()); + } + else + { + const ldraw::ColorTable::ColorDefinition& colordef = this->colorTable[this->selectedColor]; + this->ui.selectedColorName->setText(colordef.displayName); + } + this->ui.selectedColorName->setStyleSheet(styleSheetForColor(ldraw::colorFace(this->selectedColor, this->colorTable))); + this->ui.colorIndex->setValue(this->selectedColor.index); + for (QPushButton* button : this->buttons) + { + ldraw::Color buttonColor = colorFromButton(button); + button->setChecked(buttonColor == this->selectedColor); + } +} + +void ColorSelectDialog::handleButtonClick() +{ + QAbstractButton* button = qobject_cast<QAbstractButton*>(this->sender()); + if (button != nullptr) + { + this->setCurrentColor(colorFromButton(button)); + } +} + +void ColorSelectDialog::spinboxEdited() +{ + this->setCurrentColor(ldraw::Color{this->ui.colorIndex->value()}); +} + +void ColorSelectDialog::chooseDirectColor() +{ + QColorDialog dialog; + dialog.setCurrentColor(ldraw::colorFace(this->selectedColor, this->colorTable)); + if (dialog.exec()) + { + this->setCurrentColor(ldraw::directColor(dialog.selectedColor())); + } +} + +bool ColorSelectDialog::filterColor(ldraw::Color color) const +{ + const QString& filterText = this->ui.filter->text(); + if (filterText.isEmpty()) + { + return true; + } + else + { + const ldraw::ColorTable::ColorDefinition& colordef = this->colorTable[color]; + return colordef.displayName.contains(filterText, Qt::CaseInsensitive); + } +} + +void ColorSelectDialog::setCurrentColor(ldraw::Color color) +{ + this->selectedColor = color; + this->updateSelectedColorTexts(); +}