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/Builds/QtCreator/Fractorium/Fractorium.pro b/Builds/QtCreator/Fractorium/Fractorium.pro index 813a15c..3e0a3be 100644 --- a/Builds/QtCreator/Fractorium/Fractorium.pro +++ b/Builds/QtCreator/Fractorium/Fractorium.pro @@ -73,7 +73,8 @@ HEADERS += \ ../../../Source/EmberCommon/EmberCommon.h \ ../../../Source/EmberCommon/JpegUtils.h \ ../../../Source/EmberCommon/EmberCommonPch.h \ - ../../../Source/Fractorium/FractoriumCommon.h + ../../../Source/Fractorium/FractoriumCommon.h \ + ../../../Source/Fractorium/DoubleSpinBoxTableItemDelegate.h FORMS += \ ../../../Source/Fractorium/AboutDialog.ui \ diff --git a/Source/Fractorium/DoubleSpinBox.cpp b/Source/Fractorium/DoubleSpinBox.cpp index 17115b5..d9fe1f1 100644 --- a/Source/Fractorium/DoubleSpinBox.cpp +++ b/Source/Fractorium/DoubleSpinBox.cpp @@ -23,7 +23,6 @@ DoubleSpinBox::DoubleSpinBox(QWidget* p, int h, double step) m_SmallStep = step / 10.0; setSingleStep(step); setFrame(false); - //setAttribute(Qt::WA_PaintOnScreen); setButtonSymbols(QAbstractSpinBox::NoButtons); setFocusPolicy(Qt::StrongFocus); setMinimumHeight(h);//setGeometry() has no effect, so must set both of these instead. 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;