src/widgets/colorselectdialog.cpp

Mon, 20 Jun 2022 21:14:17 +0300

author
Teemu Piippo <teemu.s.piippo@gmail.com>
date
Mon, 20 Jun 2022 21:14:17 +0300
changeset 238
b8ad4c12d937
parent 205
1a4342d80de7
child 264
76a025db4948
permissions
-rw-r--r--

Fix pick scene rendering: we cannot use glReadPixels when using multisampling, so we need to render the pick scene to a separate frame buffer

#include <QColorDialog>
#include <QTableView>
#include <QStyleFactory>
#include "colorselectdialog.h"
#include "ui_colorselectdialog.h"
#include "uiutilities.h"

ColorSelectDialog::ColorSelectDialog(const 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>()};
}

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.index;
		const ColorDefinition& colordef = iterator->second;
		QPushButton* const button = new QPushButton{QString::number(index), this};
		button->setMinimumSize({40, 40});
		button->setToolTip(colordef.displayName);
		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);
		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()
{
	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)
	{
		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;
	const std::optional<QColor> face = colorFace(this->selectedColor, this->colorTable);
	if (face.has_value()) {
		dialog.setCurrentColor(*face);
	}
	if (dialog.exec())
	{
		this->setCurrentColor(directColor(dialog.selectedColor()));
	}
}

bool ColorSelectDialog::filterColor(ldraw::Color color) const
{
	const QString& filterText = this->ui.filter->text();
	if (filterText.isEmpty())
	{
		return true;
	}
	else
	{
		const std::optional<QString> name = colorDisplayName(color, colorTable);
		return name.value_or(QString{}).contains(filterText, Qt::CaseInsensitive);
	}
}

void ColorSelectDialog::setCurrentColor(ColorIndex color)
{
	this->selectedColor = color;
	this->updateSelectedColorTexts();
}

ldraw::Color ColorSelectDialog::currentColor() const
{
	return this->selectedColor;
}

mercurial