From 83ad93aadfd9115a6aca713c1a96771441f10718 Mon Sep 17 00:00:00 2001 From: mfeemster Date: Fri, 29 May 2015 21:08:44 -0700 Subject: [PATCH] --User changes More efficient table on the Xaos tab when using xaos on a flame with a large number of xforms. --Code changes Use QTableView instead of QTableWidget for the xaos table. Add custom DoubleSpinBoxTableItemDelegate for this. Make row and column toggling functions work for QTableView and QTableWidget. Remove some dead code from Fractorium.h/cpp Miscellaneous hacks to keep it building on Linux. --- Builds/MSVC/VS2013/Fractorium.vcxproj | 44 +++++ Builds/MSVC/VS2013/Fractorium.vcxproj.filters | 12 ++ .../DoubleSpinBoxTableItemDelegate.h | 91 ++++++++++ Source/Fractorium/Fractorium.cpp | 166 +++++++++--------- Source/Fractorium/Fractorium.h | 15 +- Source/Fractorium/Fractorium.ui | 74 ++------ Source/Fractorium/FractoriumEmberController.h | 4 +- Source/Fractorium/FractoriumPch.h | 1 + Source/Fractorium/FractoriumXaos.cpp | 129 +++++++------- .../Fractorium/FractoriumXformsVariations.cpp | 1 + Source/Fractorium/SpinBox.cpp | 1 + 11 files changed, 327 insertions(+), 211 deletions(-) create mode 100644 Source/Fractorium/DoubleSpinBoxTableItemDelegate.h diff --git a/Builds/MSVC/VS2013/Fractorium.vcxproj b/Builds/MSVC/VS2013/Fractorium.vcxproj index d4c16dc..5a78d0e 100644 --- a/Builds/MSVC/VS2013/Fractorium.vcxproj +++ b/Builds/MSVC/VS2013/Fractorium.vcxproj @@ -361,6 +361,12 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"true true + + true + true + true + true + true true @@ -447,6 +453,12 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"true true + + true + true + true + true + true true @@ -519,6 +531,12 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)"true true + + true + true + true + true + true true @@ -776,6 +794,32 @@ xcopy /F /Y /R /D "$(SolutionDir)..\..\..\Data\flam3-palettes.xml" "$(OutDir)".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/CurvesGraphicsView.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(AMDAPPSDKROOT)\include" "-I$(CUDA_PATH)include" "-I.\GeneratedFiles\$(ConfigurationName)\." + + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing DoubleSpinBoxTableItemDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/DoubleSpinBoxTableItemDelegate.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(AMDAPPSDKROOT)\include" "-I$(CUDA_PATH)include" "-I.\GeneratedFiles\$(ConfigurationName)\." + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing DoubleSpinBoxTableItemDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/DoubleSpinBoxTableItemDelegate.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(AMDAPPSDKROOT)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing DoubleSpinBoxTableItemDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/DoubleSpinBoxTableItemDelegate.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(AMDAPPSDKROOT)\include" "-I$(CUDA_PATH)include" "-I.\GeneratedFiles\$(ConfigurationName)\." + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing DoubleSpinBoxTableItemDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/DoubleSpinBoxTableItemDelegate.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(AMDAPPSDKROOT)\include" "-I.\GeneratedFiles\$(ConfigurationName)\." + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing DoubleSpinBoxTableItemDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/DoubleSpinBoxTableItemDelegate.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(CUDA_PATH)include" "-I.\GeneratedFiles\$(ConfigurationName)\." + $(QTDIR)\bin\moc.exe;%(FullPath) + Moc%27ing DoubleSpinBoxTableItemDelegate.h... + .\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp + "$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\GeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" "-fFractoriumPch.h" "-f../../../../../Source/Fractorium/DoubleSpinBoxTableItemDelegate.h" -DUNICODE -DWIN32 -DQT_DLL -DQT_NO_DEBUG -DNDEBUG -DQT_CORE_LIB -DQT_GUI_LIB -DQT_MULTIMEDIA_LIB -DQT_HELP_LIB -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_XML_LIB -D_MBCS "-I." "-I$(QTDIR)\include" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles" "-I$(ProjectDir)..\..\..\Fractorium\GeneratedFiles\ConfigurationName" "-I$(QTDIR)\..\qtmultimedia\include\QtMultimedia" "-I$(QTDIR)\..\qtmultimedia\include" "-I$(QTDIR)\..\qttools\include" "-I$(QTDIR)\..\qttools\include\QtHelp" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtCore" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtXml" "-I.\GeneratedFiles" "-I$(ProjectDir)..\..\..\Source\Ember" "-I$(ProjectDir)..\..\..\Source\EmberCL" "-I$(ProjectDir)..\..\..\Source\EmberCommon" "-I$(ProjectDir)..\..\..\..\glm" "-I$(ProjectDir)..\..\..\..\tbb\include" "-I$(ProjectDir)..\..\..\..\libjpeg" "-I$(ProjectDir)..\..\..\..\libpng" "-I$(ProjectDir)..\..\..\..\libxml2\include" "-I$(ProjectDir)..\..\..\..\glew\include" "-I$(AMDAPPSDKROOT)\include" "-I$(CUDA_PATH)include" "-I.\GeneratedFiles\$(ConfigurationName)\." + diff --git a/Builds/MSVC/VS2013/Fractorium.vcxproj.filters b/Builds/MSVC/VS2013/Fractorium.vcxproj.filters index 853fb83..bb3dac8 100644 --- a/Builds/MSVC/VS2013/Fractorium.vcxproj.filters +++ b/Builds/MSVC/VS2013/Fractorium.vcxproj.filters @@ -247,6 +247,15 @@ MainWindows + + Generated Files\Debug + + + Generated Files\Release + + + Generated Files\ReleaseNvidia + @@ -347,6 +356,9 @@ Widgets + + Widgets + diff --git a/Source/Fractorium/DoubleSpinBoxTableItemDelegate.h b/Source/Fractorium/DoubleSpinBoxTableItemDelegate.h new file mode 100644 index 0000000..5830b6c --- /dev/null +++ b/Source/Fractorium/DoubleSpinBoxTableItemDelegate.h @@ -0,0 +1,91 @@ +#pragma once + +#include "FractoriumPch.h" +#include "DoubleSpinBox.h" + +/// +/// DoubleSpinBoxTableItemDelegate class. +/// + +/// +/// Used for showing a DoubleSpinBox on the cell of a QTableView when the user enters the cell to edit it. +/// +class DoubleSpinBoxTableItemDelegate + : public QItemDelegate +{ + Q_OBJECT +public: + /// + /// Constructor that assigns a DoubleSpinBox. + /// + /// The DoubleSpinBox to use throughought the life of the object + /// The parent widget. Default: nullptr. + explicit DoubleSpinBoxTableItemDelegate(DoubleSpinBox* spinBox, QObject* parent = nullptr) + : QItemDelegate(parent), + m_SpinBox(spinBox) + { + } + + /// + /// Re-parent and return the DoubleSpinBox to display when the user clicks on a cell and it enters edit mode. + /// The re-parenting is done so that the DoubleSpinBox appears directly on top of the cell. + /// + /// The parent cell + /// Unused + /// unused + /// The DoubleSpinBox member + QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override + { + m_SpinBox->setParent(parent); + + return m_SpinBox; + } + + /// + /// Prevent DoubleSpinBox control from being destroyed when the cell loses focus. + /// + /// Unused + /// Unused + void destroyEditor(QWidget* editor, const QModelIndex& index) const override + { + } + + /// + /// Set the value of the DoubleSpinBox as well as its tableindex property. + /// + /// Unused + /// Unused + void setEditorData(QWidget* editor, const QModelIndex& index) const override + { + QPoint p(index.row(), index.column()); + auto value = index.model()->data(index, Qt::EditRole).toDouble(); + + m_SpinBox->setProperty("tableindex", p); + m_SpinBox->setValue(value); + } + + /// + /// Set the cell in the model to the value of the DoubleSpinBox. + /// + /// Unused + /// The model whose value will be set + /// The cell index of the model + void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const override + { + model->setData(index, m_SpinBox->value(), Qt::EditRole); + } + + /// + /// Set the geometry of the DoubleSpinBox to match the cell being edited. + /// + /// The DoubleSpinBox member + /// Contains the rectangle to be used for the geometry of the DoubleSpinBox + /// Unused + void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override + { + editor->setGeometry(option.rect); + } + +private: + DoubleSpinBox* m_SpinBox; +}; \ No newline at end of file diff --git a/Source/Fractorium/Fractorium.cpp b/Source/Fractorium/Fractorium.cpp index 43ed366..9cf142a 100644 --- a/Source/Fractorium/Fractorium.cpp +++ b/Source/Fractorium/Fractorium.cpp @@ -1,6 +1,11 @@ #include "FractoriumPch.h" #include "Fractorium.h" +// X11 headers on Linux define this, causing build errors. +#ifdef KeyRelease + #undef KeyRelease +#endif + /// /// Constructor that initializes the entire program. /// The setup process is very lengthy because it requires many custom modifications @@ -584,16 +589,15 @@ QString Fractorium::SetupSaveFolderDialog() /// /// Thin wrapper around QMessageBox::critical() to allow it to be invoked from another thread. /// +/// The title of the message box +/// The text displayed on the message box +/// True if running on another thread, else false. Default: false. void Fractorium::ShowCritical(const QString& title, const QString& text, bool invokeRequired) { if (!invokeRequired) - { QMessageBox::critical(this, title, text); - } else - { QMetaObject::invokeMethod(this, "ShowCritical", Qt::QueuedConnection, Q_ARG(const QString&, title), Q_ARG(const QString&, text), Q_ARG(bool, false)); - } } /// @@ -730,33 +734,58 @@ void Fractorium::SetTabOrders() /// If shift is held down, reverse the logic. /// Resets the rendering process. /// +/// The QTableWidget or QTableView whose row will be toggled /// The index of the row that was double clicked -void Fractorium::ToggleTableRow(TableWidget* table, int logicalIndex) +void Fractorium::ToggleTableRow(QTableView* table, int logicalIndex) { bool allZero = true; - int cols = table->columnCount(); + auto model = table->model(); + int cols = model->columnCount(); bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier); + auto tableWidget = dynamic_cast(table); - for (int i = 0; i < cols; i++) + if (tableWidget) { - if (auto* spinBox = dynamic_cast(table->cellWidget(logicalIndex, i))) + for (int i = 0; i < cols; i++) { - if (!IsNearZero(spinBox->value())) + if (auto* spinBox = dynamic_cast(tableWidget->cellWidget(logicalIndex, i))) + { + if (!IsNearZero(spinBox->value())) + { + allZero = false; + break; + } + } + } + + if (shift) + allZero = !allZero; + + double val = allZero ? 1.0 : 0.0; + + for (int i = 0; i < cols; i++) + if (auto* spinBox = dynamic_cast(tableWidget->cellWidget(logicalIndex, i))) + spinBox->setValue(val); + } + else + { + for (int i = 0; i < cols; i++) + { + if (!IsNearZero(model->data(model->index(logicalIndex, i, QModelIndex())).toDouble())) { allZero = false; break; } } + + if (shift) + allZero = !allZero; + + double val = allZero ? 1.0 : 0.0; + + for (int i = 0; i < cols; i++) + model->setData(model->index(logicalIndex, i), val, Qt::EditRole); } - - if (shift) - allZero = !allZero; - - double val = allZero ? 1.0 : 0.0; - - for (int i = 0; i < cols; i++) - if (auto* spinBox = dynamic_cast(table->cellWidget(logicalIndex, i))) - spinBox->setValue(val); } /// @@ -766,82 +795,61 @@ void Fractorium::ToggleTableRow(TableWidget* table, int logicalIndex) /// If shift is held down, reverse the logic. /// Resets the rendering process. /// +/// The QTableWidget or QTableView whose column will be toggled /// The index of the column that was double clicked -void Fractorium::ToggleTableCol(TableWidget* table, int logicalIndex) +void Fractorium::ToggleTableCol(QTableView* table, int logicalIndex) { bool allZero = true; - int rows = table->rowCount(); + auto model = table->model(); + int rows = model->rowCount(); bool shift = QGuiApplication::keyboardModifiers().testFlag(Qt::ShiftModifier); + + auto tableWidget = dynamic_cast(table); - for (int i = 0; i < rows; i++) + if (tableWidget) { - if (auto* spinBox = dynamic_cast(table->cellWidget(i, logicalIndex))) + for (int i = 0; i < rows; i++) { - if (!IsNearZero(spinBox->value())) + if (auto* spinBox = dynamic_cast(tableWidget->cellWidget(i, logicalIndex))) + { + if (!IsNearZero(spinBox->value())) + { + allZero = false; + break; + } + } + } + + if (shift) + allZero = !allZero; + + double val = allZero ? 1.0 : 0.0; + + for (int i = 0; i < rows; i++) + if (auto* spinBox = dynamic_cast(tableWidget->cellWidget(i, logicalIndex))) + spinBox->setValue(val); + } + else + { + for (int i = 0; i < rows; i++) + { + if (!IsNearZero(model->data(model->index(i, logicalIndex, QModelIndex())).toDouble())) { allZero = false; break; } } + + if (shift) + allZero = !allZero; + + double val = allZero ? 1.0 : 0.0; + + for (int i = 0; i < rows; i++) + model->setData(model->index(i, logicalIndex), val, Qt::EditRole); } - - if (shift) - allZero = !allZero; - - double val = allZero ? 1.0 : 0.0; - - for (int i = 0; i < rows; i++) - if (auto* spinBox = dynamic_cast(table->cellWidget(i, logicalIndex))) - spinBox->setValue(val); } -/// -/// This is no longer needed and was used to compensate for a different bug -/// however the code is interesting, so keep it around for possible future use. -/// This was used to correct a rotation bug where matrix rotation comes out in the wrong direction -/// if x1, y1 (a & d) are on the left side of the line from 0,0 to -/// x2, y2 (b, e). In that case, the angle must be flipped. In order -/// to determine which side of the line it's on, create a mat2 -/// and find its determinant. Values > 0 are on the left side of the line. -/// -/// The affine. -/// -int Fractorium::FlipDet(Affine2D& affine) -{ - float x1 = affine.A(); - float y1 = affine.D(); - float x2 = affine.B(); - float y2 = affine.E(); - - //Just make the other end of the line be the center of the circle. - glm::mat2 mat( 0 - x1, 0 - y1,//Col 0. - x2 - x1, y2 - y1);//Col 1. - - return (glm::determinant(mat) > 0) ? -1 : 1; -} - -//template//See note at the end of Fractorium.h -//void Fractorium::SetupSpinner(QTableWidget* table, const QObject* receiver, int& row, int col, spinType*& spinBox, int height, valType min, valType max, valType step, const char* signal, const char* slot, bool incRow, valType val, valType doubleClickZero, valType doubleClickNonZero) -//{ -// spinBox = new spinType(table, height, step); -// spinBox->setRange(min, max); -// spinBox->setValue(val); -// table->setCellWidget(row, col, spinBox); -// -// if (string(signal) != "" && string(slot) != "") -// connect(spinBox, signal, receiver, slot, connectionType); -// -// if (doubleClickNonZero != -999 && doubleClickZero != -999) -// { -// spinBox->DoubleClick(true); -// spinBox->DoubleClickZero((valType)doubleClickZero); -// spinBox->DoubleClickNonZero((valType)doubleClickNonZero); -// } -// -// if (incRow) -// row++; -//} - template class FractoriumEmberController; #ifdef DO_DOUBLE diff --git a/Source/Fractorium/Fractorium.h b/Source/Fractorium/Fractorium.h index f4d8d51..93465d9 100644 --- a/Source/Fractorium/Fractorium.h +++ b/Source/Fractorium/Fractorium.h @@ -11,6 +11,7 @@ #include "OptionsDialog.h" #include "AboutDialog.h" #include "CurvesGraphicsView.h" +#include "DoubleSpinBoxTableItemDelegate.h" /// /// Fractorium class. @@ -258,6 +259,7 @@ public slots: void OnRandomXaosButtonClicked(bool checked); void OnXaosRowDoubleClicked(int logicalIndex); void OnXaosColDoubleClicked(int logicalIndex); + void OnXaosTableModelDataChanged(const QModelIndex& indexA, const QModelIndex& indexB); //Palette. void OnPaletteFilenameComboChanged(const QString& text); @@ -282,7 +284,6 @@ public: static void SetupAffineSpinner(QTableWidget* table, const QObject* receiver, int row, int col, DoubleSpinBox*& spinBox, int height, double min, double max, double step, double prec, const char* signal, const char* slot); static void SetupCombo(QTableWidget* table, const QObject* receiver, int& row, int col, StealthComboBox*& comboBox, const vector& vals, const char* signal, const char* slot, Qt::ConnectionType connectionType = Qt::QueuedConnection); static void SetFixedTableHeader(QHeaderView* header, QHeaderView::ResizeMode mode = QHeaderView::Fixed); - static int FlipDet(Affine2D& affine); protected: virtual bool eventFilter(QObject* o, QEvent* e) override; @@ -306,8 +307,8 @@ private: void InitLibraryUI(); void SetTabOrders(); - void ToggleTableRow(TableWidget* table, int logicalIndex); - void ToggleTableCol(TableWidget* table, int logicalIndex); + void ToggleTableRow(QTableView* table, int logicalIndex); + void ToggleTableCol(QTableView* table, int logicalIndex); //Embers. bool HaveFinal(); @@ -421,6 +422,11 @@ private: DoubleSpinBox* m_PreSpins[6]; DoubleSpinBox* m_PostSpins[6]; + //Xaos. + DoubleSpinBox* m_XaosSpinBox; + QStandardItemModel* m_XaosTableModel; + DoubleSpinBoxTableItemDelegate* m_XaosTableItemDelegate; + //Palette. SpinBox* m_PaletteHueSpin; SpinBox* m_PaletteSaturationSpin; @@ -457,6 +463,3 @@ private: unique_ptr m_Controller; Ui::FractoriumClass ui; }; - -//template void Fractorium::SetupSpinner (QTableWidget* table, const QObject* receiver, int& row, int col, SpinBox*& spinBox, int height, int min, int max, int step, const char* signal, const char* slot, bool incRow, int val, int doubleClickZero, int doubleClickNonZero); -//template void Fractorium::SetupSpinner(QTableWidget* table, const QObject* receiver, int& row, int col, DoubleSpinBox*& spinBox, int height, double min, double max, double step, const char* signal, const char* slot, bool incRow, double val, double doubleClickZero, double doubleClickNonZero); diff --git a/Source/Fractorium/Fractorium.ui b/Source/Fractorium/Fractorium.ui index 12e5630..84d12aa 100644 --- a/Source/Fractorium/Fractorium.ui +++ b/Source/Fractorium/Fractorium.ui @@ -2644,8 +2644,8 @@ SpinBox 0 0 - 245 - 747 + 118 + 618 @@ -4301,8 +4301,8 @@ SpinBox 0 0 - 245 - 682 + 133 + 52 @@ -4717,7 +4717,7 @@ SpinBox 4 - + 0 @@ -4766,13 +4766,13 @@ SpinBox QAbstractScrollArea::AdjustToContents - false + true - QAbstractItemView::NoEditTriggers + QAbstractItemView::CurrentChanged|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked - false + true false @@ -4784,7 +4784,7 @@ SpinBox false - QAbstractItemView::NoSelection + QAbstractItemView::SingleSelection QAbstractItemView::ScrollPerPixel @@ -4804,14 +4804,8 @@ SpinBox false - - 3 - - - false - - true + false 35 @@ -4822,14 +4816,8 @@ SpinBox 35 - - false - - - false - - true + false 22 @@ -4840,44 +4828,6 @@ SpinBox 22 - - false - - - - - - - - - F1 - - - - - F2 - - - - - F3 - - - - - - - - - - - - - - - - - @@ -6181,7 +6131,7 @@ SpinBox CurvesGraphicsView QGraphicsView -
curvesgraphicsview.h
+
CurvesGraphicsView.h
diff --git a/Source/Fractorium/FractoriumEmberController.h b/Source/Fractorium/FractoriumEmberController.h index 5ac75de..25cce67 100644 --- a/Source/Fractorium/FractoriumEmberController.h +++ b/Source/Fractorium/FractoriumEmberController.h @@ -189,7 +189,7 @@ public: //Xaos. virtual void FillXaos() { } virtual QString MakeXaosNameString(uint i) { return ""; } - virtual void XaosChanged(DoubleSpinBox* sender) { } + virtual void XaosChanged(int x, int y, double val) { } virtual void ClearXaos() { } virtual void RandomXaos() { } @@ -422,7 +422,7 @@ public: //Xforms Xaos. virtual void FillXaos() override; virtual QString MakeXaosNameString(uint i) override; - virtual void XaosChanged(DoubleSpinBox* sender) override; + virtual void XaosChanged(int x, int y, double val) override; virtual void ClearXaos() override; virtual void RandomXaos() override; diff --git a/Source/Fractorium/FractoriumPch.h b/Source/Fractorium/FractoriumPch.h index bfb9f72..c9fba54 100644 --- a/Source/Fractorium/FractoriumPch.h +++ b/Source/Fractorium/FractoriumPch.h @@ -42,6 +42,7 @@ #include #include #include +#include #include "glm/glm.hpp" #include "glm/gtc/matrix_transform.hpp" diff --git a/Source/Fractorium/FractoriumXaos.cpp b/Source/Fractorium/FractoriumXaos.cpp index df3efce..3235056 100644 --- a/Source/Fractorium/FractoriumXaos.cpp +++ b/Source/Fractorium/FractoriumXaos.cpp @@ -6,15 +6,25 @@ ///
void Fractorium::InitXaosUI() { - ui.XaosTable->verticalHeader()->setVisible(true); - ui.XaosTable->horizontalHeader()->setVisible(true); - ui.XaosTable->verticalHeader()->setSectionsClickable(true); - ui.XaosTable->horizontalHeader()->setSectionsClickable(true); + int spinHeight = 20; + ui.XaosTableView->verticalHeader()->setSectionsClickable(true); + ui.XaosTableView->horizontalHeader()->setSectionsClickable(true); + + m_XaosSpinBox = new DoubleSpinBox(nullptr, spinHeight, 0.1); + m_XaosSpinBox->setFixedWidth(35); + m_XaosSpinBox->DoubleClick(true); + m_XaosSpinBox->DoubleClickZero(1); + m_XaosSpinBox->DoubleClickNonZero(0); + + m_XaosTableModel = nullptr; + m_XaosTableItemDelegate = new DoubleSpinBoxTableItemDelegate(m_XaosSpinBox, this); + + connect(m_XaosSpinBox, SIGNAL(valueChanged(double)), this, SLOT(OnXaosChanged(double)), Qt::QueuedConnection); connect(ui.ClearXaosButton, SIGNAL(clicked(bool)), this, SLOT(OnClearXaosButtonClicked(bool)), Qt::QueuedConnection); connect(ui.RandomXaosButton, SIGNAL(clicked(bool)), this, SLOT(OnRandomXaosButtonClicked(bool)), Qt::QueuedConnection); - connect(ui.XaosTable->verticalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(OnXaosRowDoubleClicked(int)), Qt::QueuedConnection); - connect(ui.XaosTable->horizontalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(OnXaosColDoubleClicked(int)), Qt::QueuedConnection); + connect(ui.XaosTableView->verticalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(OnXaosRowDoubleClicked(int)), Qt::QueuedConnection); + connect(ui.XaosTableView->horizontalHeader(), SIGNAL(sectionDoubleClicked(int)), this, SLOT(OnXaosColDoubleClicked(int)), Qt::QueuedConnection); } /// @@ -25,11 +35,14 @@ void FractoriumEmberController::FillXaos() { for (int i = 0, count = int(XformCount()); i < count; i++) { - auto* xform = m_Ember.GetXform(i); - - for (int j = 0; j < count; j++) - if (auto* spinBox = dynamic_cast(m_Fractorium->ui.XaosTable->cellWidget(i, j))) - spinBox->SetValueStealth(xform->Xaos(j)); + if (auto xform = m_Ember.GetXform(i)) + { + for (int j = 0; j < count; j++) + { + QModelIndex index = m_Fractorium->m_XaosTableModel->index(i, j, QModelIndex()); + m_Fractorium->m_XaosTableModel->setData(index, xform->Xaos(j)); + } + } } } @@ -67,22 +80,34 @@ QString FractoriumEmberController::MakeXaosNameString(uint i) /// /// Set the xaos value. /// Called when any xaos spinner is changed. +/// It actually gets called multiple times as the user clicks around the +/// xaos table due to how QTableView passes events to and from its model. +/// To filter out spurrious events, the value is checked against the existing +/// xaos value. /// Resets the rendering process. /// /// The DoubleSpinBox that triggered this event template -void FractoriumEmberController::XaosChanged(DoubleSpinBox* sender) +void FractoriumEmberController::XaosChanged(int x, int y, double val) { - auto p = sender->property("tableindex").toPoint(); - - if (auto* xform = m_Ember.GetXform(p.x())) - Update([&] { xform->SetXaos(p.y(), sender->value()); }); + if (Xform* xform = m_Ember.GetXform(x)) + if (!IsClose(val, xform->Xaos(y), 1e-10))//Ensure it actually changed. + Update([&] { xform->SetXaos(y, val); }); } void Fractorium::OnXaosChanged(double d) { if (auto* senderSpinBox = dynamic_cast(this->sender())) - m_Controller->XaosChanged(senderSpinBox); + { + auto p = senderSpinBox->property("tableindex").toPoint(); + + m_Controller->XaosChanged(p.x(), p.y(), d); + } +} + +void Fractorium::OnXaosTableModelDataChanged(const QModelIndex& indexA, const QModelIndex& indexB) +{ + m_Controller->XaosChanged(indexA.row(), indexA.column(), indexA.data().toDouble()); } /// @@ -90,57 +115,37 @@ void Fractorium::OnXaosChanged(double d) /// void Fractorium::FillXaosTable() { - int spinHeight = 20; int count = int(m_Controller->XformCount()); - QWidget* w = nullptr; - QString lbl("lbl"); + QStringList hl, vl; + auto oldModel = m_XaosTableModel; - ui.XaosTable->blockSignals(true); - ui.XaosTable->setRowCount(count);//This will grow or shrink the number of rows and call the destructor for previous DoubleSpinBoxes. - ui.XaosTable->setColumnCount(count); + hl.reserve(count); + vl.reserve(count); + m_XaosTableModel = new QStandardItemModel(count, count, this); + connect(m_XaosTableModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), SLOT(OnXaosTableModelDataChanged(QModelIndex, QModelIndex))); + ui.XaosTableView->blockSignals(true); for (int i = 0; i < count; i++) { - for (int j = 0; j < count; j++) - { - QPoint p(i, j); - DoubleSpinBox* spinBox = new DoubleSpinBox(ui.XaosTable, spinHeight, 0.1); + auto s = QString::number(i + 1); - spinBox->setFixedWidth(35); - spinBox->DoubleClick(true); - spinBox->DoubleClickZero(1); - spinBox->DoubleClickNonZero(0); - spinBox->setProperty("tableindex", p); - ui.XaosTable->setCellWidget(i, j, spinBox); - - auto wp = ui.XaosTable->item(i, j); - - if (wp) - wp->setTextAlignment(Qt::AlignCenter); - - connect(spinBox, SIGNAL(valueChanged(double)), this, SLOT(OnXaosChanged(double)), Qt::QueuedConnection); - - if (i == 0 && j == 0) - w = spinBox; - else - w = SetTabOrder(this, w, spinBox); - } + hl.push_back("F" + s); + vl.push_back("T" + s); } + + m_XaosTableModel->setHorizontalHeaderLabels(hl); + m_XaosTableModel->setVerticalHeaderLabels(vl); + + ui.XaosTableView->setModel(m_XaosTableModel); + ui.XaosTableView->setItemDelegate(m_XaosTableItemDelegate); + ui.XaosTableView->resizeRowsToContents(); + ui.XaosTableView->resizeColumnsToContents(); + + SetTabOrder(this, ui.ClearXaosButton, ui.RandomXaosButton); + ui.XaosTableView->blockSignals(false); - for (int i = 0; i < count; i++) - { - ui.XaosTable->setHorizontalHeaderItem(i, new QTableWidgetItem("F" + QString::number(i + 1))); - ui.XaosTable->setVerticalHeaderItem(i, new QTableWidgetItem("T" + QString::number(i + 1))); - ui.XaosTable->horizontalHeader()->setSectionResizeMode(i, QHeaderView::ResizeToContents); - ui.XaosTable->verticalHeader()->setSectionResizeMode(i, QHeaderView::ResizeToContents); - } - - ui.XaosTable->resizeRowsToContents(); - ui.XaosTable->resizeColumnsToContents(); - - w = SetTabOrder(this, w, ui.ClearXaosButton); - w = SetTabOrder(this, w, ui.RandomXaosButton); - ui.XaosTable->blockSignals(false); + if (oldModel) + delete oldModel; } /// @@ -193,7 +198,7 @@ void Fractorium::OnRandomXaosButtonClicked(bool checked) { m_Controller->RandomX /// The index of the row that was double clicked void Fractorium::OnXaosRowDoubleClicked(int logicalIndex) { - ToggleTableRow(ui.XaosTable, logicalIndex); + ToggleTableRow(ui.XaosTableView, logicalIndex); } /// @@ -203,7 +208,7 @@ void Fractorium::OnXaosRowDoubleClicked(int logicalIndex) /// The index of the column that was double clicked void Fractorium::OnXaosColDoubleClicked(int logicalIndex) { - ToggleTableCol(ui.XaosTable, logicalIndex); + ToggleTableCol(ui.XaosTableView, logicalIndex); } template class FractoriumEmberController; diff --git a/Source/Fractorium/FractoriumXformsVariations.cpp b/Source/Fractorium/FractoriumXformsVariations.cpp index cae22a7..69f1a70 100644 --- a/Source/Fractorium/FractoriumXformsVariations.cpp +++ b/Source/Fractorium/FractoriumXformsVariations.cpp @@ -18,6 +18,7 @@ void Fractorium::InitXformsVariationsUI() //Setting dimensions in the designer with a layout is futile, so must hard code here. tree->setColumnWidth(0, 160); tree->setColumnWidth(1, 23); + //tree->setAttribute(Qt::WA_PaintOnScreen); } /// diff --git a/Source/Fractorium/SpinBox.cpp b/Source/Fractorium/SpinBox.cpp index 13d05a4..04e86d7 100644 --- a/Source/Fractorium/SpinBox.cpp +++ b/Source/Fractorium/SpinBox.cpp @@ -23,6 +23,7 @@ SpinBox::SpinBox(QWidget* p, int h, int step) m_SmallStep = 1; setSingleStep(step); setFrame(false); + //setAttribute(Qt::WA_PaintOnScreen); setButtonSymbols(QAbstractSpinBox::NoButtons); setFocusPolicy(Qt::StrongFocus); setMinimumHeight(h);//setGeometry() has no effect, so set both of these instead.