added scaling vector editing into the subfile editing dialog

Thu, 10 May 2018 14:57:23 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Thu, 10 May 2018 14:57:23 +0300
changeset 1386
c59dac18b06b
parent 1384
4c134708be05
child 1387
6393b6020c62

added scaling vector editing into the subfile editing dialog

src/dialogs/subfilereferenceeditor.cpp file | annotate | diff | comparison | revisions
src/dialogs/subfilereferenceeditor.h file | annotate | diff | comparison | revisions
src/dialogs/subfilereferenceeditor.ui file | annotate | diff | comparison | revisions
--- 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>

mercurial