Thu, 10 May 2018 14:57:23 +0300
added scaling vector editing into the subfile editing dialog
--- a/src/dialogs/subfilereferenceeditor.cpp Wed Apr 25 18:55:15 2018 +0300 +++ b/src/dialogs/subfilereferenceeditor.cpp Thu May 10 14:57:23 2018 +0300 @@ -49,7 +49,15 @@ { QLayoutItem* item = this->ui.matrixLayout->itemAtPosition(i, j); QDoubleSpinBox* spinbox = item ? qobject_cast<QDoubleSpinBox*>(item->widget()) : nullptr; + spinbox->blockSignals(true); spinbox->setValue(reference->transformationMatrix()(i, j)); + spinbox->blockSignals(false); + connect( + spinbox, + qOverload<double>(&QDoubleSpinBox::valueChanged), + this, + &SubfileReferenceEditor::matrixChanged + ); } connect( this->ui.primitivesTreeView, @@ -63,6 +71,69 @@ this->ui.referenceName->setText(primitiveName.toString()); } ); + + for (QDoubleSpinBox* spinbox : {this->ui.scalingX, this->ui.scalingY, this->ui.scalingZ}) + { + connect( + spinbox, + qOverload<double>(&QDoubleSpinBox::valueChanged), + this, + &SubfileReferenceEditor::scalingChanged + ); + } + + // Fill in the initial scaling values + for (int column : {0, 1, 2}) + { + QDoubleSpinBox* spinbox = this->vectorElement(column); + spinbox->blockSignals(true); + spinbox->setValue(this->matrixScaling(column)); + spinbox->blockSignals(false); + } +} + +SubfileReferenceEditor::~SubfileReferenceEditor() +{ + delete &this->ui; +} + +/* + * Returns a spinbox from the matrix grid at position (row, column). + * Row and column must be within [0, 2]. + */ +QDoubleSpinBox* SubfileReferenceEditor::matrixCell(int row, int column) const +{ + if (qBound(0, row, 2) != row or qBound(0, column, 2) != column) + { + throw std::out_of_range {"bad row and column values"}; + } + else + { + QLayoutItem* item = this->ui.matrixLayout->itemAtPosition(row, column); + return item ? qobject_cast<QDoubleSpinBox*>(item->widget()) : nullptr; + } +} + +/* + * Returns a spinbox for the vector element at the given position + * Index must be within [0, 2] + */ +QDoubleSpinBox* SubfileReferenceEditor::vectorElement(int index) +{ + switch (index) + { + case 0: + return this->ui.scalingX; + + case 1: + return this->ui.scalingY; + + case 2: + return this->ui.scalingZ; + + default: + throw std::out_of_range {"bad index"}; + } } void SubfileReferenceEditor::accept() @@ -72,9 +143,7 @@ for (int i : {0, 1, 2}) for (int j : {0, 1, 2}) { - QLayoutItem* item = this->ui.matrixLayout->itemAtPosition(i, j); - QDoubleSpinBox* spinbox = item ? qobject_cast<QDoubleSpinBox*>(item->widget()) : nullptr; - transformationMatrix(i, j) = spinbox->value(); + transformationMatrix(i, j) = this->matrixCell(i, j)->value(); } this->reference->setTransformationMatrix(transformationMatrix); this->reference->setPosition({ @@ -91,7 +160,74 @@ this->ui.primitivesTreeView->setModel(primitives); } -SubfileReferenceEditor::~SubfileReferenceEditor() +double SubfileReferenceEditor::matrixScaling(int column) const +{ + return sqrt( + pow(this->matrixCell(0, column)->value(), 2) + + pow(this->matrixCell(1, column)->value(), 2) + + pow(this->matrixCell(2, column)->value(), 2) + ); +} + +/* + * Updates the appropriate matrix column when a scaling vector element is changed. + */ +void SubfileReferenceEditor::scalingChanged() { - delete &this->ui; + for (int column : {0, 1, 2}) + { + if (this->sender() == this->vectorElement(column)) + { + double oldScaling = this->matrixScaling(column); + double newScaling = static_cast<QDoubleSpinBox*>(this->sender())->value(); + + if (not qFuzzyCompare(newScaling, 0.0)) + { + for (int row : {0, 1, 2}) + { + double cellValue = abs(this->matrixCell(row, column)->value()); + cellValue *= newScaling / oldScaling; + QDoubleSpinBox* cellWidget = this->matrixCell(row, column); + cellWidget->blockSignals(true); + cellWidget->setValue(cellValue); + cellWidget->blockSignals(false); + } + } + + break; + } + } } + +/* + * Finds the position for the given cell widget. + */ +QPair<int, int> SubfileReferenceEditor::cellPosition(QDoubleSpinBox* cellWidget) +{ + for (int row : {0, 1, 2}) + for (int column : {0, 1, 2}) + { + if (this->matrixCell(row, column) == cellWidget) + return {row, column}; + } + + throw std::out_of_range {"widget is not in the matrix"}; +} + +/* + * Updates the appropriate scaling vector element when a matrix cell is changed. + */ +void SubfileReferenceEditor::matrixChanged() +{ + QDoubleSpinBox* cellWidget = static_cast<QDoubleSpinBox*>(this->sender()); + + try + { + int column = this->cellPosition(cellWidget).second; + QDoubleSpinBox* spinbox = this->vectorElement(column); + spinbox->blockSignals(true); + spinbox->setValue(this->matrixScaling(column)); + spinbox->blockSignals(false); + } + catch (const std::out_of_range&) {} +}
--- a/src/dialogs/subfilereferenceeditor.h Wed Apr 25 18:55:15 2018 +0300 +++ b/src/dialogs/subfilereferenceeditor.h Thu May 10 14:57:23 2018 +0300 @@ -20,6 +20,8 @@ #include <QDialog> #include "../main.h" +class QDoubleSpinBox; + class SubfileReferenceEditor : public QDialog { Q_OBJECT @@ -31,7 +33,16 @@ void accept() override; void setPrimitivesTree(class PrimitiveManager* primitives); +private slots: + void scalingChanged(); + void matrixChanged(); + private: + QDoubleSpinBox* matrixCell(int row, int column) const; + double matrixScaling(int column) const; + QPair<int, int> cellPosition(QDoubleSpinBox* cellWidget); + QDoubleSpinBox* vectorElement(int index); + class Ui_SubfileReferenceEditor& ui; class LDSubfileReference* const reference; LDColor color;
--- a/src/dialogs/subfilereferenceeditor.ui Wed Apr 25 18:55:15 2018 +0300 +++ b/src/dialogs/subfilereferenceeditor.ui Thu May 10 14:57:23 2018 +0300 @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>625</width> - <height>642</height> + <height>644</height> </rect> </property> <property name="windowTitle"> @@ -110,6 +110,13 @@ </item> </layout> </item> + <item row="3" column="1"> + <widget class="Line" name="line"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> <item row="4" column="0"> <widget class="QLabel" name="label_3"> <property name="text"> @@ -238,8 +245,67 @@ </item> </layout> </item> - <item row="3" column="1"> - <widget class="Line" name="line"> + <item row="6" column="0"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>Scaling vector:</string> + </property> + </widget> + </item> + <item row="6" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QDoubleSpinBox" name="scalingX"> + <property name="prefix"> + <string>𝑥 × </string> + </property> + <property name="decimals"> + <number>5</number> + </property> + <property name="minimum"> + <double>-10000.000000000000000</double> + </property> + <property name="maximum"> + <double>10000.000000000000000</double> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="scalingY"> + <property name="prefix"> + <string>𝑦 × </string> + </property> + <property name="decimals"> + <number>5</number> + </property> + <property name="minimum"> + <double>-10000.000000000000000</double> + </property> + <property name="maximum"> + <double>10000.000000000000000</double> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="scalingZ"> + <property name="prefix"> + <string>𝑧 × </string> + </property> + <property name="decimals"> + <number>5</number> + </property> + <property name="minimum"> + <double>-10000.000000000000000</double> + </property> + <property name="maximum"> + <double>10000.000000000000000</double> + </property> + </widget> + </item> + </layout> + </item> + <item row="5" column="1"> + <widget class="Line" name="line_2"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> @@ -259,6 +325,26 @@ </item> </layout> </widget> + <tabstops> + <tabstop>primitivesTreeView</tabstop> + <tabstop>referenceName</tabstop> + <tabstop>colorButton</tabstop> + <tabstop>positionX</tabstop> + <tabstop>positionY</tabstop> + <tabstop>positionZ</tabstop> + <tabstop>matrixA</tabstop> + <tabstop>matrixB</tabstop> + <tabstop>matrixC</tabstop> + <tabstop>matrixD</tabstop> + <tabstop>matrixE</tabstop> + <tabstop>matrixF</tabstop> + <tabstop>matrixG</tabstop> + <tabstop>matrixH</tabstop> + <tabstop>matrixI</tabstop> + <tabstop>scalingX</tabstop> + <tabstop>scalingY</tabstop> + <tabstop>scalingZ</tabstop> + </tabstops> <resources/> <connections> <connection> @@ -268,8 +354,8 @@ <slot>accept()</slot> <hints> <hint type="sourcelabel"> - <x>248</x> - <y>254</y> + <x>257</x> + <y>634</y> </hint> <hint type="destinationlabel"> <x>157</x> @@ -284,8 +370,8 @@ <slot>reject()</slot> <hints> <hint type="sourcelabel"> - <x>316</x> - <y>260</y> + <x>325</x> + <y>634</y> </hint> <hint type="destinationlabel"> <x>286</x>